diff --git a/contracts/Lens/PoolLens.sol b/contracts/Lens/PoolLens.sol index 86c896839..c07aea248 100644 --- a/contracts/Lens/PoolLens.sol +++ b/contracts/Lens/PoolLens.sol @@ -136,12 +136,22 @@ contract PoolLens is ExponentialNoError, TimeManagerV8 { BadDebt[] badDebts; } + /// @notice Address of the core pool comptroller (all markets are returned for this pool, including paused ones) + address public immutable corePoolComptroller; + /** * @param timeBased_ A boolean indicating whether the contract is based on time or block. * @param blocksPerYear_ The number of blocks per year + * @param corePoolComptroller_ The address of the core pool comptroller * @custom:oz-upgrades-unsafe-allow constructor */ - constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) {} + constructor( + bool timeBased_, + uint256 blocksPerYear_, + address corePoolComptroller_ + ) TimeManagerV8(timeBased_, blocksPerYear_) { + corePoolComptroller = corePoolComptroller_; + } /** * @notice Queries the user's supply/borrow balances in vTokens @@ -250,7 +260,7 @@ contract PoolLens is ExponentialNoError, TimeManagerV8 { address account, address comptrollerAddress ) external view returns (RewardSummary[] memory) { - VToken[] memory markets = ComptrollerInterface(comptrollerAddress).getAllMarkets(); + VToken[] memory markets = _getMarkets(ComptrollerInterface(comptrollerAddress)); RewardsDistributor[] memory rewardsDistributors = ComptrollerViewInterface(comptrollerAddress) .getRewardDistributors(); RewardSummary[] memory rewardSummary = new RewardSummary[](rewardsDistributors.length); @@ -276,9 +286,9 @@ contract PoolLens is ExponentialNoError, TimeManagerV8 { function getPoolBadDebt(address comptrollerAddress) external view returns (BadDebtSummary memory) { uint256 totalBadDebtUsd; - // Get every market in the pool + // Get every listed market in the pool ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress); - VToken[] memory markets = comptroller.getAllMarkets(); + VToken[] memory markets = _getMarkets(ComptrollerInterface(comptrollerAddress)); ResilientOracleInterface priceOracle = comptroller.oracle(); BadDebt[] memory badDebts = new BadDebt[](markets.length); @@ -344,7 +354,7 @@ contract PoolLens is ExponentialNoError, TimeManagerV8 { // Get tokens in the Pool ComptrollerInterface comptrollerInstance = ComptrollerInterface(venusPool.comptroller); - VToken[] memory vTokens = comptrollerInstance.getAllMarkets(); + VToken[] memory vTokens = _getMarkets(comptrollerInstance); VTokenMetadata[] memory vTokenMetadataItems = vTokenMetadataAll(vTokens); @@ -453,6 +463,37 @@ contract PoolLens is ExponentialNoError, TimeManagerV8 { }); } + /** + * @notice Returns markets from a comptroller. For the core pool, all markets are returned. + * For other pools, markets with zero internalCash are filtered. + * @param comptroller The comptroller to query + * @return An array of VToken addresses + */ + function _getMarkets(ComptrollerInterface comptroller) internal view returns (VToken[] memory) { + VToken[] memory allMarkets = comptroller.getAllMarkets(); + + if (address(comptroller) == corePoolComptroller) { + return allMarkets; + } + + // Single-loop filter: pack active markets to the front of allMarkets + uint256 count; + uint256 len = allMarkets.length; + for (uint256 i; i < len; ++i) { + if (allMarkets[i].internalCash() > 0) { + allMarkets[count] = allMarkets[i]; + ++count; + } + } + + // Trim the array to the active count + assembly { + mstore(allMarkets, count) + } + + return allMarkets; + } + function _calculateNotDistributedAwards( address account, VToken[] memory markets, diff --git a/deploy/007-deploy-pool-lens.ts b/deploy/007-deploy-pool-lens.ts index 0c204f7ef..45ec16fb3 100644 --- a/deploy/007-deploy-pool-lens.ts +++ b/deploy/007-deploy-pool-lens.ts @@ -10,14 +10,36 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { isTimeBased, blocksPerYear } = getBlockOrTimestampBasedDeploymentInfo(hre.getNetworkName()); - await deploy("PoolLens", { + const corePoolComptroller = await deployments.get("Comptroller_Core"); + const constructorArgs = [isTimeBased, blocksPerYear, corePoolComptroller.address]; + + const poolLens = await deploy("PoolLens", { from: deployer, - args: [isTimeBased, blocksPerYear], + args: constructorArgs, log: true, autoMine: true, + skipIfAlreadyDeployed: true, }); + + if (poolLens.newlyDeployed) { + console.log("Verifying PoolLens..."); + try { + await hre.run("verify:verify", { + address: poolLens.address, + constructorArguments: constructorArgs, + }); + console.log("PoolLens verified successfully"); + } catch (error: any) { + if (error.message.includes("Already Verified")) { + console.log("PoolLens already verified"); + } else { + console.error("Verification failed:", error.message); + } + } + } }; func.tags = ["PoolLens", "il"]; +func.skip = async (hre: HardhatRuntimeEnvironment) => !hre.network.live; export default func; diff --git a/deployments/arbitrumone.json b/deployments/arbitrumone.json index 294f1acd9..9281c82d3 100644 --- a/deployments/arbitrumone.json +++ b/deployments/arbitrumone.json @@ -5825,7 +5825,7 @@ ] }, "PoolLens": { - "address": "0x53F34FF95367B2A4542461a6A63fD321F8da22AD", + "address": "0x7603e9aD2b5f758C8eb8480Ed9Cb1509BeDB126c", "abi": [ { "inputs": [ @@ -5838,6 +5838,11 @@ "internalType": "uint256", "name": "blocksPerYear_", "type": "uint256" + }, + { + "internalType": "address", + "name": "corePoolComptroller_", + "type": "address" } ], "stateMutability": "nonpayable", @@ -5866,6 +5871,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "corePoolComptroller", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { diff --git a/deployments/arbitrumone/PoolLens.json b/deployments/arbitrumone/PoolLens.json index 55b1d5b3d..143cd87dc 100644 --- a/deployments/arbitrumone/PoolLens.json +++ b/deployments/arbitrumone/PoolLens.json @@ -1,5 +1,5 @@ { - "address": "0x53F34FF95367B2A4542461a6A63fD321F8da22AD", + "address": "0x7603e9aD2b5f758C8eb8480Ed9Cb1509BeDB126c", "abi": [ { "inputs": [ @@ -12,6 +12,11 @@ "internalType": "uint256", "name": "blocksPerYear_", "type": "uint256" + }, + { + "internalType": "address", + "name": "corePoolComptroller_", + "type": "address" } ], "stateMutability": "nonpayable", @@ -40,6 +45,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "corePoolComptroller", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -1168,28 +1186,28 @@ "type": "function" } ], - "transactionHash": "0x88a718b91f9f20b981c25fead31331ba69105d32bd094e1bb127ac482c6ceeb2", + "transactionHash": "0x8745a6efaaacd7de866b4203eb83b5c8a67fc6710a8a62de8eb77afb355e9276", "receipt": { "to": null, "from": "0x2A94EAb15be8557e6dDAE87eCeCf69ba58aAE2AD", - "contractAddress": "0x53F34FF95367B2A4542461a6A63fD321F8da22AD", - "transactionIndex": 4, - "gasUsed": "4586413", + "contractAddress": "0x7603e9aD2b5f758C8eb8480Ed9Cb1509BeDB126c", + "transactionIndex": 3, + "gasUsed": "3633673", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xd521f883f4ebf9a4029bad40501cafaeca73f330522f565d6005d8e63432cdd7", - "transactionHash": "0x88a718b91f9f20b981c25fead31331ba69105d32bd094e1bb127ac482c6ceeb2", + "blockHash": "0xe29d01a00ad5569430f4fd31aad0b9588b5b2d1a24f3a72598d0ddc845a392c3", + "transactionHash": "0x8745a6efaaacd7de866b4203eb83b5c8a67fc6710a8a62de8eb77afb355e9276", "logs": [], - "blockNumber": 211879390, - "cumulativeGasUsed": "9680201", + "blockNumber": 447575861, + "cumulativeGasUsed": "3875588", "status": 1, "byzantium": true }, - "args": [true, 0], - "numDeployments": 1, - "solcInputHash": "e010dbbe24a800ab0b08a110710123b2", - "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"timeBased_\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"blocksPerYear_\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidBlocksPerYear\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTimeBasedConfiguration\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"blocksOrSecondsPerYear\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"}],\"name\":\"getAllPools\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockNumberOrTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getPendingRewards\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"distributorAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"rewardTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalRewards\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.PendingReward[]\",\"name\":\"pendingRewards\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.RewardSummary[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getPoolBadDebt\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalBadDebtUsd\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"badDebtUsd\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.BadDebt[]\",\"name\":\"badDebts\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.BadDebtSummary\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolByComptroller\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolRegistryInterface.VenusPool\",\"name\":\"venusPool\",\"type\":\"tuple\"}],\"name\":\"getPoolDataFromVenusPool\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getPoolsSupportedByAsset\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getVTokenForAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isTimeBased\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"vTokenBalances\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalanceCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balanceOfUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenAllowance\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenBalances\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"vTokenBalancesAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalanceCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balanceOfUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenAllowance\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenBalances[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"vTokenMetadata\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"vTokenMetadataAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"vTokenUnderlyingPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"underlyingPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenUnderlyingPrice\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"vTokenUnderlyingPriceAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"underlyingPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenUnderlyingPrice[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"params\":{\"blocksPerYear_\":\"The number of blocks per year\",\"timeBased_\":\"A boolean indicating whether the contract is based on time or block.\"}},\"getAllPools(address)\":{\"details\":\"This function is not designed to be called in a transaction: it is too gas-intensive\",\"params\":{\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"Arrays of all Venus pools' data\"}},\"getBlockNumberOrTimestamp()\":{\"details\":\"Function to simply retrieve block number or block timestamp\",\"returns\":{\"_0\":\"Current block number or block timestamp\"}},\"getPendingRewards(address,address)\":{\"params\":{\"account\":\"The user account.\",\"comptrollerAddress\":\"address\"},\"returns\":{\"_0\":\"Pending rewards array\"}},\"getPoolBadDebt(address)\":{\"params\":{\"comptrollerAddress\":\"Address of the comptroller\"},\"returns\":{\"_0\":\"badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and a break down of bad debt by market\"}},\"getPoolByComptroller(address,address)\":{\"params\":{\"comptroller\":\"The Comptroller implementation address\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"PoolData structure containing the details of the pool\"}},\"getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))\":{\"params\":{\"poolRegistryAddress\":\"Address of the PoolRegistry\",\"venusPool\":\"The VenusPool Object from PoolRegistry\"},\"returns\":{\"_0\":\"Enriched PoolData\"}},\"getPoolsSupportedByAsset(address,address)\":{\"params\":{\"asset\":\"The underlying asset of vToken\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"A list of Comptroller contracts\"}},\"getVTokenForAsset(address,address,address)\":{\"params\":{\"asset\":\"The underlyingAsset of VToken\",\"comptroller\":\"The pool comptroller\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"Address of the vToken\"}},\"vTokenBalances(address,address)\":{\"params\":{\"account\":\"The user Account\",\"vToken\":\"vToken address\"},\"returns\":{\"_0\":\"A struct containing the balances data\"}},\"vTokenBalancesAll(address[],address)\":{\"params\":{\"account\":\"The user Account\",\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"A list of structs containing balances data\"}},\"vTokenMetadata(address)\":{\"params\":{\"vToken\":\"The address of vToken\"},\"returns\":{\"_0\":\"VTokenMetadata struct\"}},\"vTokenMetadataAll(address[])\":{\"params\":{\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"An array of VTokenMetadata structs\"}},\"vTokenUnderlyingPrice(address)\":{\"params\":{\"vToken\":\"vToken address\"},\"returns\":{\"_0\":\"The price data for each asset\"}},\"vTokenUnderlyingPriceAll(address[])\":{\"params\":{\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"An array containing the price data for each asset\"}}},\"title\":\"PoolLens\",\"version\":1},\"userdoc\":{\"errors\":{\"InvalidBlocksPerYear()\":[{\"notice\":\"Thrown when blocks per year is invalid\"}],\"InvalidTimeBasedConfiguration()\":[{\"notice\":\"Thrown when time based but blocks per year is provided\"}]},\"kind\":\"user\",\"methods\":{\"blocksOrSecondsPerYear()\":{\"notice\":\"Stores blocksPerYear if isTimeBased is true else secondsPerYear is stored\"},\"getAllPools(address)\":{\"notice\":\"Queries all pools with addtional details for each of them\"},\"getPendingRewards(address,address)\":{\"notice\":\"Returns the pending rewards for a user for a given pool.\"},\"getPoolBadDebt(address)\":{\"notice\":\"Returns a summary of a pool's bad debt broken down by market\"},\"getPoolByComptroller(address,address)\":{\"notice\":\"Queries the details of a pool identified by Comptroller address\"},\"getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))\":{\"notice\":\"Queries additional information for the pool\"},\"getPoolsSupportedByAsset(address,address)\":{\"notice\":\"Returns all pools that support the specified underlying asset\"},\"getVTokenForAsset(address,address,address)\":{\"notice\":\"Returns vToken holding the specified underlying asset in the specified pool\"},\"isTimeBased()\":{\"notice\":\"Acknowledges if a contract is time based or not\"},\"vTokenBalances(address,address)\":{\"notice\":\"Queries the user's supply/borrow balances in the specified vToken\"},\"vTokenBalancesAll(address[],address)\":{\"notice\":\"Queries the user's supply/borrow balances in vTokens\"},\"vTokenMetadata(address)\":{\"notice\":\"Returns the metadata of VToken\"},\"vTokenMetadataAll(address[])\":{\"notice\":\"Returns the metadata of all VTokens\"},\"vTokenUnderlyingPrice(address)\":{\"notice\":\"Returns the price data for the underlying asset of the specified vToken\"},\"vTokenUnderlyingPriceAll(address[])\":{\"notice\":\"Returns the price data for the underlying assets of the specified vTokens\"}},\"notice\":\"The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be looked up for specific pools and markets: - the vToken balance of a given user; - the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address; - the vToken address in a pool for a given asset; - a list of all pools that support an asset; - the underlying asset price of a vToken; - the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Lens/PoolLens.sol\":\"PoolLens\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"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\",\"keccak256\":\"0x9140dabc466abab21b48b72dbda26736b1183a310d0e677d3719d201df026510\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x359a1ab89b46b9aba7bcad3fb651924baf4893d15153049b9976b0fc9be1358e\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x07e881de3b9f6d2c07909f193f24b96c7fe4ea60013260f3f25aecd8bab3c2f8\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x75097e35253e7fb282ee4d7f27a80eaacfa759923185bf17302a89cbc059c5ef\",\"license\":\"MIT\"},\"@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\"},\"@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 private _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\",\"keccak256\":\"0x0dcf283925f4dddc23ca0ee71d2cb96a9dd6e4cf08061b69fde1697ea39dc514\",\"license\":\"BSD-3-Clause\"},\"@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/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface IProtocolShareReserve {\\n /// @notice it represents the type of vToken income\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION\\n }\\n\\n function updateAssetsState(\\n address comptroller,\\n address asset,\\n IncomeType incomeType\\n ) external;\\n}\\n\",\"keccak256\":\"0x5fddc5b63fdd850b3b5c83576cda50dcb27a205dbb1a23af17d9da0d9f04fa0a\",\"license\":\"BSD-3-Clause\"},\"@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\",\"keccak256\":\"0x57a2bbb9b8e02b1c0a5c0e305fef1328a22db56c3d4b148c362010a6e767243c\",\"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\"},\"@venusprotocol/venus-protocol/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\",\"keccak256\":\"0xd112f60183416ad796093b4a83a80ddc1b8b655965f02ae55ca82e2a0c68f97d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/venus-protocol/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\",\"keccak256\":\"0x5285c875114db2ea2be0b81b65722d5761806217022db733323c4e03365a95e7\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IPrime } from \\\"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\\\";\\n\\nimport { ComptrollerInterface, Action } from \\\"./ComptrollerInterface.sol\\\";\\nimport { ComptrollerStorage } from \\\"./ComptrollerStorage.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"./MaxLoopsLimitHelper.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title Comptroller\\n * @author Venus\\n * @notice The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating,\\n * and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts\\n * with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows\\n * or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing\\n * liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow,\\n * as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the\\n * markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market\\u2019s corresponding liquidation threshold,\\n * the borrow is eligible for liquidation.\\n *\\n * The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed\\n * the `minLiquidatableCollateral` for the `Comptroller`:\\n *\\n * - `healAccount()`: This function is called to seize all of a given user\\u2019s collateral, requiring the `msg.sender` repay a certain percentage\\n * of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed\\n * 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt\\n * and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool.\\n * - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation\\n * incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic\\n * verifying that the repay amount does not exceed the close factor.\\n */\\ncontract Comptroller is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n ComptrollerStorage,\\n ComptrollerInterface,\\n ExponentialNoError,\\n MaxLoopsLimitHelper\\n{\\n // PoolRegistry, immutable to save on gas\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable poolRegistry;\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(VToken indexed vToken, address indexed account);\\n\\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(VToken vToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa);\\n\\n /// @notice Emitted when liquidation threshold is changed by admin\\n event NewLiquidationThreshold(\\n VToken vToken,\\n uint256 oldLiquidationThresholdMantissa,\\n uint256 newLiquidationThresholdMantissa\\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 an action is paused on a market\\n event ActionPausedMarket(VToken vToken, Action action, bool pauseState);\\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 the collateral threshold (in USD) for non-batch liquidations is changed\\n event NewMinLiquidatableCollateral(uint256 oldMinLiquidatableCollateral, uint256 newMinLiquidatableCollateral);\\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 a rewards distributor is added\\n event NewRewardsDistributor(address indexed rewardsDistributor, address indexed rewardToken);\\n\\n /// @notice Emitted when a market is supported\\n event MarketSupported(VToken vToken);\\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 a market\\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\\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 Thrown when collateral factor exceeds the upper bound\\n error InvalidCollateralFactor();\\n\\n /// @notice Thrown when liquidation threshold exceeds the collateral factor\\n error InvalidLiquidationThreshold();\\n\\n /// @notice Thrown when the action is only available to specific sender, but the real sender was different\\n error UnexpectedSender(address expectedSender, address actualSender);\\n\\n /// @notice Thrown when the oracle returns an invalid price for some asset\\n error PriceError(address vToken);\\n\\n /// @notice Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\\n error SnapshotError(address vToken, address user);\\n\\n /// @notice Thrown when the market is not listed\\n error MarketNotListed(address market);\\n\\n /// @notice Thrown when a market has an unexpected comptroller\\n error ComptrollerMismatch();\\n\\n /// @notice Thrown when user is not member of market\\n error MarketNotCollateral(address vToken, address user);\\n\\n /**\\n * @notice Thrown during the liquidation if user's total collateral amount is lower than\\n * a predefined threshold. In this case only batch liquidations (either liquidateAccount\\n * or healAccount) are available.\\n */\\n error MinimalCollateralViolated(uint256 expectedGreaterThan, uint256 actual);\\n error CollateralExceedsThreshold(uint256 expectedLessThanOrEqualTo, uint256 actual);\\n error InsufficientCollateral(uint256 collateralToSeize, uint256 availableCollateral);\\n\\n /// @notice Thrown when the account doesn't have enough liquidity to redeem or borrow\\n error InsufficientLiquidity();\\n\\n /// @notice Thrown when trying to liquidate a healthy account\\n error InsufficientShortfall();\\n\\n /// @notice Thrown when trying to repay more than allowed by close factor\\n error TooMuchRepay();\\n\\n /// @notice Thrown if the user is trying to exit a market in which they have an outstanding debt\\n error NonzeroBorrowBalance();\\n\\n /// @notice Thrown when trying to perform an action that is paused\\n error ActionPaused(address market, Action action);\\n\\n /// @notice Thrown when trying to add a market that is already listed\\n error MarketAlreadyListed(address market);\\n\\n /// @notice Thrown if the supply cap is exceeded\\n error SupplyCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if the borrow cap is exceeded\\n error BorrowCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if delegate approval status is already set to the requested value\\n error DelegationStatusUnchanged();\\n\\n /// @param poolRegistry_ Pool registry address\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n constructor(address poolRegistry_) {\\n ensureNonzeroAddress(poolRegistry_);\\n\\n poolRegistry = poolRegistry_;\\n _disableInitializers();\\n }\\n\\n /**\\n * @param loopLimit Limit for the loops can iterate to avoid the DOS\\n * @param accessControlManager Access control manager contract address\\n */\\n function initialize(uint256 loopLimit, address accessControlManager) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager);\\n\\n _setMaxLoopsLimit(loopLimit);\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation; enabling them to be used as collateral\\n * @param vTokens The list of addresses of the vToken markets to be enabled\\n * @return errors An array of NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketEntered is emitted for each market on success\\n * @custom:error ActionPaused error is thrown if entering any of the markets is paused\\n * @custom:error MarketNotListed error is thrown if any of the markets is not listed\\n * @custom:access Not restricted\\n */\\n function enterMarkets(address[] memory vTokens) external override returns (uint256[] memory) {\\n uint256 len = vTokens.length;\\n\\n uint256[] memory results = new uint256[](len);\\n for (uint256 i; i < len; ++i) {\\n VToken vToken = VToken(vTokens[i]);\\n\\n _addToMarket(vToken, msg.sender);\\n results[i] = NO_ERROR;\\n }\\n\\n return results;\\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 * @custom:event DelegateUpdated emits on success\\n * @custom:error ZeroAddressNotAllowed is thrown when delegate address is zero\\n * @custom:error DelegationStatusUnchanged is thrown if approval status is already set to the requested value\\n * @custom:access Not restricted\\n */\\n function updateDelegate(address delegate, bool approved) external {\\n ensureNonzeroAddress(delegate);\\n if (approvedDelegates[msg.sender][delegate] == approved) {\\n revert DelegationStatusUnchanged();\\n }\\n\\n approvedDelegates[msg.sender][delegate] = approved;\\n emit DelegateUpdated(msg.sender, delegate, approved);\\n }\\n\\n /**\\n * @notice Removes asset from sender's account liquidity calculation; disabling them as collateral\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketExited is emitted on success\\n * @custom:error ActionPaused error is thrown if exiting the market is paused\\n * @custom:error NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function exitMarket(address vTokenAddress) external override returns (uint256) {\\n _checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\\n VToken vToken = VToken(vTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\\n (uint256 tokensHeld, uint256 amountOwed, ) = _safeGetAccountSnapshot(vToken, msg.sender);\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n revert NonzeroBorrowBalance();\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n _checkRedeemAllowed(vTokenAddress, msg.sender, tokensHeld);\\n\\n Market storage marketToExit = markets[address(vToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return 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 // load into memory for faster iteration\\n VToken[] memory userAssetList = accountAssets[msg.sender];\\n uint256 len = userAssetList.length;\\n\\n uint256 assetIndex = len;\\n for (uint256 i; i < len; ++i) {\\n if (userAssetList[i] == vToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n VToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.pop();\\n\\n emit MarketExited(vToken, msg.sender);\\n\\n return NO_ERROR;\\n }\\n\\n /*** Policy Hooks ***/\\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 * @custom:error ActionPaused error is thrown if supplying to this market is paused\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\\n * @custom:access Not restricted\\n */\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external override {\\n _checkActionPauseState(vToken, Action.MINT);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n uint256 supplyCap = supplyCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (supplyCap != type(uint256).max) {\\n uint256 vTokenSupply = VToken(vToken).totalSupply();\\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\\n if (nextTotalSupply > supplyCap) {\\n revert SupplyCapExceeded(vToken, supplyCap);\\n }\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, minter);\\n }\\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external override {\\n _checkActionPauseState(vToken, Action.REDEEM);\\n\\n _checkRedeemAllowed(vToken, redeemer, redeemTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, redeemer);\\n }\\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 if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(redeemer, vToken);\\n }\\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 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 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 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 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 * @custom:error ActionPaused error is thrown if borrowing is paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if there is not enough collateral to borrow\\n * @custom:error BorrowCapExceeded is thrown if the borrow cap will be exceeded should this borrow succeed\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted if vToken is enabled as collateral, otherwise only vToken\\n */\\n /// disable-eslint\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external override {\\n _checkActionPauseState(vToken, Action.BORROW);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (!markets[vToken].accountMembership[borrower]) {\\n // only vTokens may call borrowAllowed if borrower not in market\\n _checkSenderIs(vToken);\\n\\n // attempt to add borrower to the market or revert\\n _addToMarket(VToken(msg.sender), borrower);\\n }\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (oracle.getUnderlyingPrice(vToken) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 borrowCap = borrowCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (borrowCap != type(uint256).max) {\\n uint256 totalBorrows = VToken(vToken).totalBorrows();\\n uint256 badDebt = VToken(vToken).badDebt();\\n uint256 nextTotalBorrows = totalBorrows + borrowAmount + badDebt;\\n if (nextTotalBorrows > borrowCap) {\\n revert BorrowCapExceeded(vToken, borrowCap);\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n borrower,\\n VToken(vToken),\\n 0,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\n }\\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 borrower The account which would borrowed the asset\\n * @custom:error ActionPaused error is thrown if repayments are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:access Not restricted\\n */\\n function preRepayHook(address vToken, address borrower) external override {\\n _checkActionPauseState(vToken, Action.REPAY);\\n\\n oracle.updatePrice(vToken);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\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 borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n * @param skipLiquidityCheck Allows the borrow to be liquidated regardless of the account liquidity\\n * @custom:error ActionPaused error is thrown if liquidations are paused in this market\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor\\n * @custom:error MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations\\n * @custom:error InsufficientShortfall is thrown when trying to liquidate a healthy account\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n */\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external override {\\n // Pause Action.LIQUIDATE on BORROWED TOKEN to prevent liquidating it.\\n // If we want to pause liquidating to vTokenCollateral, we should pause\\n // Action.SEIZE on it\\n _checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(address(vTokenBorrowed));\\n }\\n if (!markets[vTokenCollateral].isListed) {\\n revert MarketNotListed(address(vTokenCollateral));\\n }\\n\\n uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\\n\\n /* Allow accounts to be liquidated if it is a forced liquidation */\\n if (skipLiquidityCheck || isForcedLiquidationEnabled[vTokenBorrowed]) {\\n if (repayAmount > borrowBalance) {\\n revert TooMuchRepay();\\n }\\n return;\\n }\\n\\n /* The borrower must have shortfall and collateral > threshold in order to be liquidatable */\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral <= minLiquidatableCollateral) {\\n /* The liquidator should use either liquidateAccount or healAccount */\\n revert MinimalCollateralViolated(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint256 maxClose = mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance);\\n if (repayAmount > maxClose) {\\n revert TooMuchRepay();\\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 seizerContract Contract that tries to seize the asset (either borrowed vToken or Comptroller)\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @custom:error ActionPaused error is thrown if seizing this type of collateral is paused\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error ComptrollerMismatch error is when seizer contract or seized asset belong to different pools\\n * @custom:access Not restricted\\n */\\n function preSeizeHook(\\n address vTokenCollateral,\\n address seizerContract,\\n address liquidator,\\n address borrower\\n ) external override {\\n // Pause Action.SEIZE on COLLATERAL to prevent seizing it.\\n // If we want to pause liquidating vTokenBorrowed, we should pause\\n // Action.LIQUIDATE on it\\n _checkActionPauseState(vTokenCollateral, Action.SEIZE);\\n\\n Market storage market = markets[vTokenCollateral];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(vTokenCollateral);\\n }\\n\\n if (seizerContract == address(this)) {\\n // If Comptroller is the seizer, just check if collateral's comptroller\\n // is equal to the current address\\n if (address(VToken(vTokenCollateral).comptroller()) != address(this)) {\\n revert ComptrollerMismatch();\\n }\\n } else {\\n // If the seizer is not the Comptroller, check that the seizer is a\\n // listed market, and that the markets' comptrollers match\\n if (!markets[seizerContract].isListed) {\\n revert MarketNotListed(seizerContract);\\n }\\n if (VToken(vTokenCollateral).comptroller() != VToken(seizerContract).comptroller()) {\\n revert ComptrollerMismatch();\\n }\\n }\\n\\n if (!market.accountMembership[borrower]) {\\n revert MarketNotCollateral(vTokenCollateral, borrower);\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vTokenCollateral);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, borrower);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, liquidator);\\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external override {\\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 _checkRedeemAllowed(vToken, src, transferTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, src);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, dst);\\n }\\n }\\n\\n /*** Pool-level operations ***/\\n\\n /**\\n * @notice Seizes all the remaining collateral, makes msg.sender repay the existing\\n * borrows, and treats the rest of the debt as bad debt (for each market).\\n * The sender has to repay a certain percentage of the debt, computed as\\n * collateral / (borrows * liquidationIncentive).\\n * @param user account to heal\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for healing\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function healAccount(address user) external {\\n VToken[] memory userAssets = accountAssets[user];\\n uint256 userAssetsCount = userAssets.length;\\n\\n address liquidator = msg.sender;\\n {\\n ResilientOracleInterface oracle_ = oracle;\\n // We need all user's markets to be fresh for the computations to be correct\\n for (uint256 i; i < userAssetsCount; ++i) {\\n userAssets[i].accrueInterest();\\n oracle_.updatePrice(address(userAssets[i]));\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(user, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n // percentage = collateral / (borrows * liquidation incentive)\\n Exp memory collateral = Exp({ mantissa: snapshot.totalCollateral });\\n Exp memory scaledBorrows = mul_(\\n Exp({ mantissa: snapshot.borrows }),\\n Exp({ mantissa: liquidationIncentiveMantissa })\\n );\\n\\n Exp memory percentage = div_(collateral, scaledBorrows);\\n if (lessThanExp(Exp({ mantissa: MANTISSA_ONE }), percentage)) {\\n revert CollateralExceedsThreshold(scaledBorrows.mantissa, collateral.mantissa);\\n }\\n\\n for (uint256 i; i < userAssetsCount; ++i) {\\n VToken market = userAssets[i];\\n\\n (uint256 tokens, uint256 borrowBalance, ) = _safeGetAccountSnapshot(market, user);\\n uint256 repaymentAmount = mul_ScalarTruncate(percentage, borrowBalance);\\n\\n // Seize the entire collateral\\n if (tokens != 0) {\\n market.seize(liquidator, user, tokens);\\n }\\n // Repay a certain percentage of the borrow, forgive the rest\\n if (borrowBalance != 0) {\\n market.healBorrow(liquidator, user, repaymentAmount);\\n }\\n }\\n }\\n\\n /**\\n * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than\\n * a predefined threshold, and the account collateral can be seized to cover all borrows. If\\n * the collateral is higher than the threshold, use regular liquidations. If the collateral is\\n * below the threshold, and the account is insolvent, use healAccount.\\n * @param borrower the borrower address\\n * @param orders an array of liquidation orders\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation\\n * @custom:error InsufficientCollateral error is thrown when there is not enough collateral to cover the debt\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function liquidateAccount(address borrower, LiquidationOrder[] calldata orders) external {\\n // We will accrue interest and update the oracle prices later during the liquidation\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n // You should use the regular vToken.liquidateBorrow(...) call\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n uint256 collateralToSeize = mul_ScalarTruncate(\\n Exp({ mantissa: liquidationIncentiveMantissa }),\\n snapshot.borrows\\n );\\n if (collateralToSeize >= snapshot.totalCollateral) {\\n // There is not enough collateral to seize. Use healBorrow to repay some part of the borrow\\n // and record bad debt.\\n revert InsufficientCollateral(collateralToSeize, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n uint256 ordersCount = orders.length;\\n\\n _ensureMaxLoops(ordersCount / 2);\\n\\n for (uint256 i; i < ordersCount; ++i) {\\n if (!markets[address(orders[i].vTokenBorrowed)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenBorrowed));\\n }\\n if (!markets[address(orders[i].vTokenCollateral)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenCollateral));\\n }\\n\\n LiquidationOrder calldata order = orders[i];\\n order.vTokenBorrowed.forceLiquidateBorrow(\\n msg.sender,\\n borrower,\\n order.repayAmount,\\n order.vTokenCollateral,\\n true\\n );\\n }\\n\\n VToken[] memory borrowMarkets = accountAssets[borrower];\\n uint256 marketsCount = borrowMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower);\\n require(borrowBalance == 0, \\\"Nonzero borrow balance after liquidation\\\");\\n }\\n }\\n\\n /**\\n * @notice Sets the closeFactor to use when liquidating borrows\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @custom:event Emits NewCloseFactor on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCloseFactor(uint256 newCloseFactorMantissa) external {\\n _checkAccessAllowed(\\\"setCloseFactor(uint256)\\\");\\n require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, \\\"Close factor greater than maximum close factor\\\");\\n require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, \\\"Close factor smaller than minimum close factor\\\");\\n\\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev This function is restricted by the AccessControlManager\\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 * @custom:event Emits NewCollateralFactor when collateral factor is updated\\n * and NewLiquidationThreshold when liquidation threshold is updated\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InvalidCollateralFactor error is thrown when collateral factor is too high\\n * @custom:error InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor\\n * @custom:error PriceError is thrown when the oracle returns an invalid price for the asset\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCollateralFactor(\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external {\\n _checkAccessAllowed(\\\"setCollateralFactor(address,uint256,uint256)\\\");\\n\\n // Verify market is listed\\n Market storage market = markets[address(vToken)];\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Check collateral factor <= 0.9\\n if (newCollateralFactorMantissa > MAX_COLLATERAL_FACTOR_MANTISSA) {\\n revert InvalidCollateralFactor();\\n }\\n\\n // Ensure that liquidation threshold <= 1\\n if (newLiquidationThresholdMantissa > MANTISSA_ONE) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // Ensure that liquidation threshold >= CF\\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n }\\n\\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\\n emit NewLiquidationThreshold(vToken, oldLiquidationThresholdMantissa, newLiquidationThresholdMantissa);\\n }\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev This function is restricted by the AccessControlManager\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @custom:event Emits NewLiquidationIncentive on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external {\\n require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, \\\"liquidation incentive should be greater than 1e18\\\");\\n\\n _checkAccessAllowed(\\\"setLiquidationIncentive(uint256)\\\");\\n\\n // Save current value for use in log\\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\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\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Only callable by the PoolRegistry\\n * @param vToken The address of the market (token) to list\\n * @custom:error MarketAlreadyListed is thrown if the market is already listed in this pool\\n * @custom:access Only PoolRegistry\\n */\\n function supportMarket(VToken vToken) external {\\n _checkSenderIs(poolRegistry);\\n\\n if (markets[address(vToken)].isListed) {\\n revert MarketAlreadyListed(address(vToken));\\n }\\n\\n require(vToken.isVToken(), \\\"Comptroller: Invalid vToken\\\"); // Sanity check to make sure its really a VToken\\n\\n Market storage newMarket = markets[address(vToken)];\\n newMarket.isListed = true;\\n newMarket.collateralFactorMantissa = 0;\\n newMarket.liquidationThresholdMantissa = 0;\\n\\n _addMarket(address(vToken));\\n\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n rewardsDistributors[i].initializeMarket(address(vToken));\\n }\\n\\n emit MarketSupported(vToken);\\n }\\n\\n /**\\n * @notice Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A borrow cap of type(uint256).max corresponds to unlimited borrowing.\\n * @dev Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed\\n until the total borrows amount goes below the new borrow cap\\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 type(uint256).max corresponds to unlimited borrowing.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\\n _checkAccessAllowed(\\\"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 _ensureMaxLoops(numMarkets);\\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 * @notice Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A supply cap of type(uint256).max corresponds to unlimited supply.\\n * @dev Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed\\n until the total supplies amount goes below the new supply cap\\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 type(uint256).max corresponds to unlimited supply.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\\n _checkAccessAllowed(\\\"setMarketSupplyCaps(address[],uint256[])\\\");\\n uint256 vTokensCount = vTokens.length;\\n\\n require(vTokensCount != 0, \\\"invalid number of markets\\\");\\n require(vTokensCount == newSupplyCaps.length, \\\"invalid number of markets\\\");\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Pause/unpause specified actions\\n * @dev This function is restricted by the AccessControlManager\\n * @param marketsList Markets to pause/unpause the actions on\\n * @param actionsList List of action ids to pause/unpause\\n * @param paused The new paused state (true=paused, false=unpaused)\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setActionsPaused(VToken[] calldata marketsList, Action[] calldata actionsList, bool paused) external {\\n _checkAccessAllowed(\\\"setActionsPaused(address[],uint256[],bool)\\\");\\n\\n uint256 marketsCount = marketsList.length;\\n uint256 actionsCount = actionsList.length;\\n\\n _ensureMaxLoops(marketsCount * actionsCount);\\n\\n for (uint256 marketIdx; marketIdx < marketsCount; ++marketIdx) {\\n for (uint256 actionIdx; actionIdx < actionsCount; ++actionIdx) {\\n _setActionPaused(address(marketsList[marketIdx]), actionsList[actionIdx], paused);\\n }\\n }\\n }\\n\\n /**\\n * @notice Set the given collateral threshold for non-batch liquidations. Regular liquidations\\n * will fail if the collateral amount is less than this threshold. Liquidators should use batch\\n * operations like liquidateAccount or healAccount.\\n * @dev This function is restricted by the AccessControlManager\\n * @param newMinLiquidatableCollateral The new min liquidatable collateral (in USD).\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external {\\n _checkAccessAllowed(\\\"setMinLiquidatableCollateral(uint256)\\\");\\n\\n uint256 oldMinLiquidatableCollateral = minLiquidatableCollateral;\\n minLiquidatableCollateral = newMinLiquidatableCollateral;\\n emit NewMinLiquidatableCollateral(oldMinLiquidatableCollateral, newMinLiquidatableCollateral);\\n }\\n\\n /**\\n * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor\\n * contracts with the same rewardToken, and there could be overlaping among them considering the last reward slot (block or second)\\n * @dev Only callable by the admin\\n * @param _rewardsDistributor Address of the RewardDistributor contract to add\\n * @custom:access Only Governance\\n * @custom:event Emits NewRewardsDistributor with distributor address\\n */\\n function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner {\\n require(!rewardsDistributorExists[address(_rewardsDistributor)], \\\"already exists\\\");\\n\\n uint256 rewardsDistributorsLen = rewardsDistributors.length;\\n _ensureMaxLoops(rewardsDistributorsLen + 1);\\n\\n rewardsDistributors.push(_rewardsDistributor);\\n rewardsDistributorExists[address(_rewardsDistributor)] = true;\\n\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n _rewardsDistributor.initializeMarket(address(allMarkets[i]));\\n }\\n\\n emit NewRewardsDistributor(address(_rewardsDistributor), address(_rewardsDistributor.rewardToken()));\\n }\\n\\n /**\\n * @notice Sets a new price oracle for the Comptroller\\n * @dev Only callable by the admin\\n * @param newOracle Address of the new price oracle to set\\n * @custom:event Emits NewPriceOracle on success\\n * @custom:error ZeroAddressNotAllowed is thrown when the new oracle address is zero\\n */\\n function setPriceOracle(ResilientOracleInterface newOracle) external onlyOwner {\\n ensureNonzeroAddress(address(newOracle));\\n\\n ResilientOracleInterface oldOracle = oracle;\\n oracle = newOracle;\\n emit NewPriceOracle(oldOracle, newOracle);\\n }\\n\\n /**\\n * @notice Set the for loop iteration limit to avoid DOS\\n * @param limit Limit for the max loops can execute at a time\\n */\\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Sets the prime token contract for the comptroller\\n * @param _prime Address of the Prime contract\\n */\\n function setPrimeToken(IPrime _prime) external onlyOwner {\\n ensureNonzeroAddress(address(_prime));\\n\\n emit NewPrimeToken(prime, _prime);\\n prime = _prime;\\n }\\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 * @param vTokenBorrowed Borrowed vToken\\n * @param enable Whether to enable forced liquidations\\n */\\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\\n _checkAccessAllowed(\\\"setForcedLiquidation(address,bool)\\\");\\n ensureNonzeroAddress(vTokenBorrowed);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(vTokenBorrowed);\\n }\\n\\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to liquidation threshold requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of liquidation threshold requirements,\\n * @return shortfall Account shortfall below liquidation threshold requirements\\n */\\n function getAccountLiquidity(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getLiquidationThreshold);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to collateral requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of collateral requirements,\\n * @return shortfall Account shortfall below collateral requirements\\n */\\n function getBorrowingPower(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getCollateralFactor);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Hypothetical account liquidity in excess of collateral requirements,\\n * @return shortfall 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 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n account,\\n VToken(vTokenModify),\\n redeemTokens,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\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 markets The list of market addresses\\n */\\n function getAllMarkets() external view override returns (VToken[] memory) {\\n return allMarkets;\\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 /*** Assets You Are In ***/\\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 list with the assets the account has entered\\n */\\n function getAssetsIn(address account) external view returns (VToken[] memory) {\\n VToken[] memory assetsIn = accountAssets[account];\\n\\n return assetsIn;\\n }\\n\\n /**\\n * @notice Returns whether the given account is entered in a given market\\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 market specified, 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 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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return tokensToSeize Number of vTokenCollateral tokens to be seized in a liquidation\\n * @custom:error PriceError if the oracle returns an invalid price\\n */\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view override returns (uint256 error, uint256 tokensToSeize) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint256 priceBorrowedMantissa = _safeGetUnderlyingPrice(VToken(vTokenBorrowed));\\n uint256 priceCollateralMantissa = _safeGetUnderlyingPrice(VToken(vTokenCollateral));\\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 uint256 exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint256 seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n\\n numerator = mul_(Exp({ mantissa: liquidationIncentiveMantissa }), Exp({ mantissa: priceBorrowedMantissa }));\\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\\n ratio = div_(numerator, denominator);\\n\\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\\n\\n return (NO_ERROR, seizeTokens);\\n }\\n\\n /**\\n * @notice Returns reward speed given a vToken\\n * @param vToken The vToken to get the reward speeds for\\n * @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors\\n */\\n function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {\\n uint256 rewardsDistributorsLength = rewardsDistributors.length;\\n rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);\\n for (uint256 i; i < rewardsDistributorsLength; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n address rewardToken = address(rewardsDistributor.rewardToken());\\n rewardSpeeds[i] = RewardSpeeds({\\n rewardToken: rewardToken,\\n supplySpeed: rewardsDistributor.rewardTokenSupplySpeeds(vToken),\\n borrowSpeed: rewardsDistributor.rewardTokenBorrowSpeeds(vToken)\\n });\\n }\\n return rewardSpeeds;\\n }\\n\\n /**\\n * @notice Return all reward distributors for this pool\\n * @return Array of RewardDistributor addresses\\n */\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory) {\\n return rewardsDistributors;\\n }\\n\\n /**\\n * @notice A marker method that returns true for a valid Comptroller contract\\n * @return Always true\\n */\\n function isComptroller() external pure override returns (bool) {\\n return true;\\n }\\n\\n /**\\n * @notice Update the prices of all the tokens associated with the provided account\\n * @param account Address of the account to get associated tokens with\\n */\\n function updatePrices(address account) public {\\n VToken[] memory vTokens = accountAssets[account];\\n uint256 vTokensCount = vTokens.length;\\n\\n ResilientOracleInterface oracle_ = oracle;\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n oracle_.updatePrice(address(vTokens[i]));\\n }\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param market vToken address\\n * @param action Action to check\\n * @return paused True if the action is paused otherwise false\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][action];\\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 */\\n function _addToMarket(VToken vToken, address borrower) internal {\\n _checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = markets[address(vToken)];\\n\\n if (!marketToJoin.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return;\\n }\\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\\n /**\\n * @notice Internal function to validate that a market hasn't already been added\\n * and if it hasn't adds it\\n * @param vToken The market to support\\n */\\n function _addMarket(address vToken) internal {\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n if (allMarkets[i] == VToken(vToken)) {\\n revert MarketAlreadyListed(vToken);\\n }\\n }\\n allMarkets.push(VToken(vToken));\\n marketsCount = allMarkets.length;\\n _ensureMaxLoops(marketsCount);\\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 _setActionPaused(address market, Action action, bool paused) internal {\\n require(markets[market].isListed, \\\"cannot pause a market that is not listed\\\");\\n _actionPaused[market][action] = paused;\\n emit ActionPausedMarket(VToken(market), action, paused);\\n }\\n\\n /**\\n * @dev Internal function to check that vTokens can be safely redeemed for the underlying asset.\\n * @param vToken Address of the vTokens to redeem\\n * @param redeemer Account redeeming the tokens\\n * @param redeemTokens The number of tokens to redeem\\n */\\n function _checkRedeemAllowed(address vToken, address redeemer, uint256 redeemTokens) internal {\\n Market storage market = markets[vToken];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!market.accountMembership[redeemer]) {\\n return;\\n }\\n\\n // Update the prices of tokens\\n updatePrices(redeemer);\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n _getCollateralFactor\\n );\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n }\\n\\n /**\\n * @notice Get the total collateral, weighted collateral, borrow balance, liquidity, shortfall\\n * @param account The account to get the snapshot for\\n * @param weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n * liquidation threshold. Accepts the address of the vToken and returns the weight as Exp.\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getCurrentLiquiditySnapshot(\\n address account,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n return _getHypotheticalLiquiditySnapshot(account, VToken(address(0)), 0, 0, weight);\\n }\\n\\n /**\\n * @notice Determine what the supply/borrow balances 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 weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n liquidation threshold. Accepts the address of the VToken and returns the weight\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getHypotheticalLiquiditySnapshot(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n // For each asset the account is in\\n VToken[] memory assets = accountAssets[account];\\n uint256 assetsCount = assets.length;\\n\\n for (uint256 i; i < assetsCount; ++i) {\\n VToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the vToken\\n (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) = _safeGetAccountSnapshot(\\n asset,\\n account\\n );\\n\\n // Get the normalized price of the asset\\n Exp memory oraclePrice = Exp({ mantissa: _safeGetUnderlyingPrice(asset) });\\n\\n // Pre-compute conversion factors from vTokens -> usd\\n Exp memory vTokenPrice = mul_(Exp({ mantissa: exchangeRateMantissa }), oraclePrice);\\n Exp memory weightedVTokenPrice = mul_(weight(asset), vTokenPrice);\\n\\n // weightedCollateral += weightedVTokenPrice * vTokenBalance\\n snapshot.weightedCollateral = mul_ScalarTruncateAddUInt(\\n weightedVTokenPrice,\\n vTokenBalance,\\n snapshot.weightedCollateral\\n );\\n\\n // totalCollateral += vTokenPrice * vTokenBalance\\n snapshot.totalCollateral = mul_ScalarTruncateAddUInt(vTokenPrice, vTokenBalance, snapshot.totalCollateral);\\n\\n // borrows += oraclePrice * borrowBalance\\n snapshot.borrows = mul_ScalarTruncateAddUInt(oraclePrice, borrowBalance, snapshot.borrows);\\n\\n // Calculate effects of interacting with vTokenModify\\n if (asset == vTokenModify) {\\n // redeem effect\\n // effects += tokensToDenom * redeemTokens\\n snapshot.effects = mul_ScalarTruncateAddUInt(weightedVTokenPrice, redeemTokens, snapshot.effects);\\n\\n // borrow effect\\n // effects += oraclePrice * borrowAmount\\n snapshot.effects = mul_ScalarTruncateAddUInt(oraclePrice, borrowAmount, snapshot.effects);\\n }\\n }\\n\\n uint256 borrowPlusEffects = snapshot.borrows + snapshot.effects;\\n // These are safe, as the underflow condition is checked first\\n unchecked {\\n if (snapshot.weightedCollateral > borrowPlusEffects) {\\n snapshot.liquidity = snapshot.weightedCollateral - borrowPlusEffects;\\n snapshot.shortfall = 0;\\n } else {\\n snapshot.liquidity = 0;\\n snapshot.shortfall = borrowPlusEffects - snapshot.weightedCollateral;\\n }\\n }\\n\\n return snapshot;\\n }\\n\\n /**\\n * @dev Retrieves price from oracle for an asset and checks it is nonzero\\n * @param asset Address for asset to query price\\n * @return Underlying price\\n */\\n function _safeGetUnderlyingPrice(VToken asset) internal view returns (uint256) {\\n uint256 oraclePriceMantissa = oracle.getUnderlyingPrice(address(asset));\\n if (oraclePriceMantissa == 0) {\\n revert PriceError(address(asset));\\n }\\n return oraclePriceMantissa;\\n }\\n\\n /**\\n * @dev Return collateral factor for a market\\n * @param asset Address for asset\\n * @return Collateral factor as exponential\\n */\\n function _getCollateralFactor(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].collateralFactorMantissa });\\n }\\n\\n /**\\n * @dev Retrieves liquidation threshold for a market as an exponential\\n * @param asset Address for asset to liquidation threshold\\n * @return Liquidation threshold as exponential\\n */\\n function _getLiquidationThreshold(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].liquidationThresholdMantissa });\\n }\\n\\n /**\\n * @dev Returns supply and borrow balances of user in vToken, reverts on failure\\n * @param vToken Market to query\\n * @param user Account address\\n * @return vTokenBalance Balance of vTokens, the same as vToken.balanceOf(user)\\n * @return borrowBalance Borrowed amount, including the interest\\n * @return exchangeRateMantissa Stored exchange rate\\n */\\n function _safeGetAccountSnapshot(\\n VToken vToken,\\n address user\\n ) internal view returns (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) {\\n uint256 err;\\n (err, vTokenBalance, borrowBalance, exchangeRateMantissa) = vToken.getAccountSnapshot(user);\\n if (err != 0) {\\n revert SnapshotError(address(vToken), user);\\n }\\n return (vTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /// @notice Reverts if the call is not from expectedSender\\n /// @param expectedSender Expected transaction sender\\n function _checkSenderIs(address expectedSender) internal view {\\n if (msg.sender != expectedSender) {\\n revert UnexpectedSender(expectedSender, msg.sender);\\n }\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n /// @param market Market to check\\n /// @param action Action to check\\n function _checkActionPauseState(address market, Action action) private view {\\n if (actionPaused(market, action)) {\\n revert ActionPaused(market, action);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xc335c6b62d0029396318a984c3e63ca493c299d664feab74acb28eb2e8a4cc1c\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.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\\n/**\\n * @title ComptrollerInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract.\\n */\\ninterface ComptrollerInterface {\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\\n\\n function exitMarket(address vToken) external returns (uint256);\\n\\n /*** Policy Hooks ***/\\n\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external;\\n\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external;\\n\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external;\\n\\n function preRepayHook(address vToken, address borrower) external;\\n\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external;\\n\\n function preSeizeHook(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower\\n ) external;\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\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 seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external;\\n\\n function isComptroller() external view returns (bool);\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 repayAmount\\n ) external view returns (uint256, uint256);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n}\\n\\n/**\\n * @title ComptrollerViewInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract, including only some util view functions.\\n */\\ninterface ComptrollerViewInterface {\\n function markets(address) external view returns (bool, uint256);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function closeFactorMantissa() external view returns (uint256);\\n\\n function liquidationIncentiveMantissa() external view returns (uint256);\\n\\n function minLiquidatableCollateral() external view returns (uint256);\\n\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function borrowCaps(address) external view returns (uint256);\\n\\n function supplyCaps(address) external view returns (uint256);\\n\\n function approvedDelegates(address user, address delegate) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xcbf7f9977472650c61345b7cbde23e81f626e1f8863bab4c6ce3dacfc7604919\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { IPrime } from \\\"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\\\";\\nimport { Action } from \\\"./ComptrollerInterface.sol\\\";\\n\\n/**\\n * @title ComptrollerStorage\\n * @author Venus\\n * @notice Storage layout for the `Comptroller` contract.\\n */\\ncontract ComptrollerStorage {\\n struct LiquidationOrder {\\n VToken vTokenCollateral;\\n VToken vTokenBorrowed;\\n uint256 repayAmount;\\n }\\n\\n struct AccountLiquiditySnapshot {\\n uint256 totalCollateral;\\n uint256 weightedCollateral;\\n uint256 borrows;\\n uint256 effects;\\n uint256 liquidity;\\n uint256 shortfall;\\n }\\n\\n struct RewardSpeeds {\\n address rewardToken;\\n uint256 supplySpeed;\\n uint256 borrowSpeed;\\n }\\n\\n struct Market {\\n // Whether or not this market is listed\\n bool isListed;\\n // 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 uint256 collateralFactorMantissa;\\n // 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 uint256 liquidationThresholdMantissa;\\n // Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n }\\n\\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 Per-account mapping of \\\"assets you are in\\\"\\n */\\n mapping(address => VToken[]) public accountAssets;\\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 /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\\n mapping(address => uint256) public borrowCaps;\\n\\n /// @notice Minimal collateral required for regular (non-batch) liquidations\\n uint256 public minLiquidatableCollateral;\\n\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\\n mapping(address => uint256) public supplyCaps;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(Action => bool)) internal _actionPaused;\\n\\n // List of Reward Distributors added\\n RewardsDistributor[] internal rewardsDistributors;\\n\\n // Used to check if rewards distributor is added\\n mapping(address => bool) internal rewardsDistributorExists;\\n\\n /// @notice Flag indicating whether forced liquidation enabled for a market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n\\n uint256 internal constant NO_ERROR = 0;\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant MIN_CLOSE_FACTOR_MANTISSA = 0.05e18; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant MAX_CLOSE_FACTOR_MANTISSA = 0.9e18; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.9e18; // 0.9\\n\\n /// Prime token address\\n IPrime public prime;\\n\\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 /**\\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[47] private __gap;\\n}\\n\",\"keccak256\":\"0xea2cb59a749eeba52190889ec1058c63ca23a06160d0b7b2ad6327f679db57f1\",\"license\":\"BSD-3-Clause\"},\"contracts/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title TokenErrorReporter\\n * @author Venus\\n * @notice Errors that can be thrown by the `VToken` contract.\\n */\\ncontract TokenErrorReporter {\\n uint256 public constant NO_ERROR = 0; // support legacy return codes\\n\\n error TransferNotAllowed();\\n\\n error MintFreshnessCheck();\\n\\n error RedeemFreshnessCheck();\\n error RedeemTransferOutNotPossible();\\n\\n error BorrowFreshnessCheck();\\n error BorrowCashNotAvailable();\\n error DelegateNotApproved();\\n\\n error RepayBorrowFreshnessCheck();\\n\\n error HealBorrowUnauthorized();\\n error ForceLiquidateBorrowUnauthorized();\\n\\n error LiquidateFreshnessCheck();\\n error LiquidateCollateralFreshnessCheck();\\n error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\\n error LiquidateLiquidatorIsBorrower();\\n error LiquidateCloseAmountIsZero();\\n error LiquidateCloseAmountIsUintMax();\\n\\n error LiquidateSeizeLiquidatorIsBorrower();\\n\\n error ProtocolSeizeShareTooBig();\\n\\n error SetReserveFactorFreshCheck();\\n error SetReserveFactorBoundsCheck();\\n\\n error AddReservesFactorFreshCheck(uint256 actualAddAmount);\\n\\n error ReduceReservesFreshCheck();\\n error ReduceReservesCashNotAvailable();\\n error ReduceReservesCashValidation();\\n\\n error SetInterestRateModelFreshCheck();\\n}\\n\",\"keccak256\":\"0x7a7ced1caaac2d9242659ebd50b99f308c725ce958ac9e11f7ada404b1d97a7b\",\"license\":\"BSD-3-Clause\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from \\\"./lib/constants.sol\\\";\\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 struct Exp {\\n uint256 mantissa;\\n }\\n\\n struct Double {\\n uint256 mantissa;\\n }\\n\\n uint256 internal constant EXP_SCALE = EXP_SCALE_;\\n uint256 internal constant DOUBLE_SCALE = 1e36;\\n uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;\\n uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint256) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / EXP_SCALE;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\\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 // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint256 scalar, uint256 addend) internal pure returns (uint256) {\\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 function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\\n require(n <= type(uint224).max, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\\n require(n <= type(uint32).max, 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_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a + b;\\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_(uint256 a, uint256 b) internal pure returns (uint256) {\\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) / EXP_SCALE });\\n }\\n\\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / EXP_SCALE;\\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) / DOUBLE_SCALE });\\n }\\n\\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / DOUBLE_SCALE;\\n }\\n\\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a * b;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return div_(mul_(a, EXP_SCALE), 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, DOUBLE_SCALE), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return div_(mul_(a, DOUBLE_SCALE), b.mantissa);\\n }\\n\\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a / b;\\n }\\n\\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });\\n }\\n}\\n\",\"keccak256\":\"0x8afbe8a24fe3539c124e718681ed3dcebd24c40dd53095786c0155998213b9b0\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModel.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\nabstract contract InterestRateModel {\\n /**\\n * @notice Calculates the current borrow interest rate per slot (block or second)\\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 amount of reserves the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per slot (block or second)\\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 amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\\n * @return Always true\\n */\\n function isInterestRateModel() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xc4fda1ab75ebe4b187b707c4f10c58780f343cf343c537f641dc75d3cd28ab51\",\"license\":\"BSD-3-Clause\"},\"contracts/Lens/PoolLens.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { IERC20Metadata } from \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Action, ComptrollerInterface, ComptrollerViewInterface } from \\\"../ComptrollerInterface.sol\\\";\\nimport { PoolRegistryInterface } from \\\"../Pool/PoolRegistryInterface.sol\\\";\\nimport { PoolRegistry } from \\\"../Pool/PoolRegistry.sol\\\";\\nimport { RewardsDistributor } from \\\"../Rewards/RewardsDistributor.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\n\\n/**\\n * @title PoolLens\\n * @author Venus\\n * @notice The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information\\n * for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be\\n * looked up for specific pools and markets:\\n- the vToken balance of a given user;\\n- the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address;\\n- the vToken address in a pool for a given asset;\\n- a list of all pools that support an asset;\\n- the underlying asset price of a vToken;\\n- the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\\n */\\ncontract PoolLens is ExponentialNoError, TimeManagerV8 {\\n /**\\n * @dev Struct for PoolDetails.\\n */\\n struct PoolData {\\n string name;\\n address creator;\\n address comptroller;\\n uint256 blockPosted;\\n uint256 timestampPosted;\\n string category;\\n string logoURL;\\n string description;\\n address priceOracle;\\n uint256 closeFactor;\\n uint256 liquidationIncentive;\\n uint256 minLiquidatableCollateral;\\n VTokenMetadata[] vTokens;\\n }\\n\\n /**\\n * @dev Struct for VToken.\\n */\\n struct VTokenMetadata {\\n address vToken;\\n uint256 exchangeRateCurrent;\\n uint256 supplyRatePerBlockOrTimestamp;\\n uint256 borrowRatePerBlockOrTimestamp;\\n uint256 reserveFactorMantissa;\\n uint256 supplyCaps;\\n uint256 borrowCaps;\\n uint256 totalBorrows;\\n uint256 totalReserves;\\n uint256 totalSupply;\\n uint256 totalCash;\\n bool isListed;\\n uint256 collateralFactorMantissa;\\n address underlyingAssetAddress;\\n uint256 vTokenDecimals;\\n uint256 underlyingDecimals;\\n uint256 pausedActions;\\n }\\n\\n /**\\n * @dev Struct for VTokenBalance.\\n */\\n struct VTokenBalances {\\n address vToken;\\n uint256 balanceOf;\\n uint256 borrowBalanceCurrent;\\n uint256 balanceOfUnderlying;\\n uint256 tokenBalance;\\n uint256 tokenAllowance;\\n }\\n\\n /**\\n * @dev Struct for underlyingPrice of VToken.\\n */\\n struct VTokenUnderlyingPrice {\\n address vToken;\\n uint256 underlyingPrice;\\n }\\n\\n /**\\n * @dev Struct with pending reward info for a market.\\n */\\n struct PendingReward {\\n address vTokenAddress;\\n uint256 amount;\\n }\\n\\n /**\\n * @dev Struct with reward distribution totals for a single reward token and distributor.\\n */\\n struct RewardSummary {\\n address distributorAddress;\\n address rewardTokenAddress;\\n uint256 totalRewards;\\n PendingReward[] pendingRewards;\\n }\\n\\n /**\\n * @dev Struct used in RewardDistributor to save last updated market state.\\n */\\n struct RewardTokenState {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number or timestamp the index was last updated at\\n uint256 blockOrTimestamp;\\n // The block number or timestamp at which to stop rewards\\n uint256 lastRewardingBlockOrTimestamp;\\n }\\n\\n /**\\n * @dev Struct with bad debt of a market denominated\\n */\\n struct BadDebt {\\n address vTokenAddress;\\n uint256 badDebtUsd;\\n }\\n\\n /**\\n * @dev Struct with bad debt total denominated in usd for a pool and an array of BadDebt structs for each market\\n */\\n struct BadDebtSummary {\\n address comptroller;\\n uint256 totalBadDebtUsd;\\n BadDebt[] badDebts;\\n }\\n\\n /**\\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) {}\\n\\n /**\\n * @notice Queries the user's supply/borrow balances in vTokens\\n * @param vTokens The list of vToken addresses\\n * @param account The user Account\\n * @return A list of structs containing balances data\\n */\\n function vTokenBalancesAll(VToken[] calldata vTokens, address account) external returns (VTokenBalances[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenBalances[] memory res = new VTokenBalances[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenBalances(vTokens[i], account);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Queries all pools with addtional details for each of them\\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @return Arrays of all Venus pools' data\\n */\\n function getAllPools(address poolRegistryAddress) external view returns (PoolData[] memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n PoolRegistry.VenusPool[] memory venusPools = poolRegistryInterface.getAllPools();\\n uint256 poolLength = venusPools.length;\\n\\n PoolData[] memory poolDataItems = new PoolData[](poolLength);\\n\\n for (uint256 i; i < poolLength; ++i) {\\n PoolRegistry.VenusPool memory venusPool = venusPools[i];\\n PoolData memory poolData = getPoolDataFromVenusPool(poolRegistryAddress, venusPool);\\n poolDataItems[i] = poolData;\\n }\\n\\n return poolDataItems;\\n }\\n\\n /**\\n * @notice Queries the details of a pool identified by Comptroller address\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param comptroller The Comptroller implementation address\\n * @return PoolData structure containing the details of the pool\\n */\\n function getPoolByComptroller(\\n address poolRegistryAddress,\\n address comptroller\\n ) external view returns (PoolData memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return getPoolDataFromVenusPool(poolRegistryAddress, poolRegistryInterface.getPoolByComptroller(comptroller));\\n }\\n\\n /**\\n * @notice Returns vToken holding the specified underlying asset in the specified pool\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param comptroller The pool comptroller\\n * @param asset The underlyingAsset of VToken\\n * @return Address of the vToken\\n */\\n function getVTokenForAsset(\\n address poolRegistryAddress,\\n address comptroller,\\n address asset\\n ) external view returns (address) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return poolRegistryInterface.getVTokenForAsset(comptroller, asset);\\n }\\n\\n /**\\n * @notice Returns all pools that support the specified underlying asset\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param asset The underlying asset of vToken\\n * @return A list of Comptroller contracts\\n */\\n function getPoolsSupportedByAsset(\\n address poolRegistryAddress,\\n address asset\\n ) external view returns (address[] memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return poolRegistryInterface.getPoolsSupportedByAsset(asset);\\n }\\n\\n /**\\n * @notice Returns the price data for the underlying assets of the specified vTokens\\n * @param vTokens The list of vToken addresses\\n * @return An array containing the price data for each asset\\n */\\n function vTokenUnderlyingPriceAll(\\n VToken[] calldata vTokens\\n ) external view returns (VTokenUnderlyingPrice[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenUnderlyingPrice[] memory res = new VTokenUnderlyingPrice[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenUnderlyingPrice(vTokens[i]);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Returns the pending rewards for a user for a given pool.\\n * @param account The user account.\\n * @param comptrollerAddress address\\n * @return Pending rewards array\\n */\\n function getPendingRewards(\\n address account,\\n address comptrollerAddress\\n ) external view returns (RewardSummary[] memory) {\\n VToken[] memory markets = ComptrollerInterface(comptrollerAddress).getAllMarkets();\\n RewardsDistributor[] memory rewardsDistributors = ComptrollerViewInterface(comptrollerAddress)\\n .getRewardDistributors();\\n RewardSummary[] memory rewardSummary = new RewardSummary[](rewardsDistributors.length);\\n for (uint256 i; i < rewardsDistributors.length; ++i) {\\n RewardSummary memory reward;\\n reward.distributorAddress = address(rewardsDistributors[i]);\\n reward.rewardTokenAddress = address(rewardsDistributors[i].rewardToken());\\n reward.totalRewards = rewardsDistributors[i].rewardTokenAccrued(account);\\n reward.pendingRewards = _calculateNotDistributedAwards(account, markets, rewardsDistributors[i]);\\n rewardSummary[i] = reward;\\n }\\n return rewardSummary;\\n }\\n\\n /**\\n * @notice Returns a summary of a pool's bad debt broken down by market\\n *\\n * @param comptrollerAddress Address of the comptroller\\n *\\n * @return badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and\\n * a break down of bad debt by market\\n */\\n function getPoolBadDebt(address comptrollerAddress) external view returns (BadDebtSummary memory) {\\n uint256 totalBadDebtUsd;\\n\\n // Get every market in the pool\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\\n VToken[] memory markets = comptroller.getAllMarkets();\\n ResilientOracleInterface priceOracle = comptroller.oracle();\\n\\n BadDebt[] memory badDebts = new BadDebt[](markets.length);\\n\\n BadDebtSummary memory badDebtSummary;\\n badDebtSummary.comptroller = comptrollerAddress;\\n badDebtSummary.badDebts = badDebts;\\n\\n // // Calculate the bad debt is USD per market\\n for (uint256 i; i < markets.length; ++i) {\\n BadDebt memory badDebt;\\n badDebt.vTokenAddress = address(markets[i]);\\n badDebt.badDebtUsd =\\n (VToken(address(markets[i])).badDebt() * priceOracle.getUnderlyingPrice(address(markets[i]))) /\\n EXP_SCALE;\\n badDebtSummary.badDebts[i] = badDebt;\\n totalBadDebtUsd = totalBadDebtUsd + badDebt.badDebtUsd;\\n }\\n\\n badDebtSummary.totalBadDebtUsd = totalBadDebtUsd;\\n\\n return badDebtSummary;\\n }\\n\\n /**\\n * @notice Queries the user's supply/borrow balances in the specified vToken\\n * @param vToken vToken address\\n * @param account The user Account\\n * @return A struct containing the balances data\\n */\\n function vTokenBalances(VToken vToken, address account) public returns (VTokenBalances memory) {\\n uint256 balanceOf = vToken.balanceOf(account);\\n uint256 borrowBalanceCurrent = vToken.borrowBalanceCurrent(account);\\n uint256 balanceOfUnderlying = vToken.balanceOfUnderlying(account);\\n uint256 tokenBalance;\\n uint256 tokenAllowance;\\n\\n IERC20 underlying = IERC20(vToken.underlying());\\n tokenBalance = underlying.balanceOf(account);\\n tokenAllowance = underlying.allowance(account, address(vToken));\\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 Queries additional information for the pool\\n * @param poolRegistryAddress Address of the PoolRegistry\\n * @param venusPool The VenusPool Object from PoolRegistry\\n * @return Enriched PoolData\\n */\\n function getPoolDataFromVenusPool(\\n address poolRegistryAddress,\\n PoolRegistry.VenusPool memory venusPool\\n ) public view returns (PoolData memory) {\\n // Get tokens in the Pool\\n ComptrollerInterface comptrollerInstance = ComptrollerInterface(venusPool.comptroller);\\n\\n VToken[] memory vTokens = comptrollerInstance.getAllMarkets();\\n\\n VTokenMetadata[] memory vTokenMetadataItems = vTokenMetadataAll(vTokens);\\n\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n\\n PoolRegistry.VenusPoolMetaData memory venusPoolMetaData = poolRegistryInterface.getVenusPoolMetadata(\\n venusPool.comptroller\\n );\\n\\n ComptrollerViewInterface comptrollerViewInstance = ComptrollerViewInterface(venusPool.comptroller);\\n\\n PoolData memory poolData = PoolData({\\n name: venusPool.name,\\n creator: venusPool.creator,\\n comptroller: venusPool.comptroller,\\n blockPosted: venusPool.blockPosted,\\n timestampPosted: venusPool.timestampPosted,\\n category: venusPoolMetaData.category,\\n logoURL: venusPoolMetaData.logoURL,\\n description: venusPoolMetaData.description,\\n vTokens: vTokenMetadataItems,\\n priceOracle: address(comptrollerViewInstance.oracle()),\\n closeFactor: comptrollerViewInstance.closeFactorMantissa(),\\n liquidationIncentive: comptrollerViewInstance.liquidationIncentiveMantissa(),\\n minLiquidatableCollateral: comptrollerViewInstance.minLiquidatableCollateral()\\n });\\n\\n return poolData;\\n }\\n\\n /**\\n * @notice Returns the metadata of VToken\\n * @param vToken The address of vToken\\n * @return VTokenMetadata struct\\n */\\n function vTokenMetadata(VToken vToken) public view returns (VTokenMetadata memory) {\\n uint256 exchangeRateCurrent = vToken.exchangeRateStored();\\n address comptrollerAddress = address(vToken.comptroller());\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\\n (bool isListed, uint256 collateralFactorMantissa) = comptroller.markets(address(vToken));\\n\\n address underlyingAssetAddress = vToken.underlying();\\n uint256 underlyingDecimals = IERC20Metadata(underlyingAssetAddress).decimals();\\n\\n uint256 pausedActions;\\n for (uint8 i; i <= uint8(type(Action).max); ++i) {\\n uint256 paused = ComptrollerInterface(comptrollerAddress).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 supplyRatePerBlockOrTimestamp: vToken.supplyRatePerBlock(),\\n borrowRatePerBlockOrTimestamp: vToken.borrowRatePerBlock(),\\n reserveFactorMantissa: vToken.reserveFactorMantissa(),\\n supplyCaps: comptroller.supplyCaps(address(vToken)),\\n borrowCaps: comptroller.borrowCaps(address(vToken)),\\n totalBorrows: vToken.totalBorrows(),\\n totalReserves: vToken.totalReserves(),\\n totalSupply: vToken.totalSupply(),\\n totalCash: vToken.getCash(),\\n isListed: isListed,\\n collateralFactorMantissa: collateralFactorMantissa,\\n underlyingAssetAddress: underlyingAssetAddress,\\n vTokenDecimals: vToken.decimals(),\\n underlyingDecimals: underlyingDecimals,\\n pausedActions: pausedActions\\n });\\n }\\n\\n /**\\n * @notice Returns the metadata of all VTokens\\n * @param vTokens The list of vToken addresses\\n * @return An array of VTokenMetadata structs\\n */\\n function vTokenMetadataAll(VToken[] memory vTokens) public view returns (VTokenMetadata[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenMetadata[] memory res = new VTokenMetadata[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenMetadata(vTokens[i]);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Returns the price data for the underlying asset of the specified vToken\\n * @param vToken vToken address\\n * @return The price data for each asset\\n */\\n function vTokenUnderlyingPrice(VToken vToken) public view returns (VTokenUnderlyingPrice memory) {\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(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 function _calculateNotDistributedAwards(\\n address account,\\n VToken[] memory markets,\\n RewardsDistributor rewardsDistributor\\n ) internal view returns (PendingReward[] memory) {\\n PendingReward[] memory pendingRewards = new PendingReward[](markets.length);\\n\\n for (uint256 i; i < markets.length; ++i) {\\n // Market borrow and supply state we will modify update in-memory, in order to not modify storage\\n RewardTokenState memory borrowState;\\n RewardTokenState memory supplyState;\\n\\n if (isTimeBased) {\\n (\\n borrowState.index,\\n borrowState.blockOrTimestamp,\\n borrowState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenBorrowStateTimeBased(address(markets[i]));\\n (\\n supplyState.index,\\n supplyState.blockOrTimestamp,\\n supplyState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenSupplyStateTimeBased(address(markets[i]));\\n } else {\\n (\\n borrowState.index,\\n borrowState.blockOrTimestamp,\\n borrowState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenBorrowState(address(markets[i]));\\n (\\n supplyState.index,\\n supplyState.blockOrTimestamp,\\n supplyState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenSupplyState(address(markets[i]));\\n }\\n\\n Exp memory marketBorrowIndex = Exp({ mantissa: markets[i].borrowIndex() });\\n\\n // Update market supply and borrow index in-memory\\n updateMarketBorrowIndex(address(markets[i]), rewardsDistributor, borrowState, marketBorrowIndex);\\n updateMarketSupplyIndex(address(markets[i]), rewardsDistributor, supplyState);\\n\\n // Calculate pending rewards\\n uint256 borrowReward = calculateBorrowerReward(\\n address(markets[i]),\\n rewardsDistributor,\\n account,\\n borrowState,\\n marketBorrowIndex\\n );\\n uint256 supplyReward = calculateSupplierReward(\\n address(markets[i]),\\n rewardsDistributor,\\n account,\\n supplyState\\n );\\n\\n PendingReward memory pendingReward;\\n pendingReward.vTokenAddress = address(markets[i]);\\n pendingReward.amount = borrowReward + supplyReward;\\n pendingRewards[i] = pendingReward;\\n }\\n return pendingRewards;\\n }\\n\\n function updateMarketBorrowIndex(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n RewardTokenState memory borrowState,\\n Exp memory marketBorrowIndex\\n ) internal view {\\n uint256 borrowSpeed = rewardsDistributor.rewardTokenBorrowSpeeds(vToken);\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (\\n borrowState.lastRewardingBlockOrTimestamp > 0 &&\\n blockNumberOrTimestamp > borrowState.lastRewardingBlockOrTimestamp\\n ) {\\n blockNumberOrTimestamp = borrowState.lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, borrowState.blockOrTimestamp);\\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\\n // Remove the total earned interest rate since the opening of the market from total borrows\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, borrowSpeed);\\n Double memory ratio = borrowAmount > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\\n } else if (deltaBlocksOrTimestamp > 0) {\\n borrowState.blockOrTimestamp = blockNumberOrTimestamp;\\n }\\n }\\n\\n function updateMarketSupplyIndex(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n RewardTokenState memory supplyState\\n ) internal view {\\n uint256 supplySpeed = rewardsDistributor.rewardTokenSupplySpeeds(vToken);\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (\\n supplyState.lastRewardingBlockOrTimestamp > 0 &&\\n blockNumberOrTimestamp > supplyState.lastRewardingBlockOrTimestamp\\n ) {\\n blockNumberOrTimestamp = supplyState.lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, supplyState.blockOrTimestamp);\\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, supplySpeed);\\n Double memory ratio = supplyTokens > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\\n } else if (deltaBlocksOrTimestamp > 0) {\\n supplyState.blockOrTimestamp = blockNumberOrTimestamp;\\n }\\n }\\n\\n function calculateBorrowerReward(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n address borrower,\\n RewardTokenState memory borrowState,\\n Exp memory marketBorrowIndex\\n ) internal view returns (uint256) {\\n Double memory borrowIndex = Double({ mantissa: borrowState.index });\\n Double memory borrowerIndex = Double({\\n mantissa: rewardsDistributor.rewardTokenBorrowerIndex(vToken, borrower)\\n });\\n if (borrowerIndex.mantissa == 0 && borrowIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set\\n borrowerIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\\n }\\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n return borrowerDelta;\\n }\\n\\n function calculateSupplierReward(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n address supplier,\\n RewardTokenState memory supplyState\\n ) internal view returns (uint256) {\\n Double memory supplyIndex = Double({ mantissa: supplyState.index });\\n Double memory supplierIndex = Double({\\n mantissa: rewardsDistributor.rewardTokenSupplierIndex(vToken, supplier)\\n });\\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\\n // Covers the case where users supplied tokens before the market's supply state index was set\\n supplierIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\\n }\\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n return supplierDelta;\\n }\\n}\\n\",\"keccak256\":\"0xab04eb777ddc89a994e38e10ef0e776d165f1b7d98a4cf7715464366f931007a\",\"license\":\"BSD-3-Clause\"},\"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\",\"keccak256\":\"0x4c25e30635485d162177effa384eee51768b0141a567a0da16ff6ad673274166\",\"license\":\"BSD-3-Clause\"},\"contracts/Pool/PoolRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\nimport { PoolRegistryInterface } from \\\"./PoolRegistryInterface.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"../lib/validators.sol\\\";\\n\\n/**\\n * @title PoolRegistry\\n * @author Venus\\n * @notice The Isolated Pools architecture centers around the `PoolRegistry` contract. The `PoolRegistry` maintains a directory of isolated lending\\n * pools and can perform actions like creating and registering new pools, adding new markets to existing pools, setting and updating the pool's required\\n * metadata, and providing the getter methods to get information on the pools.\\n *\\n * Isolated lending has three main components: PoolRegistry, pools, and markets. The PoolRegistry is responsible for managing pools.\\n * It can create new pools, update pool metadata and manage markets within pools. PoolRegistry contains getter methods to get the details of\\n * any existing pool like `getVTokenForAsset` and `getPoolsSupportedByAsset`. It also contains methods for updating pool metadata (`updatePoolMetadata`)\\n * and setting pool name (`setPoolName`).\\n *\\n * The directory of pools is managed through two mappings: `_poolByComptroller` which is a hashmap with the comptroller address as the key and `VenusPool` as\\n * the value and `_poolsByID` which is an array of comptroller addresses. Individual pools can be accessed by calling `getPoolByComptroller` with the pool's\\n * comptroller address. `_poolsByID` is used to iterate through all of the pools.\\n *\\n * PoolRegistry also contains a map of asset addresses called `_supportedPools` that maps to an array of assets suppored by each pool. This array of pools by\\n * asset is retrieved by calling `getPoolsSupportedByAsset`.\\n *\\n * PoolRegistry registers new isolated pools in the directory with the `createRegistryPool` method. Isolated pools are composed of independent markets with\\n * specific assets and custom risk management configurations according to their markets.\\n */\\ncontract PoolRegistry is Ownable2StepUpgradeable, AccessControlledV8, PoolRegistryInterface {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n struct AddMarketInput {\\n VToken vToken;\\n uint256 collateralFactor;\\n uint256 liquidationThreshold;\\n uint256 initialSupply;\\n address vTokenReceiver;\\n uint256 supplyCap;\\n uint256 borrowCap;\\n }\\n\\n uint256 internal constant MAX_POOL_NAME_LENGTH = 100;\\n\\n /**\\n * @notice Maps pool's comptroller address to metadata.\\n */\\n mapping(address => VenusPoolMetaData) public metadata;\\n\\n /**\\n * @dev Maps pool ID to pool's comptroller address\\n */\\n mapping(uint256 => address) private _poolsByID;\\n\\n /**\\n * @dev Total number of pools created.\\n */\\n uint256 private _numberOfPools;\\n\\n /**\\n * @dev Maps comptroller address to Venus pool Index.\\n */\\n mapping(address => VenusPool) private _poolByComptroller;\\n\\n /**\\n * @dev Maps pool's comptroller address to asset to vToken.\\n */\\n mapping(address => mapping(address => address)) private _vTokens;\\n\\n /**\\n * @dev Maps asset to list of supported pools.\\n */\\n mapping(address => address[]) private _supportedPools;\\n\\n /**\\n * @notice Emitted when a new Venus pool is added to the directory.\\n */\\n event PoolRegistered(address indexed comptroller, VenusPool pool);\\n\\n /**\\n * @notice Emitted when a pool name is set.\\n */\\n event PoolNameSet(address indexed comptroller, string oldName, string newName);\\n\\n /**\\n * @notice Emitted when a pool metadata is updated.\\n */\\n event PoolMetadataUpdated(\\n address indexed comptroller,\\n VenusPoolMetaData oldMetadata,\\n VenusPoolMetaData newMetadata\\n );\\n\\n /**\\n * @notice Emitted when a Market is added to the pool.\\n */\\n event MarketAdded(address indexed comptroller, address indexed vTokenAddress);\\n\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor() {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializes the deployer to owner\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(address accessControlManager_) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n /**\\n * @notice Adds a new Venus pool to the directory\\n * @dev Price oracle must be configured before adding a pool\\n * @param name The name of the pool\\n * @param comptroller Pool's Comptroller contract\\n * @param closeFactor The pool's close factor (scaled by 1e18)\\n * @param liquidationIncentive The pool's liquidation incentive (scaled by 1e18)\\n * @param minLiquidatableCollateral Minimal collateral for regular (non-batch) liquidations flow\\n * @return index The index of the registered Venus pool\\n * @custom:error ZeroAddressNotAllowed is thrown when Comptroller address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\\n */\\n function addPool(\\n string calldata name,\\n Comptroller comptroller,\\n uint256 closeFactor,\\n uint256 liquidationIncentive,\\n uint256 minLiquidatableCollateral\\n ) external virtual returns (uint256 index) {\\n _checkAccessAllowed(\\\"addPool(string,address,uint256,uint256,uint256)\\\");\\n // Input validation\\n ensureNonzeroAddress(address(comptroller));\\n ensureNonzeroAddress(address(comptroller.oracle()));\\n\\n uint256 poolId = _registerPool(name, address(comptroller));\\n\\n // Set Venus pool parameters\\n comptroller.setCloseFactor(closeFactor);\\n comptroller.setLiquidationIncentive(liquidationIncentive);\\n comptroller.setMinLiquidatableCollateral(minLiquidatableCollateral);\\n\\n return poolId;\\n }\\n\\n /**\\n * @notice Add a market to an existing pool and then mint to provide initial supply\\n * @param input The structure describing the parameters for adding a market to a pool\\n * @custom:error ZeroAddressNotAllowed is thrown when vToken address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when vTokenReceiver address is zero\\n */\\n function addMarket(AddMarketInput memory input) external {\\n _checkAccessAllowed(\\\"addMarket(AddMarketInput)\\\");\\n ensureNonzeroAddress(address(input.vToken));\\n ensureNonzeroAddress(input.vTokenReceiver);\\n require(input.initialSupply > 0, \\\"PoolRegistry: initialSupply is zero\\\");\\n\\n VToken vToken = input.vToken;\\n address vTokenAddress = address(vToken);\\n address comptrollerAddress = address(vToken.comptroller());\\n Comptroller comptroller = Comptroller(comptrollerAddress);\\n address underlyingAddress = vToken.underlying();\\n IERC20Upgradeable underlying = IERC20Upgradeable(underlyingAddress);\\n\\n require(_poolByComptroller[comptrollerAddress].creator != address(0), \\\"PoolRegistry: Pool not registered\\\");\\n // solhint-disable-next-line reason-string\\n require(\\n _vTokens[comptrollerAddress][underlyingAddress] == address(0),\\n \\\"PoolRegistry: Market already added for asset comptroller combination\\\"\\n );\\n\\n comptroller.supportMarket(vToken);\\n comptroller.setCollateralFactor(vToken, input.collateralFactor, input.liquidationThreshold);\\n\\n uint256[] memory newSupplyCaps = new uint256[](1);\\n uint256[] memory newBorrowCaps = new uint256[](1);\\n VToken[] memory vTokens = new VToken[](1);\\n\\n newSupplyCaps[0] = input.supplyCap;\\n newBorrowCaps[0] = input.borrowCap;\\n vTokens[0] = vToken;\\n\\n comptroller.setMarketSupplyCaps(vTokens, newSupplyCaps);\\n comptroller.setMarketBorrowCaps(vTokens, newBorrowCaps);\\n\\n _vTokens[comptrollerAddress][underlyingAddress] = vTokenAddress;\\n _supportedPools[underlyingAddress].push(comptrollerAddress);\\n\\n uint256 amountToSupply = _transferIn(underlying, msg.sender, input.initialSupply);\\n underlying.forceApprove(vTokenAddress, 0);\\n underlying.forceApprove(vTokenAddress, amountToSupply);\\n vToken.mintBehalf(input.vTokenReceiver, amountToSupply);\\n\\n emit MarketAdded(comptrollerAddress, vTokenAddress);\\n }\\n\\n /**\\n * @notice Modify existing Venus pool name\\n * @param comptroller Pool's Comptroller\\n * @param name New pool name\\n */\\n function setPoolName(address comptroller, string calldata name) external {\\n _checkAccessAllowed(\\\"setPoolName(address,string)\\\");\\n _ensureValidName(name);\\n VenusPool storage pool = _poolByComptroller[comptroller];\\n string memory oldName = pool.name;\\n pool.name = name;\\n emit PoolNameSet(comptroller, oldName, name);\\n }\\n\\n /**\\n * @notice Update metadata of an existing pool\\n * @param comptroller Pool's Comptroller\\n * @param metadata_ New pool metadata\\n */\\n function updatePoolMetadata(address comptroller, VenusPoolMetaData calldata metadata_) external {\\n _checkAccessAllowed(\\\"updatePoolMetadata(address,VenusPoolMetaData)\\\");\\n VenusPoolMetaData memory oldMetadata = metadata[comptroller];\\n metadata[comptroller] = metadata_;\\n emit PoolMetadataUpdated(comptroller, oldMetadata, metadata_);\\n }\\n\\n /**\\n * @notice Returns arrays of all Venus pools' data\\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\\n * @return A list of all pools within PoolRegistry, with details for each pool\\n */\\n function getAllPools() external view override returns (VenusPool[] memory) {\\n uint256 numberOfPools_ = _numberOfPools; // storage load to save gas\\n VenusPool[] memory _pools = new VenusPool[](numberOfPools_);\\n for (uint256 i = 1; i <= numberOfPools_; ++i) {\\n address comptroller = _poolsByID[i];\\n _pools[i - 1] = (_poolByComptroller[comptroller]);\\n }\\n return _pools;\\n }\\n\\n /**\\n * @param comptroller The comptroller proxy address associated to the pool\\n * @return Returns Venus pool\\n */\\n function getPoolByComptroller(address comptroller) external view override returns (VenusPool memory) {\\n return _poolByComptroller[comptroller];\\n }\\n\\n /**\\n * @param comptroller comptroller of Venus pool\\n * @return Returns Metadata of Venus pool\\n */\\n function getVenusPoolMetadata(address comptroller) external view override returns (VenusPoolMetaData memory) {\\n return metadata[comptroller];\\n }\\n\\n function getVTokenForAsset(address comptroller, address asset) external view override returns (address) {\\n return _vTokens[comptroller][asset];\\n }\\n\\n function getPoolsSupportedByAsset(address asset) external view override returns (address[] memory) {\\n return _supportedPools[asset];\\n }\\n\\n /**\\n * @dev Adds a new Venus pool to the directory (without checking msg.sender).\\n * @param name The name of the pool\\n * @param comptroller The pool's Comptroller proxy contract address\\n * @return The index of the registered Venus pool\\n */\\n function _registerPool(string calldata name, address comptroller) internal returns (uint256) {\\n VenusPool storage storedPool = _poolByComptroller[comptroller];\\n\\n require(storedPool.creator == address(0), \\\"PoolRegistry: Pool already exists in the directory.\\\");\\n _ensureValidName(name);\\n\\n ++_numberOfPools;\\n uint256 numberOfPools_ = _numberOfPools; // cache on stack to save storage read gas\\n\\n VenusPool memory pool = VenusPool(name, msg.sender, comptroller, block.number, block.timestamp);\\n\\n _poolsByID[numberOfPools_] = comptroller;\\n _poolByComptroller[comptroller] = pool;\\n\\n emit PoolRegistered(comptroller, pool);\\n return numberOfPools_;\\n }\\n\\n function _transferIn(IERC20Upgradeable token, address from, uint256 amount) internal returns (uint256) {\\n uint256 balanceBefore = token.balanceOf(address(this));\\n token.safeTransferFrom(from, address(this), amount);\\n uint256 balanceAfter = token.balanceOf(address(this));\\n return balanceAfter - balanceBefore;\\n }\\n\\n function _ensureValidName(string calldata name) internal pure {\\n require(bytes(name).length <= MAX_POOL_NAME_LENGTH, \\\"Pool's name is too large\\\");\\n }\\n}\\n\",\"keccak256\":\"0xafbb871f7b4db3ef439d846baa5f18a136192f9b43ea695c81262a77b06c4b25\",\"license\":\"BSD-3-Clause\"},\"contracts/Pool/PoolRegistryInterface.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 /**\\n * @notice Struct for a Venus interest rate pool metadata.\\n */\\n struct VenusPoolMetaData {\\n string category;\\n string logoURL;\\n string description;\\n }\\n\\n /// @notice Get all pools in PoolRegistry\\n function getAllPools() external view returns (VenusPool[] memory);\\n\\n /// @notice Get a pool by comptroller address\\n function getPoolByComptroller(address comptroller) external view returns (VenusPool memory);\\n\\n /// @notice Get the address of the VToken contract in the Pool where the underlying token is the provided 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 /// @notice Get the metadata of a Pool by comptroller address\\n function getVenusPoolMetadata(address comptroller) external view returns (VenusPoolMetaData memory);\\n}\\n\",\"keccak256\":\"0x7b39cda3b372a686501ce3c2aad288c6af410148110318249d75d4516729c92c\",\"license\":\"BSD-3-Clause\"},\"contracts/Rewards/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\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 { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"../MaxLoopsLimitHelper.sol\\\";\\nimport { RewardsDistributorStorage } from \\\"./RewardsDistributorStorage.sol\\\";\\n\\n/**\\n * @title `RewardsDistributor`\\n * @author Venus\\n * @notice Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol.\\n * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward\\n * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool.\\n * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward\\n * token to be released each slot (block or second) for borrowers and suppliers, which is distributed based on a user\\u2019s percentage of the borrows or supplies\\n * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting\\n * their contributor reward token speed, which similarly allocates a fixed amount of reward token per slot (block or second).\\n *\\n * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed\\n * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized\\n * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\\n */\\ncontract RewardsDistributor is\\n ExponentialNoError,\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n MaxLoopsLimitHelper,\\n RewardsDistributorStorage,\\n TimeManagerV8\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice The initial REWARD TOKEN index for a market\\n uint224 public constant INITIAL_INDEX = 1e36;\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a supplier\\n event DistributedSupplierRewardToken(\\n VToken indexed vToken,\\n address indexed supplier,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenSupplyIndex\\n );\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a borrower\\n event DistributedBorrowerRewardToken(\\n VToken indexed vToken,\\n address indexed borrower,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenBorrowIndex\\n );\\n\\n /// @notice Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when REWARD TOKEN is granted by admin\\n event RewardTokenGranted(address indexed recipient, uint256 amount);\\n\\n /// @notice Emitted when a new REWARD TOKEN speed is set for a contributor\\n event ContributorRewardTokenSpeedUpdated(address indexed contributor, uint256 newSpeed);\\n\\n /// @notice Emitted when a market is initialized\\n event MarketInitialized(address indexed vToken);\\n\\n /// @notice Emitted when a reward token supply index is updated\\n event RewardTokenSupplyIndexUpdated(address indexed vToken);\\n\\n /// @notice Emitted when a reward token borrow index is updated\\n event RewardTokenBorrowIndexUpdated(address indexed vToken, Exp marketBorrowIndex);\\n\\n /// @notice Emitted when a reward for contributor is updated\\n event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued);\\n\\n /// @notice Emitted when a reward token last rewarding block for supply is updated\\n event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding block for borrow is updated\\n event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding timestamp for supply is updated\\n event SupplyLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\\n\\n /// @notice Emitted when a reward token last rewarding timestamp for borrow is updated\\n event BorrowLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\\n\\n modifier onlyComptroller() {\\n require(address(comptroller) == msg.sender, \\\"Only comptroller can call this function\\\");\\n _;\\n }\\n\\n /**\\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice RewardsDistributor initializer\\n * @dev Initializes the deployer to owner\\n * @param comptroller_ Comptroller to attach the reward distributor to\\n * @param rewardToken_ Reward token to distribute\\n * @param loopsLimit_ Maximum number of iterations for the loops in this contract\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(\\n Comptroller comptroller_,\\n IERC20Upgradeable rewardToken_,\\n uint256 loopsLimit_,\\n address accessControlManager_\\n ) external initializer {\\n comptroller = comptroller_;\\n rewardToken = rewardToken_;\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n\\n _setMaxLoopsLimit(loopsLimit_);\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken\\n * @param vToken The address of the vToken to be initialized\\n * @custom:event MarketInitialized emits on success\\n * @custom:access Only Comptroller\\n */\\n function initializeMarket(address vToken) external onlyComptroller {\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n isTimeBased\\n ? _initializeMarketTimestampBased(vToken, blockNumberOrTimestamp)\\n : _initializeMarketBlockBased(vToken, safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\"));\\n\\n emit MarketInitialized(vToken);\\n }\\n\\n /*** Reward Token Distribution ***/\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them\\n * Borrowers will begin to accrue after the first interaction with the protocol.\\n * @dev This function should only be called when the user has a borrow position in the market\\n * (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook)\\n * We avoid an external call to check if they are in the market to save gas because this function is called in many places\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function distributeBorrowerRewardToken(\\n address vToken,\\n address borrower,\\n Exp memory marketBorrowIndex\\n ) external onlyComptroller {\\n _distributeBorrowerRewardToken(vToken, borrower, marketBorrowIndex);\\n }\\n\\n function updateRewardTokenSupplyIndex(address vToken) external onlyComptroller {\\n _updateRewardTokenSupplyIndex(vToken);\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the recipient\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\\n * @param recipient The address of the recipient to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n */\\n function grantRewardToken(address recipient, uint256 amount) external onlyOwner {\\n uint256 amountLeft = _grantRewardToken(recipient, amount);\\n require(amountLeft == 0, \\\"insufficient rewardToken for grant\\\");\\n emit RewardTokenGranted(recipient, amount);\\n }\\n\\n function updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) external onlyComptroller {\\n _updateRewardTokenBorrowIndex(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN borrow and supply speeds for the specified markets\\n * @param vTokens The markets whose REWARD TOKEN speed to update\\n * @param supplySpeeds New supply-side REWARD TOKEN speed for the corresponding market\\n * @param borrowSpeeds New borrow-side REWARD TOKEN speed for the corresponding market\\n */\\n function setRewardTokenSpeeds(\\n VToken[] memory vTokens,\\n uint256[] memory supplySpeeds,\\n uint256[] memory borrowSpeeds\\n ) external {\\n _checkAccessAllowed(\\\"setRewardTokenSpeeds(address[],uint256[],uint256[])\\\");\\n uint256 numTokens = vTokens.length;\\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \\\"invalid setRewardTokenSpeeds\\\");\\n\\n for (uint256 i; i < numTokens; ++i) {\\n _setRewardTokenSpeed(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for the specified markets, used when contract is block based\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market\\n * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market\\n */\\n function setLastRewardingBlocks(\\n VToken[] calldata vTokens,\\n uint32[] calldata supplyLastRewardingBlocks,\\n uint32[] calldata borrowLastRewardingBlocks\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlocks(address[],uint32[],uint32[])\\\");\\n require(!isTimeBased, \\\"Block-based operation only\\\");\\n\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length,\\n \\\"RewardsDistributor::setLastRewardingBlocks invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlock(vTokens[i], supplyLastRewardingBlocks[i], borrowLastRewardingBlocks[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block timestamp for the specified markets, used when contract is time based\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlockTimestamps New supply-side REWARD TOKEN last rewarding block timestamp for the corresponding market\\n * @param borrowLastRewardingBlockTimestamps New borrow-side REWARD TOKEN last rewarding block timestamp for the corresponding market\\n */\\n function setLastRewardingBlockTimestamps(\\n VToken[] calldata vTokens,\\n uint256[] calldata supplyLastRewardingBlockTimestamps,\\n uint256[] calldata borrowLastRewardingBlockTimestamps\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlockTimestamps(address[],uint256[],uint256[])\\\");\\n require(isTimeBased, \\\"Time-based operation only\\\");\\n\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlockTimestamps.length &&\\n numTokens == borrowLastRewardingBlockTimestamps.length,\\n \\\"RewardsDistributor::setLastRewardingBlockTimestamps invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlockTimestamp(\\n vTokens[i],\\n supplyLastRewardingBlockTimestamps[i],\\n borrowLastRewardingBlockTimestamps[i]\\n );\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single contributor\\n * @param contributor The contributor whose REWARD TOKEN speed to update\\n * @param rewardTokenSpeed New REWARD TOKEN speed for contributor\\n */\\n function setContributorRewardTokenSpeed(address contributor, uint256 rewardTokenSpeed) external onlyOwner {\\n // note that REWARD TOKEN speed could be set to 0 to halt liquidity rewards for a contributor\\n updateContributorRewards(contributor);\\n if (rewardTokenSpeed == 0) {\\n // release storage\\n delete lastContributorBlock[contributor];\\n } else {\\n lastContributorBlock[contributor] = getBlockNumberOrTimestamp();\\n }\\n rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed;\\n\\n emit ContributorRewardTokenSpeedUpdated(contributor, rewardTokenSpeed);\\n }\\n\\n function distributeSupplierRewardToken(address vToken, address supplier) external onlyComptroller {\\n _distributeSupplierRewardToken(vToken, supplier);\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in all markets\\n * @param holder The address to claim REWARD TOKEN for\\n */\\n function claimRewardToken(address holder) external {\\n return claimRewardToken(holder, comptroller.getAllMarkets());\\n }\\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) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Calculate additional accrued REWARD TOKEN for a contributor since last accrual\\n * @param contributor The address to calculate contributor rewards for\\n */\\n function updateContributorRewards(address contributor) public {\\n uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, lastContributorBlock[contributor]);\\n if (deltaBlocksOrTimestamp > 0 && rewardTokenSpeed > 0) {\\n uint256 newAccrued = mul_(deltaBlocksOrTimestamp, rewardTokenSpeed);\\n uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued);\\n\\n rewardTokenAccrued[contributor] = contributorAccrued;\\n lastContributorBlock[contributor] = blockNumberOrTimestamp;\\n\\n emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]);\\n }\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in the specified markets\\n * @param holder The address to claim REWARD TOKEN for\\n * @param vTokens The list of markets to claim REWARD TOKEN in\\n */\\n function claimRewardToken(address holder, VToken[] memory vTokens) public {\\n uint256 vTokensCount = vTokens.length;\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n VToken vToken = vTokens[i];\\n require(comptroller.isMarketListed(vToken), \\\"market must be listed\\\");\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n _distributeBorrowerRewardToken(address(vToken), holder, borrowIndex);\\n _updateRewardTokenSupplyIndex(address(vToken));\\n _distributeSupplierRewardToken(address(vToken), holder);\\n }\\n rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for a single market.\\n * @param vToken market's whose reward token last rewarding block to be updated\\n * @param supplyLastRewardingBlock New supply-side REWARD TOKEN last rewarding block for market\\n * @param borrowLastRewardingBlock New borrow-side REWARD TOKEN last rewarding block for market\\n */\\n function _setLastRewardingBlock(\\n VToken vToken,\\n uint32 supplyLastRewardingBlock,\\n uint32 borrowLastRewardingBlock\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockNumber = getBlockNumberOrTimestamp();\\n\\n require(supplyLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n require(borrowLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n\\n uint32 currentSupplyLastRewardingBlock = rewardTokenSupplyState[address(vToken)].lastRewardingBlock;\\n uint32 currentBorrowLastRewardingBlock = rewardTokenBorrowState[address(vToken)].lastRewardingBlock;\\n\\n require(\\n currentSupplyLastRewardingBlock == 0 || currentSupplyLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlock == 0 || currentBorrowLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlock != supplyLastRewardingBlock) {\\n rewardTokenSupplyState[address(vToken)].lastRewardingBlock = supplyLastRewardingBlock;\\n emit SupplyLastRewardingBlockUpdated(address(vToken), supplyLastRewardingBlock);\\n }\\n\\n if (currentBorrowLastRewardingBlock != borrowLastRewardingBlock) {\\n rewardTokenBorrowState[address(vToken)].lastRewardingBlock = borrowLastRewardingBlock;\\n emit BorrowLastRewardingBlockUpdated(address(vToken), borrowLastRewardingBlock);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding timestamp for a single market.\\n * @param vToken market's whose reward token last rewarding timestamp to be updated\\n * @param supplyLastRewardingBlockTimestamp New supply-side REWARD TOKEN last rewarding timestamp for market\\n * @param borrowLastRewardingBlockTimestamp New borrow-side REWARD TOKEN last rewarding timestamp for market\\n */\\n function _setLastRewardingBlockTimestamp(\\n VToken vToken,\\n uint256 supplyLastRewardingBlockTimestamp,\\n uint256 borrowLastRewardingBlockTimestamp\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockTimestamp = getBlockNumberOrTimestamp();\\n\\n require(\\n supplyLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"setting last rewarding timestamp in the past is not allowed\\\"\\n );\\n require(\\n borrowLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"setting last rewarding timestamp in the past is not allowed\\\"\\n );\\n\\n uint256 currentSupplyLastRewardingBlockTimestamp = rewardTokenSupplyStateTimeBased[address(vToken)]\\n .lastRewardingTimestamp;\\n uint256 currentBorrowLastRewardingBlockTimestamp = rewardTokenBorrowStateTimeBased[address(vToken)]\\n .lastRewardingTimestamp;\\n\\n require(\\n currentSupplyLastRewardingBlockTimestamp == 0 || currentSupplyLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlockTimestamp == 0 || currentBorrowLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlockTimestamp != supplyLastRewardingBlockTimestamp) {\\n rewardTokenSupplyStateTimeBased[address(vToken)].lastRewardingTimestamp = supplyLastRewardingBlockTimestamp;\\n emit SupplyLastRewardingBlockTimestampUpdated(address(vToken), supplyLastRewardingBlockTimestamp);\\n }\\n\\n if (currentBorrowLastRewardingBlockTimestamp != borrowLastRewardingBlockTimestamp) {\\n rewardTokenBorrowStateTimeBased[address(vToken)].lastRewardingTimestamp = borrowLastRewardingBlockTimestamp;\\n emit BorrowLastRewardingBlockTimestampUpdated(address(vToken), borrowLastRewardingBlockTimestamp);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single market.\\n * @param vToken market's whose reward token rate to be updated\\n * @param supplySpeed New supply-side REWARD TOKEN speed for market\\n * @param borrowSpeed New borrow-side REWARD TOKEN speed for market\\n */\\n function _setRewardTokenSpeed(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n if (rewardTokenSupplySpeeds[address(vToken)] != supplySpeed) {\\n // Supply speed updated so let's update supply state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n _updateRewardTokenSupplyIndex(address(vToken));\\n\\n // Update speed and emit event\\n rewardTokenSupplySpeeds[address(vToken)] = supplySpeed;\\n emit RewardTokenSupplySpeedUpdated(vToken, supplySpeed);\\n }\\n\\n if (rewardTokenBorrowSpeeds[address(vToken)] != borrowSpeed) {\\n // Borrow speed updated so let's update borrow state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n\\n // Update speed and emit event\\n rewardTokenBorrowSpeeds[address(vToken)] = borrowSpeed;\\n emit RewardTokenBorrowSpeedUpdated(vToken, borrowSpeed);\\n }\\n }\\n\\n /**\\n * @notice Calculate REWARD TOKEN 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 REWARD TOKEN to\\n */\\n function _distributeSupplierRewardToken(address vToken, address supplier) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\\n\\n uint256 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\\n uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier];\\n\\n // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenSupplierIndex[vToken][supplier] = supplyIndex;\\n\\n if (supplierIndex == 0 && supplyIndex >= INITIAL_INDEX) {\\n // Covers the case where users supplied tokens before the market's supply state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when supplier rewards were first\\n // set for the market.\\n supplierIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per vToken accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\\n\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerVToken\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n\\n uint256 supplierAccrued = add_(rewardTokenAccrued[supplier], supplierDelta);\\n rewardTokenAccrued[supplier] = supplierAccrued;\\n\\n emit DistributedSupplierRewardToken(VToken(vToken), supplier, supplierDelta, supplierAccrued, supplyIndex);\\n }\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them.\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function _distributeBorrowerRewardToken(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\\n\\n uint256 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\\n uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower];\\n\\n // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenBorrowerIndex[vToken][borrower] = borrowIndex;\\n\\n if (borrowerIndex == 0 && borrowIndex >= INITIAL_INDEX) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when borrower rewards were first\\n // set for the market.\\n borrowerIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per borrowed unit accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\\n\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerBorrowedUnit\\n if (borrowerAmount != 0) {\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n\\n uint256 borrowerAccrued = add_(rewardTokenAccrued[borrower], borrowerDelta);\\n rewardTokenAccrued[borrower] = borrowerAccrued;\\n\\n emit DistributedBorrowerRewardToken(VToken(vToken), borrower, borrowerDelta, borrowerAccrued, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the user.\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all.\\n * @param user The address of the user to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n * @return The amount of REWARD TOKEN which was NOT transferred to the user\\n */\\n function _grantRewardToken(address user, uint256 amount) internal returns (uint256) {\\n uint256 rewardTokenRemaining = rewardToken.balanceOf(address(this));\\n if (amount > 0 && amount <= rewardTokenRemaining) {\\n rewardToken.safeTransfer(user, amount);\\n return 0;\\n }\\n return amount;\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the supply index\\n * @param vToken The market whose supply index to update\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenSupplyIndex(address vToken) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\\n\\n uint256 supplySpeed = rewardTokenSupplySpeeds[vToken];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (!isTimeBased) {\\n safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\");\\n }\\n\\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\\n ? supplyStateTimeBased.lastRewardingTimestamp\\n : uint256(supplyState.lastRewardingBlock);\\n\\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(\\n blockNumberOrTimestamp,\\n (isTimeBased ? supplyStateTimeBased.timestamp : uint256(supplyState.block))\\n );\\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, supplySpeed);\\n Double memory ratio = supplyTokens > 0\\n ? fraction(accruedSinceUpdate, supplyTokens)\\n : Double({ mantissa: 0 });\\n uint224 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\\n uint224 index = safe224(\\n add_(Double({ mantissa: supplyIndex }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n\\n if (isTimeBased) {\\n supplyStateTimeBased.index = index;\\n supplyStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n supplyState.index = index;\\n supplyState.block = uint32(blockNumberOrTimestamp);\\n }\\n } else if (deltaBlocksOrTimestamp > 0) {\\n isTimeBased ? supplyStateTimeBased.timestamp = blockNumberOrTimestamp : supplyState.block = uint32(\\n blockNumberOrTimestamp\\n );\\n }\\n\\n emit RewardTokenSupplyIndexUpdated(vToken);\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the borrow index\\n * @param vToken The market whose borrow index to update\\n * @param marketBorrowIndex The current global borrow index of vToken\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\\n\\n uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (!isTimeBased) {\\n safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\");\\n }\\n\\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\\n ? borrowStateTimeBased.lastRewardingTimestamp\\n : uint256(borrowState.lastRewardingBlock);\\n\\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(\\n blockNumberOrTimestamp,\\n (isTimeBased ? borrowStateTimeBased.timestamp : uint256(borrowState.block))\\n );\\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, borrowSpeed);\\n Double memory ratio = borrowAmount > 0\\n ? fraction(accruedSinceUpdate, borrowAmount)\\n : Double({ mantissa: 0 });\\n uint224 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\\n uint224 index = safe224(\\n add_(Double({ mantissa: borrowIndex }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n\\n if (isTimeBased) {\\n borrowStateTimeBased.index = index;\\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n borrowState.index = index;\\n borrowState.block = uint32(blockNumberOrTimestamp);\\n }\\n } else if (deltaBlocksOrTimestamp > 0) {\\n if (isTimeBased) {\\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n borrowState.block = uint32(blockNumberOrTimestamp);\\n }\\n }\\n\\n emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken called when contract is block-based\\n * @param vToken The address of the vToken to be initialized\\n * @param blockNumber current block number\\n */\\n function _initializeMarketBlockBased(address vToken, uint32 blockNumber) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n RewardToken storage borrowState = rewardTokenBorrowState[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 = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block numbers\\n */\\n supplyState.block = borrowState.block = blockNumber;\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken called when contract is time-based\\n * @param vToken The address of the vToken to be initialized\\n * @param blockTimestamp current block timestamp\\n */\\n function _initializeMarketTimestampBased(address vToken, uint256 blockTimestamp) internal {\\n TimeBasedRewardToken storage supplyState = rewardTokenSupplyStateTimeBased[vToken];\\n TimeBasedRewardToken storage borrowState = rewardTokenBorrowStateTimeBased[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 = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block timestamp\\n */\\n supplyState.timestamp = borrowState.timestamp = blockTimestamp;\\n }\\n}\\n\",\"keccak256\":\"0x3cc824e59c923cfe25c4f1a875959b7e9410cde8e73cd405de13f301298c697f\",\"license\":\"BSD-3-Clause\"},\"contracts/Rewards/RewardsDistributorStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\n\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\n\\n/**\\n * @title RewardsDistributorStorage\\n * @author Venus\\n * @dev Storage for RewardsDistributor\\n */\\ncontract RewardsDistributorStorage {\\n struct RewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number the index was last updated at\\n uint32 block;\\n // The block number at which to stop rewards\\n uint32 lastRewardingBlock;\\n }\\n\\n struct TimeBasedRewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block timestamp the index was last updated at\\n uint256 timestamp;\\n // The block timestamp at which to stop rewards\\n uint256 lastRewardingTimestamp;\\n }\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => RewardToken) public rewardTokenSupplyState;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex;\\n\\n /// @notice The REWARD TOKEN accrued but not yet transferred to each user\\n mapping(address => uint256) public rewardTokenAccrued;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding borrow market per slot (block or second)\\n mapping(address => uint256) public rewardTokenBorrowSpeeds;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding supply market per slot (block or second)\\n mapping(address => uint256) public rewardTokenSupplySpeeds;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => RewardToken) public rewardTokenBorrowState;\\n\\n /// @notice The portion of REWARD TOKEN that each contributor receives per slot (block or second)\\n mapping(address => uint256) public rewardTokenContributorSpeeds;\\n\\n /// @notice Last slot (block or second) at which a contributor's REWARD TOKEN rewards have been allocated\\n mapping(address => uint256) public lastContributorBlock;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex;\\n\\n Comptroller internal comptroller;\\n\\n IERC20Upgradeable public rewardToken;\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => TimeBasedRewardToken) public rewardTokenSupplyStateTimeBased;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => TimeBasedRewardToken) public rewardTokenBorrowStateTimeBased;\\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[37] private __gap;\\n}\\n\",\"keccak256\":\"0x70e5015a78a2acf95277949c8b4796e10b9ac194130be006d5e5217e158070c0\",\"license\":\"BSD-3-Clause\"},\"contracts/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\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 { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"@venusprotocol/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\\\";\\n\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { ComptrollerInterface, ComptrollerViewInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"./ErrorReporter.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title VToken\\n * @author Venus\\n * @notice Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview,\\n * each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of\\n * the pool. The main actions a user regularly interacts with in a market are:\\n\\n- mint/redeem of vTokens;\\n- transfer of vTokens;\\n- borrow/repay a loan on an underlying asset;\\n- liquidate a borrow or liquidate/heal an account.\\n\\n * A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`.\\n * The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted\\n * `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken`\\n * as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that\\n * a user may borrow up to a portion of their collateral determined by the market\\u2019s collateral factor. However, if their borrowed amount exceeds an amount\\n * calculated using the market\\u2019s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also\\n * pay off interest accrued on the borrow.\\n * \\n * The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller`\\n * and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a\\n * total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`.\\n * Both functions settle all of an account\\u2019s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of\\n * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\\n */\\ncontract VToken is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n VTokenInterface,\\n ExponentialNoError,\\n TokenErrorReporter,\\n TimeManagerV8\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5%\\n\\n // Maximum fraction of interest that can be set aside for reserves\\n uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18;\\n\\n // Maximum borrow rate that can ever be applied per slot(block or second)\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n uint256 internal immutable MAX_BORROW_RATE_MANTISSA;\\n\\n /**\\n * Reentrancy Guard **\\n */\\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 * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @param maxBorrowRateMantissa_ The maximum value of borrowing rate mantissa\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(\\n bool timeBased_,\\n uint256 blocksPerYear_,\\n uint256 maxBorrowRateMantissa_\\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n require(maxBorrowRateMantissa_ <= 1e18, \\\"Max borrow rate must be <= 1e18\\\");\\n\\n MAX_BORROW_RATE_MANTISSA = maxBorrowRateMantissa_;\\n _disableInitializers();\\n }\\n\\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_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n */\\n function initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) external initializer {\\n ensureNonzeroAddress(admin_);\\n\\n // Initialize the market\\n _initialize(\\n underlying_,\\n comptroller_,\\n interestRateModel_,\\n initialExchangeRateMantissa_,\\n name_,\\n symbol_,\\n decimals_,\\n admin_,\\n accessControlManager_,\\n riskManagement,\\n reserveFactorMantissa_\\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 * @return success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, msg.sender, dst, amount);\\n return true;\\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 success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, src, dst, amount);\\n return true;\\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 (uint256.max means infinite)\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Increase approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param addedValue The number of additional tokens spender can transfer\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function increaseAllowance(address spender, uint256 addedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 newAllowance = transferAllowances[src][spender];\\n newAllowance += addedValue;\\n transferAllowances[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n return true;\\n }\\n\\n /**\\n * @notice Decreases approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param subtractedValue The number of tokens to remove from total approval\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 currentAllowance = transferAllowances[src][spender];\\n require(currentAllowance >= subtractedValue, \\\"decreased allowance below zero\\\");\\n unchecked {\\n currentAllowance -= subtractedValue;\\n }\\n\\n transferAllowances[src][spender] = currentAllowance;\\n\\n emit Approval(src, spender, currentAllowance);\\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 amount The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint256) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return totalBorrows The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\\n accrueInterest();\\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 borrowBalance The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n return _borrowBalanceStored(account);\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function mint(uint256 mintAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _mintFresh(msg.sender, msg.sender, mintAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param minter User whom the supply will be attributed to\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when minter address is zero\\n */\\n function mintBehalf(address minter, uint256 mintAmount) external override nonReentrant returns (uint256) {\\n ensureNonzeroAddress(minter);\\n\\n accrueInterest();\\n\\n _mintFresh(msg.sender, minter, mintAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function redeem(uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _redeemFresh(msg.sender, msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function redeemBehalf(address redeemer, uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n _ensureSenderIsDelegateOf(redeemer);\\n\\n accrueInterest();\\n\\n _redeemFresh(redeemer, msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\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 receive from redeeming vTokens\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n */\\n function redeemUnderlying(uint256 redeemAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _redeemFresh(msg.sender, msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function redeemUnderlyingBehalf(\\n address redeemer,\\n uint256 redeemAmount\\n ) external override nonReentrant returns (uint256) {\\n _ensureSenderIsDelegateOf(redeemer);\\n\\n accrueInterest();\\n\\n _redeemFresh(redeemer, msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function borrow(uint256 borrowAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _borrowFresh(msg.sender, msg.sender, borrowAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error DelegateNotApproved is thrown if caller is not approved delegate\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function borrowBehalf(address borrower, uint256 borrowAmount) external override returns (uint256) {\\n _ensureSenderIsDelegateOf(borrower);\\n accrueInterest();\\n\\n _borrowFresh(borrower, msg.sender, borrowAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrow(uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n return NO_ERROR;\\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, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _repayBorrowFresh(msg.sender, borrower, repayAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Not restricted\\n */\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external override returns (uint256) {\\n _liquidateBorrow(msg.sender, borrower, repayAmount, vTokenCollateral, false);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice sets protocol share accumulated from liquidations\\n * @dev must be equal or less than liquidation incentive - 1\\n * @param newProtocolSeizeShareMantissa_ new protocol share mantissa\\n * @custom:event Emits NewProtocolSeizeShare event on success\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error ProtocolSeizeShareTooBig is thrown when the new seize share is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa_) external {\\n _checkAccessAllowed(\\\"setProtocolSeizeShare(uint256)\\\");\\n uint256 liquidationIncentive = ComptrollerViewInterface(address(comptroller)).liquidationIncentiveMantissa();\\n if (newProtocolSeizeShareMantissa_ + MANTISSA_ONE > liquidationIncentive) {\\n revert ProtocolSeizeShareTooBig();\\n }\\n\\n uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\\n protocolSeizeShareMantissa = newProtocolSeizeShareMantissa_;\\n emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa_);\\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 * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n * @custom:event Emits NewReserveFactor event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant {\\n _checkAccessAllowed(\\\"setReserveFactor(uint256)\\\");\\n\\n accrueInterest();\\n _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to the protocol reserve contract\\n * @dev Gracefully return if reserves already reduced in accrueInterest\\n * @param reduceAmount Amount of reduction to reserves\\n * @custom:event Emits ReservesReduced event; may emit AccrueInterest\\n * @custom:error ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash\\n * @custom:error ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\\n * @custom:access Not restricted\\n */\\n function reduceReserves(uint256 reduceAmount) external override nonReentrant {\\n accrueInterest();\\n if (reduceReservesBlockNumber == getBlockNumberOrTimestamp()) return;\\n _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice The sender adds to reserves.\\n * @param addAmount The amount of underlying token to add as reserves\\n * @custom:event Emits ReservesAdded event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function addReserves(uint256 addAmount) external override nonReentrant {\\n accrueInterest();\\n _addReservesFresh(addAmount);\\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 * @custom:event Emits NewMarketInterestRateModel event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external override {\\n _checkAccessAllowed(\\\"setInterestRateModel(address)\\\");\\n\\n accrueInterest();\\n _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially\\n * \\\"forgiving\\\" the borrower. Healing is a situation that should rarely happen. However, some pools\\n * may list risky assets or be configured improperly \\u2013 we want to still handle such cases gracefully.\\n * We assume that Comptroller does the seizing, so this function is only available to Comptroller.\\n * @dev This function does not call any Comptroller hooks (like \\\"healAllowed\\\"), because we assume\\n * the Comptroller does all the necessary checks before calling this function.\\n * @param payer account who repays the debt\\n * @param borrower account to heal\\n * @param repayAmount amount to repay\\n * @custom:event Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\\n * @custom:error HealBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:access Only Comptroller\\n */\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external override nonReentrant {\\n if (repayAmount != 0) {\\n comptroller.preRepayHook(address(this), borrower);\\n }\\n\\n if (msg.sender != address(comptroller)) {\\n revert HealBorrowUnauthorized();\\n }\\n\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 totalBorrowsNew = totalBorrows;\\n\\n uint256 actualRepayAmount;\\n if (repayAmount != 0) {\\n // _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // We violate checks-effects-interactions here to account for tokens that take transfer fees\\n actualRepayAmount = _doTransferIn(payer, repayAmount);\\n totalBorrowsNew = totalBorrowsNew - actualRepayAmount;\\n emit RepayBorrow(\\n payer,\\n borrower,\\n actualRepayAmount,\\n accountBorrowsPrev - actualRepayAmount,\\n totalBorrowsNew\\n );\\n }\\n\\n // The transaction will fail if trying to repay too much\\n uint256 badDebtDelta = accountBorrowsPrev - actualRepayAmount;\\n if (badDebtDelta != 0) {\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld + badDebtDelta;\\n totalBorrowsNew = totalBorrowsNew - badDebtDelta;\\n badDebt = badDebtNew;\\n\\n // We treat healing as \\\"repayment\\\", where vToken is the payer\\n emit RepayBorrow(address(this), borrower, badDebtDelta, 0, totalBorrowsNew);\\n emit BadDebtIncreased(borrower, badDebtDelta, badDebtOld, badDebtNew);\\n }\\n\\n accountBorrows[borrower].principal = 0;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n emit HealBorrow(payer, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice The extended version of liquidations, callable only by Comptroller. May skip\\n * the close factor check. The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Only Comptroller\\n */\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) external override {\\n if (msg.sender != address(comptroller)) {\\n revert ForceLiquidateBorrowUnauthorized();\\n }\\n _liquidateBorrow(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\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 * @custom:event Emits Transfer, ReservesAdded events\\n * @custom:error LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:access Not restricted\\n */\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external override nonReentrant {\\n _seize(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Updates bad debt\\n * @dev Called only when bad debt is recovered from auction\\n * @param recoveredAmount_ The amount of bad debt recovered\\n * @custom:event Emits BadDebtRecovered event\\n * @custom:access Only Shortfall contract\\n */\\n function badDebtRecovered(uint256 recoveredAmount_) external {\\n require(msg.sender == shortfall, \\\"only shortfall contract can update bad debt\\\");\\n require(recoveredAmount_ <= badDebt, \\\"more than bad debt recovered from auction\\\");\\n\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld - recoveredAmount_;\\n badDebt = badDebtNew;\\n\\n emit BadDebtRecovered(badDebtOld, badDebtNew);\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protocolShareReserve_ The address of the protocol share reserve contract\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n * @custom:access Only Governance\\n */\\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\\n _setProtocolShareReserve(protocolShareReserve_);\\n }\\n\\n /**\\n * @notice Sets shortfall contract address\\n * @param shortfall_ The address of the shortfall contract\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:access Only Governance\\n */\\n function setShortfallContract(address shortfall_) external onlyOwner {\\n _setShortfallContract(shortfall_);\\n }\\n\\n /**\\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\\n * @param token The address of the ERC-20 token to sweep\\n * @custom:access Only Governance\\n */\\n function sweepToken(IERC20Upgradeable token) external override {\\n require(msg.sender == owner(), \\\"VToken::sweepToken: only admin can sweep tokens\\\");\\n require(address(token) != underlying, \\\"VToken::sweepToken: can not sweep underlying token\\\");\\n uint256 balance = token.balanceOf(address(this));\\n token.safeTransfer(owner(), balance);\\n\\n emit SweepToken(address(token));\\n }\\n\\n /**\\n * @notice A public function to set new threshold of slot(block or second) difference after which funds will be sent to the protocol share reserve\\n * @param _newReduceReservesBlockOrTimestampDelta slot(block or second) difference value\\n * @custom:access Only Governance\\n */\\n function setReduceReservesBlockDelta(uint256 _newReduceReservesBlockOrTimestampDelta) external {\\n _checkAccessAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n require(_newReduceReservesBlockOrTimestampDelta > 0, \\\"Invalid Input\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, _newReduceReservesBlockOrTimestampDelta);\\n reduceReservesBlockDelta = _newReduceReservesBlockOrTimestampDelta;\\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 amount 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 amount 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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return vTokenBalance User's balance of vTokens\\n * @return borrowBalance Amount owed in terms of underlying\\n * @return exchangeRate Stored exchange rate\\n */\\n function getAccountSnapshot(\\n address account\\n )\\n external\\n view\\n override\\n returns (uint256 error, uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRate)\\n {\\n return (NO_ERROR, accountTokens[account], _borrowBalanceStored(account), _exchangeRateStored());\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return cash The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint256) {\\n return _getCashPrior();\\n }\\n\\n /**\\n * @notice Returns the current per slot(block or second) borrow interest rate for this vToken\\n * @return rate The borrow interest rate per slot(block or second), scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint256) {\\n return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt);\\n }\\n\\n /**\\n * @notice Returns the current per-slot(block or second) supply interest rate for this v\\n * @return rate The supply interest rate per slot(block or second), scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint256) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPrior(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa,\\n badDebt\\n );\\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 borrowBalance The calculated balance\\n */\\n function borrowBalanceStored(address account) external view override returns (uint256) {\\n return _borrowBalanceStored(account);\\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 exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() external view override returns (uint256) {\\n return _exchangeRateStored();\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\\n accrueInterest();\\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 slot(block or second)\\n * up to the current slot(block or second) and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentSlot - reduceReservesBlockNumber >= slotDelta\\n * @return Always NO_ERROR\\n * @custom:event Emits AccrueInterest event on success\\n * @custom:access Not restricted\\n */\\n function accrueInterest() public virtual override returns (uint256) {\\n /* Remember the initial block number or timestamp */\\n uint256 currentSlotNumber = getBlockNumberOrTimestamp();\\n uint256 accrualSlotNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualSlotNumberPrior == currentSlotNumber) {\\n return NO_ERROR;\\n }\\n\\n /* Read the previous values out of storage */\\n uint256 cashPrior = _getCashPrior();\\n uint256 borrowsPrior = totalBorrows;\\n uint256 reservesPrior = totalReserves;\\n uint256 borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt);\\n require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of slots elapsed since the last accrual */\\n uint256 slotDelta = currentSlotNumber - accrualSlotNumberPrior;\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * slotDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), slotDelta);\\n uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\\n uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;\\n uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentSlotNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n if (currentSlotNumber - reduceReservesBlockNumber >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentSlotNumber;\\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 NO_ERROR;\\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 or timestamp\\n * @param payer The address of the account which is sending the assets for supply\\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 */\\n function _mintFresh(address payer, address minter, uint256 mintAmount) internal {\\n /* Fail if mint not allowed */\\n comptroller.preMintHook(address(this), minter, mintAmount);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert MintFreshnessCheck();\\n }\\n\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\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 * `_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 uint256 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 uint256 mintTokens = div_(actualMintAmount, exchangeRate);\\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 * And write them into storage\\n */\\n totalSupply = totalSupply + mintTokens;\\n uint256 balanceAfter = accountTokens[minter] + mintTokens;\\n accountTokens[minter] = balanceAfter;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, actualMintAmount, mintTokens, balanceAfter);\\n emit Transfer(address(0), minter, mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, actualMintAmount, mintTokens);\\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 Comptroller.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current slot(block or second)\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the underlying 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 */\\n function _redeemFresh(address redeemer, address receiver, uint256 redeemTokensIn, uint256 redeemAmountIn) internal {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert RedeemFreshnessCheck();\\n }\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n\\n uint256 redeemTokens;\\n uint256 redeemAmount;\\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 */\\n redeemTokens = redeemTokensIn;\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n */\\n redeemTokens = div_(redeemAmountIn, exchangeRate);\\n\\n uint256 _redeemAmount = mul_(redeemTokens, exchangeRate);\\n if (_redeemAmount != 0 && _redeemAmount != redeemAmountIn) redeemTokens++; // round up\\n }\\n\\n // redeemAmount = exchangeRate * redeemTokens\\n redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokens);\\n\\n // Revert if amount is zero\\n if (redeemAmount == 0) {\\n revert(\\\"redeemAmount is zero\\\");\\n }\\n\\n /* Fail if redeem not allowed */\\n comptroller.preRedeemHook(address(this), redeemer, redeemTokens);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (_getCashPrior() - totalReserves < redeemAmount) {\\n revert RedeemTransferOutNotPossible();\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\\n */\\n totalSupply = totalSupply - redeemTokens;\\n uint256 balanceAfter = accountTokens[redeemer] - redeemTokens;\\n accountTokens[redeemer] = balanceAfter;\\n\\n /*\\n * We invoke _doTransferOut for the receiver and the redeemAmount.\\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 _doTransferOut(receiver, redeemAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), redeemTokens);\\n emit Redeem(redeemer, redeemAmount, redeemTokens, balanceAfter);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, redeemAmount, redeemTokens);\\n }\\n\\n /**\\n * @notice Users or their delegates borrow assets from the protocol\\n * @param borrower User who borrows the assets\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param borrowAmount The amount of the underlying asset to borrow\\n */\\n function _borrowFresh(address borrower, address receiver, uint256 borrowAmount) internal {\\n /* Fail if borrow not allowed */\\n comptroller.preBorrowHook(address(this), borrower, borrowAmount);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert BorrowFreshnessCheck();\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (_getCashPrior() - totalReserves < borrowAmount) {\\n revert BorrowCashNotAvailable();\\n }\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowNew = accountBorrow + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;\\n uint256 totalBorrowsNew = totalBorrows + borrowAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\\n `*/\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /*\\n * We invoke _doTransferOut for the receiver and the borrowAmount.\\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, accountBorrowsNew, totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\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 underlying tokens being returned, or type(uint256).max for the full outstanding amount\\n * @return (uint) the actual repayment amount.\\n */\\n function _repayBorrowFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256) {\\n /* Fail if repayBorrow not allowed */\\n comptroller.preRepayHook(address(this), borrower);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert RepayBorrowFreshnessCheck();\\n }\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n\\n uint256 repayAmountFinal = repayAmount >= accountBorrowsPrev ? accountBorrowsPrev : 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 * 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 uint256 actualRepayAmount = _doTransferIn(payer, repayAmountFinal);\\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 uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\\n uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, actualRepayAmount, borrowIndex);\\n\\n return actualRepayAmount;\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal nonReentrant {\\n accrueInterest();\\n\\n uint256 error = vTokenCollateral.accrueInterest();\\n if (error != NO_ERROR) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n revert LiquidateAccrueCollateralInterestFailed(error);\\n }\\n\\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal {\\n /* Fail if liquidate not allowed */\\n comptroller.preLiquidateHook(\\n address(this),\\n address(vTokenCollateral),\\n borrower,\\n repayAmount,\\n skipLiquidityCheck\\n );\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert LiquidateFreshnessCheck();\\n }\\n\\n /* Verify vTokenCollateral market's slot(block or second) number equals current slot(block or second) number */\\n if (vTokenCollateral.accrualBlockNumber() != getBlockNumberOrTimestamp()) {\\n revert LiquidateCollateralFreshnessCheck();\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateLiquidatorIsBorrower();\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n revert LiquidateCloseAmountIsZero();\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n revert LiquidateCloseAmountIsUintMax();\\n }\\n\\n /* Fail if repayBorrow fails */\\n uint256 actualRepayAmount = _repayBorrowFresh(liquidator, borrower, repayAmount);\\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.liquidateCalculateSeizeTokens(\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n require(amountSeizeError == 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, call _seize internally to avoid re-entrancy, otherwise make an external call\\n if (address(vTokenCollateral) == address(this)) {\\n _seize(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\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\\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 * It's absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerContract The contract seizing the collateral (either borrowed vToken or Comptroller)\\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 */\\n function _seize(address seizerContract, address liquidator, address borrower, uint256 seizeTokens) internal {\\n /* Fail if seize not allowed */\\n comptroller.preSeizeHook(address(this), seizerContract, liquidator, borrower);\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateSeizeLiquidatorIsBorrower();\\n }\\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 uint256 liquidationIncentiveMantissa = ComptrollerViewInterface(address(comptroller))\\n .liquidationIncentiveMantissa();\\n uint256 numerator = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));\\n uint256 protocolSeizeTokens = div_(numerator, Exp({ mantissa: liquidationIncentiveMantissa }));\\n uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n uint256 protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the calculated values into storage */\\n totalSupply = totalSupply - protocolSeizeTokens;\\n accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\\n accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\\n\\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, protocolSeizeAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.LIQUIDATION\\n );\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\\n emit ProtocolSeize(borrower, protocolShareReserve, protocolSeizeAmount);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerContract, liquidator, borrower, seizeTokens);\\n }\\n\\n function _setComptroller(ComptrollerInterface newComptroller) internal {\\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\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n */\\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal {\\n // Verify market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert SetReserveFactorFreshCheck();\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > MAX_RESERVE_FACTOR_MANTISSA) {\\n revert SetReserveFactorBoundsCheck();\\n }\\n\\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\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 actualAddAmount The actual amount added, excluding the potential token fees\\n */\\n function _addReservesFresh(uint256 addAmount) internal returns (uint256) {\\n // totalReserves + actualAddAmount\\n uint256 totalReservesNew;\\n uint256 actualAddAmount;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert AddReservesFactorFreshCheck(actualAddAmount);\\n }\\n\\n actualAddAmount = _doTransferIn(msg.sender, addAmount);\\n totalReservesNew = totalReserves + actualAddAmount;\\n totalReserves = totalReservesNew;\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n return actualAddAmount;\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to the protocol reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n */\\n function _reduceReservesFresh(uint256 reduceAmount) internal {\\n if (reduceAmount == 0) {\\n return;\\n }\\n // totalReserves - reduceAmount\\n uint256 totalReservesNew;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert ReduceReservesFreshCheck();\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (_getCashPrior() < reduceAmount) {\\n revert ReduceReservesCashNotAvailable();\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n revert ReduceReservesCashValidation();\\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 // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, reduceAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit SpreadReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal {\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert SetInterestRateModelFreshCheck();\\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\\n /**\\n * Safe Token **\\n */\\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 returns (uint256) {\\n IERC20Upgradeable token = IERC20Upgradeable(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 to, uint256 amount) internal virtual {\\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\\n token.safeTransfer(to, amount);\\n }\\n\\n /**\\n * @notice Transfer `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 */\\n function _transferTokens(address spender, address src, address dst, uint256 tokens) internal {\\n /* Fail if transfer not allowed */\\n comptroller.preTransferHook(address(this), src, dst, tokens);\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n revert TransferNotAllowed();\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint256 startingAllowance;\\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 uint256 allowanceNew = startingAllowance - tokens;\\n uint256 srcTokensNew = accountTokens[src] - tokens;\\n uint256 dstTokensNew = accountTokens[dst] + tokens;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n\\n accountTokens[src] = srcTokensNew;\\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\\n /**\\n * @notice Initialize the 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_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n */\\n function _initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\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 _setComptroller(comptroller_);\\n\\n // Initialize slot(block or second) number and borrow index (slot(block or second) number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumberOrTimestamp();\\n borrowIndex = MANTISSA_ONE;\\n\\n // Set the interest rate model (depends on slot(block or second) number / borrow index)\\n _setInterestRateModelFresh(interestRateModel_);\\n\\n _setReserveFactorFresh(reserveFactorMantissa_);\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n _setShortfallContract(riskManagement.shortfall);\\n _setProtocolShareReserve(riskManagement.protocolShareReserve);\\n protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA;\\n\\n // Set underlying and sanity check it\\n underlying = underlying_;\\n IERC20Upgradeable(underlying).totalSupply();\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n _transferOwnership(admin_);\\n }\\n\\n function _setShortfallContract(address shortfall_) internal {\\n ensureNonzeroAddress(shortfall_);\\n address oldShortfall = shortfall;\\n shortfall = shortfall_;\\n emit NewShortfallContract(oldShortfall, shortfall_);\\n }\\n\\n function _setProtocolShareReserve(address payable protocolShareReserve_) internal {\\n ensureNonzeroAddress(protocolShareReserve_);\\n address oldProtocolShareReserve = address(protocolShareReserve);\\n protocolShareReserve = protocolShareReserve_;\\n emit NewProtocolShareReserve(oldProtocolShareReserve, address(protocolShareReserve_));\\n }\\n\\n function _ensureSenderIsDelegateOf(address user) internal view {\\n if (!ComptrollerViewInterface(address(comptroller)).approvedDelegates(user, msg.sender)) {\\n revert DelegateNotApproved();\\n }\\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 virtual returns (uint256) {\\n return IERC20Upgradeable(underlying).balanceOf(address(this));\\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 borrowBalance the calculated balance\\n */\\n function _borrowBalanceStored(address account) internal view returns (uint256) {\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot memory 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 0;\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;\\n\\n return principalTimesIndex / borrowSnapshot.interestIndex;\\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 exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function _exchangeRateStored() internal view virtual returns (uint256) {\\n uint256 _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return initialExchangeRateMantissa;\\n }\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply\\n */\\n uint256 totalCash = _getCashPrior();\\n uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;\\n uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply;\\n\\n return exchangeRate;\\n }\\n}\\n\",\"keccak256\":\"0xa220ca317fe69b920b86e43f054c43b5f891f12160fd312c9a21668f969ee056\",\"license\":\"BSD-3-Clause\"},\"contracts/VTokenInterfaces.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\\nimport { ComptrollerInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title VTokenStorage\\n * @author Venus\\n * @notice Storage layout used by the `VToken` contract\\n */\\n// solhint-disable-next-line max-states-count\\ncontract VTokenStorage {\\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 uint256 principal;\\n uint256 interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\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 Protocol share Reserve contract address\\n */\\n address payable public protocolShareReserve;\\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 InterestRateModel public interestRateModel;\\n\\n // Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n uint256 internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint256 public reserveFactorMantissa;\\n\\n /**\\n * @notice Slot(block or second) number that interest was last accrued at\\n */\\n uint256 public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint256 public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint256 public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint256 public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint256 public totalSupply;\\n\\n /**\\n * @notice Total bad debt of the market\\n */\\n uint256 public badDebt;\\n\\n // Official record of token balances for each account\\n mapping(address => uint256) internal accountTokens;\\n\\n // Approved token transfer amounts on behalf of others\\n mapping(address => mapping(address => uint256)) internal transferAllowances;\\n\\n // Mapping of account addresses to outstanding borrow balances\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint256 public protocolSeizeShareMantissa;\\n\\n /**\\n * @notice Storage of Shortfall contract address\\n */\\n address public shortfall;\\n\\n /**\\n * @notice delta slot (block or second) after which reserves will be reduced\\n */\\n uint256 public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last slot (block or second) number at which reserves were reduced\\n */\\n uint256 public reduceReservesBlockNumber;\\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\\n/**\\n * @title VTokenInterface\\n * @author Venus\\n * @notice Interface implemented by the `VToken` contract\\n */\\nabstract contract VTokenInterface is VTokenStorage {\\n struct RiskManagementInit {\\n address shortfall;\\n address payable protocolShareReserve;\\n }\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address indexed minter, uint256 mintAmount, uint256 mintTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address indexed borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(\\n address indexed payer,\\n address indexed borrower,\\n uint256 repayAmount,\\n uint256 accountBorrows,\\n uint256 totalBorrows\\n );\\n\\n /**\\n * @notice Event emitted when bad debt is accumulated on a market\\n * @param borrower borrower to \\\"forgive\\\"\\n * @param badDebtDelta amount of new bad debt recorded\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtIncreased(address indexed borrower, uint256 badDebtDelta, uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when bad debt is recovered via an auction\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtRecovered(uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address indexed liquidator,\\n address indexed borrower,\\n uint256 repayAmount,\\n address indexed vTokenCollateral,\\n uint256 seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface indexed oldComptroller, ComptrollerInterface indexed newComptroller);\\n\\n /**\\n * @notice Event emitted when shortfall contract address is changed\\n */\\n event NewShortfallContract(address indexed oldShortfall, address indexed newShortfall);\\n\\n /**\\n * @notice Event emitted when protocol share reserve contract address is changed\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModel indexed oldInterestRateModel,\\n InterestRateModel indexed newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when protocol seize share is changed\\n */\\n event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address indexed benefactor, uint256 addAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the spread reserves are reduced\\n */\\n event SpreadReservesReduced(address indexed protocolShareReserve, uint256 reduceAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /**\\n * @notice Event emitted when healing the borrow\\n */\\n event HealBorrow(address indexed payer, address indexed borrower, uint256 repayAmount);\\n\\n /**\\n * @notice Event emitted when tokens are swept\\n */\\n event SweepToken(address indexed token);\\n\\n /**\\n * @notice Event emitted when reduce reserves slot (block or second) delta is changed\\n */\\n event NewReduceReservesBlockDelta(\\n uint256 oldReduceReservesBlockOrTimestampDelta,\\n uint256 newReduceReservesBlockOrTimestampDelta\\n );\\n\\n /**\\n * @notice Event emitted when liquidation reserves are reduced\\n */\\n event ProtocolSeize(address indexed from, address indexed to, uint256 amount);\\n\\n /*** User Interface ***/\\n\\n function mint(uint256 mintAmount) external virtual returns (uint256);\\n\\n function mintBehalf(address minter, uint256 mintAllowed) external virtual returns (uint256);\\n\\n function redeem(uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemBehalf(address redeemer, uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);\\n\\n function redeemUnderlyingBehalf(address redeemer, uint256 redeemAmount) external virtual returns (uint256);\\n\\n function borrow(uint256 borrowAmount) external virtual returns (uint256);\\n\\n function borrowBehalf(address borrwwer, uint256 borrowAmount) external virtual returns (uint256);\\n\\n function repayBorrow(uint256 repayAmount) external virtual returns (uint256);\\n\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external virtual returns (uint256);\\n\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external virtual;\\n\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipCloseFactorCheck\\n ) external virtual;\\n\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external virtual;\\n\\n function transfer(address dst, uint256 amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint256 amount) external virtual returns (bool);\\n\\n function accrueInterest() external virtual returns (uint256);\\n\\n function sweepToken(IERC20Upgradeable token) external virtual;\\n\\n /*** Admin Functions ***/\\n\\n function setReserveFactor(uint256 newReserveFactorMantissa) external virtual;\\n\\n function reduceReserves(uint256 reduceAmount) external virtual;\\n\\n function exchangeRateCurrent() external virtual returns (uint256);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint256);\\n\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external virtual;\\n\\n function addReserves(uint256 addAmount) external virtual;\\n\\n function totalBorrowsCurrent() external virtual returns (uint256);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint256);\\n\\n function approve(address spender, uint256 amount) external virtual returns (bool);\\n\\n function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool);\\n\\n function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint256);\\n\\n function balanceOf(address owner) external view virtual returns (uint256);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint256, uint256, uint256, uint256);\\n\\n function borrowRatePerBlock() external view virtual returns (uint256);\\n\\n function supplyRatePerBlock() external view virtual returns (uint256);\\n\\n function borrowBalanceStored(address account) external view virtual returns (uint256);\\n\\n function exchangeRateStored() external view virtual returns (uint256);\\n\\n function getCash() external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is a VToken contract (for inspection)\\n * @return Always true\\n */\\n function isVToken() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x7c4cbb879e3a931cfee4fa7a9eb1978eddff18087a1c4f56decedb84c2479f1e\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\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\",\"keccak256\":\"0x54ab3a6f3bc87569ed12370f3470a1ec84cea9796d4d0ccf3d07dd4280c044aa\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/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 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\",\"keccak256\":\"0x93bdd5cfb100f0f9a1d446857e23c3633df6ab12c266333c978428edd96b1367\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x60e060405234801561001057600080fd5b50604051613ffc380380613ffc83398101604081905261002f916100dc565b81818115801561003d575080155b1561005b576040516302723dfb60e21b815260040160405180910390fd5b81801561006757508015155b156100855760405163ae0fcab360e01b815260040160405180910390fd5b81151560a05281610096578061009c565b6301e133805b608052816100b3576100d460201b611d89176100be565b6100d860201b611d8d175b6001600160401b031660c0525061010f92505050565b4390565b4290565b600080604083850312156100ef57600080fd5b825180151581146100ff57600080fd5b6020939093015192949293505050565b60805160a05160c051613eb76101456000396000611d5d0152600081816102a60152611e5e015260006101d10152613eb76000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c80637c51b64211610097578063c7ad089511610066578063c7ad0895146102a1578063d77ebf96146102d8578063e0a67f11146102f8578063e1d146fb1461031857600080fd5b80637c51b642146102215780637c84e3b314610241578063aa5dbd2314610261578063b31242391461028157600080fd5b806347d86a81116100d357806347d86a811461018e57806355dd9515146101a15780636857249c146101cc5780637a27db571461020157600080fd5b80630d3ae318146101055780631f884fdf1461012e578063345954dc1461014e5780633e3e399c1461016e575b600080fd5b610118610113366004612ece565b610320565b604051610125919061323b565b60405180910390f35b61014161013c366004613299565b610655565b60405161012591906132da565b61016161015c36600461333a565b61071d565b6040516101259190613357565b61018161017c36600461333a565b610850565b60405161012591906133bb565b61011861019c366004613445565b610bc2565b6101b46101af36600461347e565b610c49565b6040516001600160a01b039091168152602001610125565b6101f37f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610125565b61021461020f366004613445565b610cc9565b60405161012591906134c9565b61023461022f3660046135a5565b610fd6565b6040516101259190613630565b61025461024f36600461333a565b61108f565b604051610125919061367e565b61027461026f36600461333a565b6111f9565b604051610125919061369e565b61029461028f366004613445565b611947565b60405161012591906136ad565b6102c87f000000000000000000000000000000000000000000000000000000000000000081565b6040519015158152602001610125565b6102eb6102e6366004613445565b611c2e565b60405161012591906136bb565b61030b61030636600461371f565b611ca1565b60405161012591906137b8565b6101f3611d56565b610328612c95565b6000826040015190506000816001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610371573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261039991908101906137fb565b905060006103a682611ca1565b60408681015190516328ebbe8b60e21b81526001600160a01b039182166004820152919250879160009183169063a3aefa2c90602401600060405180830381865afa1580156103f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261042191908101906138ce565b90506000876040015190506000604051806101a001604052808a6000015181526020018a602001516001600160a01b031681526020018a604001516001600160a01b031681526020018a6060015181526020018a608001518152602001846000015181526020018460200151815260200184604001518152602001836001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104fe9190613982565b6001600160a01b03168152602001836001600160a01b031663e87554466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561054a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061056e919061399f565b8152602001836001600160a01b0316634ada90af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d5919061399f565b8152602001836001600160a01b031663db5c65de6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610618573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063c919061399f565b8152602001959095525092955050505050505b92915050565b6060816000816001600160401b0381111561067257610672612e17565b6040519080825280602002602001820160405280156106b757816020015b60408051808201909152600080825260208201528152602001906001900390816106905790505b50905060005b82811015610714576106ef8686838181106106da576106da6139b8565b905060200201602081019061024f919061333a565b828281518110610701576107016139b8565b60209081029190910101526001016106bd565b50949350505050565b606060008290506000816001600160a01b031663d88ff1f46040518163ffffffff1660e01b8152600401600060405180830381865afa158015610764573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261078c9190810190613a51565b80519091506000816001600160401b038111156107ab576107ab612e17565b6040519080825280602002602001820160405280156107e457816020015b6107d1612c95565b8152602001906001900390816107c95790505b50905060005b82811015610846576000848281518110610806576108066139b8565b60200260200101519050600061081c8983610320565b905080848481518110610831576108316139b8565b602090810291909101015250506001016107ea565b5095945050505050565b604080516060808201835260008083526020830152918101919091526000808390506000816001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156108b2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108da91908101906137fb565b90506000826001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561091c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109409190613982565b9050600082516001600160401b0381111561095d5761095d612e17565b6040519080825280602002602001820160405280156109a257816020015b604080518082019091526000808252602082015281526020019060019003908161097b5790505b5090506109d2604051806060016040528060006001600160a01b0316815260200160008152602001606081525090565b6001600160a01b03881681526040810182905260005b8451811015610bae576040805180820190915260008082526020820152858281518110610a1757610a176139b8565b602002602001015181600001906001600160a01b031690816001600160a01b031681525050670de0b6b3a7640000856001600160a01b031663fc57d4df888581518110610a6657610a666139b8565b60200260200101516040518263ffffffff1660e01b8152600401610a9991906001600160a01b0391909116815260200190565b602060405180830381865afa158015610ab6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ada919061399f565b878481518110610aec57610aec6139b8565b60200260200101516001600160a01b031663bbcac5576040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b55919061399f565b610b5f9190613b17565b610b699190613b2e565b60208201526040830151805182919084908110610b8857610b886139b8565b6020026020010181905250806020015188610ba39190613b50565b9750506001016109e8565b506020810195909552509295945050505050565b610bca612c95565b604051637aee632d60e01b81526001600160a01b0383811660048301528491610c4191839190821690637aee632d90602401600060405180830381865afa158015610c19573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526101139190810190613b63565b949350505050565b60405163266e0a7f60e01b81526001600160a01b0383811660048301528281166024830152600091859182169063266e0a7f90604401602060405180830381865afa158015610c9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc09190613982565b95945050505050565b60606000826001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610d0b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d3391908101906137fb565b90506000836001600160a01b03166361252fd16040518163ffffffff1660e01b8152600401600060405180830381865afa158015610d75573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d9d9190810190613b97565b9050600081516001600160401b03811115610dba57610dba612e17565b604051908082528060200260200182016040528015610e0b57816020015b6040805160808101825260008082526020808301829052928201526060808201528252600019909201910181610dd85790505b50905060005b8251811015610846576040805160808101825260008082526020820181905291810191909152606080820152838281518110610e4f57610e4f6139b8565b60209081029190910101516001600160a01b031681528351849083908110610e7957610e796139b8565b60200260200101516001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ebe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee29190613982565b6001600160a01b031660208201528351849083908110610f0457610f046139b8565b6020908102919091010151604051631627ee8960e01b81526001600160a01b038a8116600483015290911690631627ee8990602401602060405180830381865afa158015610f56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7a919061399f565b816040018181525050610fa78886868581518110610f9a57610f9a6139b8565b6020026020010151611d91565b816060018190525080838381518110610fc257610fc26139b8565b602090810291909101015250600101610e11565b6060826000816001600160401b03811115610ff357610ff3612e17565b60405190808252806020026020018201604052801561102c57816020015b611019612d18565b8152602001906001900390816110115790505b50905060005b828110156108465761106a87878381811061104f5761104f6139b8565b9050602002016020810190611064919061333a565b86611947565b82828151811061107c5761107c6139b8565b6020908102919091010152600101611032565b60408051808201909152600080825260208201526000826001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111079190613982565b90506000816001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611149573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116d9190613982565b6040805180820182526001600160a01b03808816808352925163fc57d4df60e01b815260048101939093529293509160208301919084169063fc57d4df90602401602060405180830381865afa1580156111cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ef919061399f565b9052949350505050565b611201612d57565b6000826001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611241573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611265919061399f565b90506000836001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cb9190613982565b604051638e8f294b60e01b81526001600160a01b03868116600483015291925082916000918291841690638e8f294b906024016040805180830381865afa15801561131a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133e9190613c35565b915091506000876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a69190613982565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061140c9190613c61565b60ff1690506000805b600860ff8216116114d2576000886001600160a01b031663e85a29608d8460ff16600881111561144757611447613c84565b6040518363ffffffff1660e01b8152600401611464929190613c9a565b602060405180830381865afa158015611481573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a59190613cd5565b6114b05760006114b3565b60015b60ff9081169083161b9290921791506114cb81613cf0565b9050611415565b506040518061022001604052808b6001600160a01b031681526020018981526020018b6001600160a01b031663ae9d70b06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611532573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611556919061399f565b81526020018b6001600160a01b031663f8f9da286040518163ffffffff1660e01b8152600401602060405180830381865afa158015611599573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115bd919061399f565b81526020018b6001600160a01b031663173b99046040518163ffffffff1660e01b8152600401602060405180830381865afa158015611600573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611624919061399f565b81526040516302c3bcbb60e01b81526001600160a01b038d811660048301526020909201918916906302c3bcbb90602401602060405180830381865afa158015611672573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611696919061399f565b815260405163252c221960e11b81526001600160a01b038d81166004830152602090920191891690634a58443290602401602060405180830381865afa1580156116e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611708919061399f565b81526020018b6001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561174b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176f919061399f565b81526020018b6001600160a01b0316638f840ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117d6919061399f565b81526020018b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611819573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061183d919061399f565b81526020018b6001600160a01b0316633b1d21a26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611880573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118a4919061399f565b81526020018615158152602001858152602001846001600160a01b031681526020018b6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611904573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119289190613c61565b60ff168152602081019390935260409092015298975050505050505050565b61194f612d18565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908516906370a0823190602401602060405180830381865afa158015611999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119bd919061399f565b6040516305eff7ef60e21b81526001600160a01b0385811660048301529192506000918616906317bfdfbc906024016020604051808303816000875af1158015611a0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a2f919061399f565b604051633af9e66960e01b81526001600160a01b038681166004830152919250600091871690633af9e669906024016020604051808303816000875af1158015611a7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa1919061399f565b90506000806000886001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0a9190613982565b6040516370a0823160e01b81526001600160a01b038a81166004830152919250908216906370a0823190602401602060405180830381865afa158015611b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b78919061399f565b604051636eb1769f60e11b81526001600160a01b038a811660048301528b811660248301529194509082169063dd62ed3e90604401602060405180830381865afa158015611bca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bee919061399f565b6040805160c0810182526001600160a01b038c168152602081019890985287019590955250506060840191909152608083015260a0820152905092915050565b604051631e6db74760e31b81526001600160a01b038281166004830152606091849182169063f36dba3890602401600060405180830381865afa158015611c79573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c419190810190613d0f565b80516060906000816001600160401b03811115611cc057611cc0612e17565b604051908082528060200260200182016040528015611cf957816020015b611ce6612d57565b815260200190600190039081611cde5790505b50905060005b82811015611d4e57611d29858281518110611d1c57611d1c6139b8565b60200260200101516111f9565b828281518110611d3b57611d3b6139b8565b6020908102919091010152600101611cff565b509392505050565b6000611d847f000000000000000000000000000000000000000000000000000000000000000063ffffffff16565b905090565b4390565b4290565b6060600083516001600160401b03811115611dae57611dae612e17565b604051908082528060200260200182016040528015611df357816020015b6040805180820190915260008082526020820152815260200190600190039081611dcc5790505b50905060005b845181101561071457611e2f604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b611e5c604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b7f000000000000000000000000000000000000000000000000000000000000000015611fdf57856001600160a01b0316638f693ec7888581518110611ea357611ea36139b8565b60200260200101516040518263ffffffff1660e01b8152600401611ed691906001600160a01b0391909116815260200190565b606060405180830381865afa158015611ef3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f179190613db4565b604085015260208401526001600160e01b0316825286516001600160a01b03871690638181494590899086908110611f5157611f516139b8565b60200260200101516040518263ffffffff1660e01b8152600401611f8491906001600160a01b0391909116815260200190565b606060405180830381865afa158015611fa1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fc59190613db4565b604084015260208301526001600160e01b0316815261214a565b856001600160a01b0316632c427b57888581518110612000576120006139b8565b60200260200101516040518263ffffffff1660e01b815260040161203391906001600160a01b0391909116815260200190565b606060405180830381865afa158015612050573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120749190613dfd565b63ffffffff90811660408601521660208401526001600160e01b0316825286516001600160a01b038716906392a18235908990869081106120b7576120b76139b8565b60200260200101516040518263ffffffff1660e01b81526004016120ea91906001600160a01b0391909116815260200190565b606060405180830381865afa158015612107573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061212b9190613dfd565b63ffffffff90811660408501521660208301526001600160e01b031681525b60006040518060200160405280898681518110612169576121696139b8565b60200260200101516001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121d2919061399f565b81525090506121fc8885815181106121ec576121ec6139b8565b60200260200101518885846122f1565b612220888581518110612211576122116139b8565b602002602001015188846124f2565b6000612248898681518110612237576122376139b8565b6020026020010151898c87866126e9565b905060006122718a8781518110612261576122616139b8565b60200260200101518a8d87612919565b60408051808201909152600080825260208201529091508a878151811061229a5761229a6139b8565b60209081029190910101516001600160a01b031681526122ba8284613b50565b6020820152875181908990899081106122d5576122d56139b8565b6020026020010181905250505050505050806001019050611df9565b604051637c05a7c560e01b81526001600160a01b03858116600483015260009190851690637c05a7c590602401602060405180830381865afa15801561233b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061235f919061399f565b9050600061236b611d56565b9050600084604001511180156123845750836040015181115b15612390575060408301515b60006123a0828660200151612b3d565b90506000811180156123b25750600083115b156124db576000612424886001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061241e919061399f565b86612b50565b905060006124328386612b6e565b90506000808311612452576040518060200160405280600081525061245c565b61245c8284612b7a565b9050600061248560405180602001604052808b600001516001600160e01b031681525083612bbf565b90506124c08160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612beb565b6001600160e01b0316895250505050602085018290526124e9565b80156124e957602085018290525b50505050505050565b604051631d31307360e21b81526001600160a01b038481166004830152600091908416906374c4c1cc90602401602060405180830381865afa15801561253c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612560919061399f565b9050600061256c611d56565b9050600083604001511180156125855750826040015181115b15612591575060408201515b60006125a1828560200151612b3d565b90506000811180156125b35750600083115b156126d3576000866001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156125f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061261c919061399f565b9050600061262a8386612b6e565b9050600080831161264a5760405180602001604052806000815250612654565b6126548284612b7a565b9050600061267d60405180602001604052808a600001516001600160e01b031681525083612bbf565b90506126b88160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612beb565b6001600160e01b0316885250505050602084018290526126e1565b80156126e157602084018290525b505050505050565b604080516020808201835284516001600160e01b031682528251908101928390526336fe846560e11b9092526001600160a01b0387811660248401528581166044840152600092839181908916636dfd08ca60648301602060405180830381865afa15801561275c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612780919061399f565b905280519091501580156128025750866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f19190613e40565b6001600160e01b0316826000015110155b1561287557866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612845573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128699190613e40565b6001600160e01b031681525b60006128818383612c27565b6040516395dd919360e01b81526001600160a01b0389811660048301529192506000916128fc91908c16906395dd919390602401602060405180830381865afa1580156128d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128f6919061399f565b87612b50565b9050600061290a8284612c53565b9b9a5050505050505050505050565b604080516020808201835283516001600160e01b0316825282519081019283905263552c097160e01b9092526001600160a01b038681166024840152848116604484015260009283918190881663552c097160648301602060405180830381865afa15801561298c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129b0919061399f565b90528051909150158015612a325750856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a219190613e40565b6001600160e01b0316826000015110155b15612aa557856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a999190613e40565b6001600160e01b031681525b6000612ab18383612c27565b6040516370a0823160e01b81526001600160a01b0388811660048301529192506000918a16906370a0823190602401602060405180830381865afa158015612afd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b21919061399f565b90506000612b2f8284612c53565b9a9950505050505050505050565b6000612b498284613e5b565b9392505050565b6000612b49612b6784670de0b6b3a7640000612b6e565b8351612c7d565b6000612b498284613b17565b6040805160208101909152600081526040518060200160405280612bb6612bb0866ec097ce7bc90715b34b9f1000000000612b6e565b85612c7d565b90529392505050565b6040805160208101909152600081526040518060200160405280612bb685600001518560000151612c89565b6000816001600160e01b03841115612c1f5760405162461bcd60e51b8152600401612c169190613e6e565b60405180910390fd5b509192915050565b6040805160208101909152600081526040518060200160405280612bb685600001518560000151612b3d565b60006ec097ce7bc90715b34b9f1000000000612c73848460000151612b6e565b612b499190613b2e565b6000612b498284613b2e565b6000612b498284613b50565b604051806101a001604052806060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160608152602001606081526020016060815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001606081525090565b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180610220016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b6001600160a01b0381168114612e0457600080fd5b50565b8035612e1281612def565b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715612e4f57612e4f612e17565b60405290565b604051606081016001600160401b0381118282101715612e4f57612e4f612e17565b604051601f8201601f191681016001600160401b0381118282101715612e9f57612e9f612e17565b604052919050565b60006001600160401b03821115612ec057612ec0612e17565b50601f01601f191660200190565b60008060408385031215612ee157600080fd5b8235612eec81612def565b91506020838101356001600160401b0380821115612f0957600080fd5b9085019060a08288031215612f1d57600080fd5b612f25612e2d565b823582811115612f3457600080fd5b83019150601f82018813612f4757600080fd5b8135612f5a612f5582612ea7565b612e77565b8181528986838601011115612f6e57600080fd5b818685018783013760008683830101528083525050612f8e848401612e07565b84820152612f9e60408401612e07565b60408201526060830135606082015260808301356080820152809450505050509250929050565b60005b83811015612fe0578181015183820152602001612fc8565b50506000910152565b60008151808452613001816020860160208601612fc5565b601f01601f19169290920160200192915050565b80516001600160a01b031682526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e0830152610100808201518184015250610120808201518184015250610140808201518184015250610160808201516130a08285018215159052565b505061018081810151908301526101a0808201516001600160a01b0316908301526101c080820151908301526101e0808201519083015261020090810151910152565b60008151808452602080850194506020840160005b8381101561311f5761310b878351613015565b6102209690960195908201906001016130f8565b509495945050505050565b60006101a0825181855261314082860182612fe9565b915050602083015161315d60208601826001600160a01b03169052565b50604083015161317860408601826001600160a01b03169052565b50606083015160608501526080830151608085015260a083015184820360a08601526131a48282612fe9565b91505060c083015184820360c08601526131be8282612fe9565b91505060e083015184820360e08601526131d88282612fe9565b915050610100808401516131f6828701826001600160a01b03169052565b5050610120838101519085015261014080840151908501526101608084015190850152610180808401518583038287015261323183826130e3565b9695505050505050565b602081526000612b49602083018461312a565b60008083601f84011261326057600080fd5b5081356001600160401b0381111561327757600080fd5b6020830191508360208260051b850101111561329257600080fd5b9250929050565b600080602083850312156132ac57600080fd5b82356001600160401b038111156132c257600080fd5b6132ce8582860161324e565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b8281101561332d5761331d84835180516001600160a01b03168252602090810151910152565b92840192908501906001016132f7565b5091979650505050505050565b60006020828403121561334c57600080fd5b8135612b4981612def565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156133ae57603f1988860301845261339c85835161312a565b94509285019290850190600101613380565b5092979650505050505050565b602080825282516001600160a01b03168282015282810151604080840191909152808401516060808501528051608085018190526000939291830191849160a08701905b808410156134395761342582865180516001600160a01b03168252602090810151910152565b9385019360019390930192908201906133ff565b50979650505050505050565b6000806040838503121561345857600080fd5b823561346381612def565b9150602083013561347381612def565b809150509250929050565b60008060006060848603121561349357600080fd5b833561349e81612def565b925060208401356134ae81612def565b915060408401356134be81612def565b809150509250925092565b600060208083018184528085518083526040925060408601915060408160051b8701018488016000805b8481101561359657898403603f19018652825180516001600160a01b03908116865289820151168986015287810151888601526060908101516080918601829052805191860182905289019060a086019084905b808210156135815761356d83855180516001600160a01b03168252602090810151910152565b928b0192918a019160019190910190613547565b505096890196945050918701916001016134f3565b50919998505050505050505050565b6000806000604084860312156135ba57600080fd5b83356001600160401b038111156135d057600080fd5b6135dc8682870161324e565b90945092505060208401356134be81612def565b80516001600160a01b031682526020808201519083015260408082015190830152606080820151908301526080808201519083015260a090810151910152565b6020808252825182820181905260009190848201906040850190845b818110156136725761365f8385516135f0565b9284019260c0929092019160010161364c565b50909695505050505050565b81516001600160a01b03168152602080830151908201526040810161064f565b610220810161064f8284613015565b60c0810161064f82846135f0565b6020808252825182820181905260009190848201906040850190845b818110156136725783516001600160a01b0316835292840192918401916001016136d7565b60006001600160401b0382111561371557613715612e17565b5060051b60200190565b6000602080838503121561373257600080fd5b82356001600160401b0381111561374857600080fd5b8301601f8101851361375957600080fd5b8035613767612f55826136fc565b81815260059190911b8201830190838101908783111561378657600080fd5b928401925b828410156137ad57833561379e81612def565b8252928401929084019061378b565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b81811015613672576137e7838551613015565b9284019261022092909201916001016137d4565b6000602080838503121561380e57600080fd5b82516001600160401b0381111561382457600080fd5b8301601f8101851361383557600080fd5b8051613843612f55826136fc565b81815260059190911b8201830190838101908783111561386257600080fd5b928401925b828410156137ad57835161387a81612def565b82529284019290840190613867565b600082601f83011261389a57600080fd5b81516138a8612f5582612ea7565b8181528460208386010111156138bd57600080fd5b610c41826020830160208701612fc5565b6000602082840312156138e057600080fd5b81516001600160401b03808211156138f757600080fd5b908301906060828603121561390b57600080fd5b613913612e55565b82518281111561392257600080fd5b61392e87828601613889565b82525060208301518281111561394357600080fd5b61394f87828601613889565b60208301525060408301518281111561396757600080fd5b61397387828601613889565b60408301525095945050505050565b60006020828403121561399457600080fd5b8151612b4981612def565b6000602082840312156139b157600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600060a082840312156139e057600080fd5b6139e8612e2d565b905081516001600160401b03811115613a0057600080fd5b613a0c84828501613889565b8252506020820151613a1d81612def565b60208201526040820151613a3081612def565b80604083015250606082015160608201526080820151608082015292915050565b60006020808385031215613a6457600080fd5b82516001600160401b0380821115613a7b57600080fd5b818501915085601f830112613a8f57600080fd5b8151613a9d612f55826136fc565b81815260059190911b83018401908481019088831115613abc57600080fd5b8585015b83811015613af457805185811115613ad85760008081fd5b613ae68b89838a01016139ce565b845250918601918601613ac0565b5098975050505050505050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761064f5761064f613b01565b600082613b4b57634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561064f5761064f613b01565b600060208284031215613b7557600080fd5b81516001600160401b03811115613b8b57600080fd5b610c41848285016139ce565b60006020808385031215613baa57600080fd5b82516001600160401b03811115613bc057600080fd5b8301601f81018513613bd157600080fd5b8051613bdf612f55826136fc565b81815260059190911b82018301908381019087831115613bfe57600080fd5b928401925b828410156137ad578351613c1681612def565b82529284019290840190613c03565b80518015158114612e1257600080fd5b60008060408385031215613c4857600080fd5b613c5183613c25565b9150602083015190509250929050565b600060208284031215613c7357600080fd5b815160ff81168114612b4957600080fd5b634e487b7160e01b600052602160045260246000fd5b6001600160a01b03831681526040810160098310613cc857634e487b7160e01b600052602160045260246000fd5b8260208301529392505050565b600060208284031215613ce757600080fd5b612b4982613c25565b600060ff821660ff8103613d0657613d06613b01565b60010192915050565b60006020808385031215613d2257600080fd5b82516001600160401b03811115613d3857600080fd5b8301601f81018513613d4957600080fd5b8051613d57612f55826136fc565b81815260059190911b82018301908381019087831115613d7657600080fd5b928401925b828410156137ad578351613d8e81612def565b82529284019290840190613d7b565b80516001600160e01b0381168114612e1257600080fd5b600080600060608486031215613dc957600080fd5b613dd284613d9d565b925060208401519150604084015190509250925092565b805163ffffffff81168114612e1257600080fd5b600080600060608486031215613e1257600080fd5b613e1b84613d9d565b9250613e2960208501613de9565b9150613e3760408501613de9565b90509250925092565b600060208284031215613e5257600080fd5b612b4982613d9d565b8181038181111561064f5761064f613b01565b602081526000612b496020830184612fe956fea264697066735822122061714451543057e1497a8492e520f0a042cefe93b330caee6118564818e936f064736f6c63430008190033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101005760003560e01c80637c51b64211610097578063c7ad089511610066578063c7ad0895146102a1578063d77ebf96146102d8578063e0a67f11146102f8578063e1d146fb1461031857600080fd5b80637c51b642146102215780637c84e3b314610241578063aa5dbd2314610261578063b31242391461028157600080fd5b806347d86a81116100d357806347d86a811461018e57806355dd9515146101a15780636857249c146101cc5780637a27db571461020157600080fd5b80630d3ae318146101055780631f884fdf1461012e578063345954dc1461014e5780633e3e399c1461016e575b600080fd5b610118610113366004612ece565b610320565b604051610125919061323b565b60405180910390f35b61014161013c366004613299565b610655565b60405161012591906132da565b61016161015c36600461333a565b61071d565b6040516101259190613357565b61018161017c36600461333a565b610850565b60405161012591906133bb565b61011861019c366004613445565b610bc2565b6101b46101af36600461347e565b610c49565b6040516001600160a01b039091168152602001610125565b6101f37f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610125565b61021461020f366004613445565b610cc9565b60405161012591906134c9565b61023461022f3660046135a5565b610fd6565b6040516101259190613630565b61025461024f36600461333a565b61108f565b604051610125919061367e565b61027461026f36600461333a565b6111f9565b604051610125919061369e565b61029461028f366004613445565b611947565b60405161012591906136ad565b6102c87f000000000000000000000000000000000000000000000000000000000000000081565b6040519015158152602001610125565b6102eb6102e6366004613445565b611c2e565b60405161012591906136bb565b61030b61030636600461371f565b611ca1565b60405161012591906137b8565b6101f3611d56565b610328612c95565b6000826040015190506000816001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610371573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261039991908101906137fb565b905060006103a682611ca1565b60408681015190516328ebbe8b60e21b81526001600160a01b039182166004820152919250879160009183169063a3aefa2c90602401600060405180830381865afa1580156103f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261042191908101906138ce565b90506000876040015190506000604051806101a001604052808a6000015181526020018a602001516001600160a01b031681526020018a604001516001600160a01b031681526020018a6060015181526020018a608001518152602001846000015181526020018460200151815260200184604001518152602001836001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104fe9190613982565b6001600160a01b03168152602001836001600160a01b031663e87554466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561054a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061056e919061399f565b8152602001836001600160a01b0316634ada90af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d5919061399f565b8152602001836001600160a01b031663db5c65de6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610618573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063c919061399f565b8152602001959095525092955050505050505b92915050565b6060816000816001600160401b0381111561067257610672612e17565b6040519080825280602002602001820160405280156106b757816020015b60408051808201909152600080825260208201528152602001906001900390816106905790505b50905060005b82811015610714576106ef8686838181106106da576106da6139b8565b905060200201602081019061024f919061333a565b828281518110610701576107016139b8565b60209081029190910101526001016106bd565b50949350505050565b606060008290506000816001600160a01b031663d88ff1f46040518163ffffffff1660e01b8152600401600060405180830381865afa158015610764573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261078c9190810190613a51565b80519091506000816001600160401b038111156107ab576107ab612e17565b6040519080825280602002602001820160405280156107e457816020015b6107d1612c95565b8152602001906001900390816107c95790505b50905060005b82811015610846576000848281518110610806576108066139b8565b60200260200101519050600061081c8983610320565b905080848481518110610831576108316139b8565b602090810291909101015250506001016107ea565b5095945050505050565b604080516060808201835260008083526020830152918101919091526000808390506000816001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156108b2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108da91908101906137fb565b90506000826001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561091c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109409190613982565b9050600082516001600160401b0381111561095d5761095d612e17565b6040519080825280602002602001820160405280156109a257816020015b604080518082019091526000808252602082015281526020019060019003908161097b5790505b5090506109d2604051806060016040528060006001600160a01b0316815260200160008152602001606081525090565b6001600160a01b03881681526040810182905260005b8451811015610bae576040805180820190915260008082526020820152858281518110610a1757610a176139b8565b602002602001015181600001906001600160a01b031690816001600160a01b031681525050670de0b6b3a7640000856001600160a01b031663fc57d4df888581518110610a6657610a666139b8565b60200260200101516040518263ffffffff1660e01b8152600401610a9991906001600160a01b0391909116815260200190565b602060405180830381865afa158015610ab6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ada919061399f565b878481518110610aec57610aec6139b8565b60200260200101516001600160a01b031663bbcac5576040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b55919061399f565b610b5f9190613b17565b610b699190613b2e565b60208201526040830151805182919084908110610b8857610b886139b8565b6020026020010181905250806020015188610ba39190613b50565b9750506001016109e8565b506020810195909552509295945050505050565b610bca612c95565b604051637aee632d60e01b81526001600160a01b0383811660048301528491610c4191839190821690637aee632d90602401600060405180830381865afa158015610c19573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526101139190810190613b63565b949350505050565b60405163266e0a7f60e01b81526001600160a01b0383811660048301528281166024830152600091859182169063266e0a7f90604401602060405180830381865afa158015610c9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc09190613982565b95945050505050565b60606000826001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610d0b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d3391908101906137fb565b90506000836001600160a01b03166361252fd16040518163ffffffff1660e01b8152600401600060405180830381865afa158015610d75573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d9d9190810190613b97565b9050600081516001600160401b03811115610dba57610dba612e17565b604051908082528060200260200182016040528015610e0b57816020015b6040805160808101825260008082526020808301829052928201526060808201528252600019909201910181610dd85790505b50905060005b8251811015610846576040805160808101825260008082526020820181905291810191909152606080820152838281518110610e4f57610e4f6139b8565b60209081029190910101516001600160a01b031681528351849083908110610e7957610e796139b8565b60200260200101516001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ebe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee29190613982565b6001600160a01b031660208201528351849083908110610f0457610f046139b8565b6020908102919091010151604051631627ee8960e01b81526001600160a01b038a8116600483015290911690631627ee8990602401602060405180830381865afa158015610f56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7a919061399f565b816040018181525050610fa78886868581518110610f9a57610f9a6139b8565b6020026020010151611d91565b816060018190525080838381518110610fc257610fc26139b8565b602090810291909101015250600101610e11565b6060826000816001600160401b03811115610ff357610ff3612e17565b60405190808252806020026020018201604052801561102c57816020015b611019612d18565b8152602001906001900390816110115790505b50905060005b828110156108465761106a87878381811061104f5761104f6139b8565b9050602002016020810190611064919061333a565b86611947565b82828151811061107c5761107c6139b8565b6020908102919091010152600101611032565b60408051808201909152600080825260208201526000826001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111079190613982565b90506000816001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611149573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116d9190613982565b6040805180820182526001600160a01b03808816808352925163fc57d4df60e01b815260048101939093529293509160208301919084169063fc57d4df90602401602060405180830381865afa1580156111cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ef919061399f565b9052949350505050565b611201612d57565b6000826001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611241573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611265919061399f565b90506000836001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cb9190613982565b604051638e8f294b60e01b81526001600160a01b03868116600483015291925082916000918291841690638e8f294b906024016040805180830381865afa15801561131a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133e9190613c35565b915091506000876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a69190613982565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061140c9190613c61565b60ff1690506000805b600860ff8216116114d2576000886001600160a01b031663e85a29608d8460ff16600881111561144757611447613c84565b6040518363ffffffff1660e01b8152600401611464929190613c9a565b602060405180830381865afa158015611481573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a59190613cd5565b6114b05760006114b3565b60015b60ff9081169083161b9290921791506114cb81613cf0565b9050611415565b506040518061022001604052808b6001600160a01b031681526020018981526020018b6001600160a01b031663ae9d70b06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611532573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611556919061399f565b81526020018b6001600160a01b031663f8f9da286040518163ffffffff1660e01b8152600401602060405180830381865afa158015611599573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115bd919061399f565b81526020018b6001600160a01b031663173b99046040518163ffffffff1660e01b8152600401602060405180830381865afa158015611600573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611624919061399f565b81526040516302c3bcbb60e01b81526001600160a01b038d811660048301526020909201918916906302c3bcbb90602401602060405180830381865afa158015611672573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611696919061399f565b815260405163252c221960e11b81526001600160a01b038d81166004830152602090920191891690634a58443290602401602060405180830381865afa1580156116e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611708919061399f565b81526020018b6001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561174b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176f919061399f565b81526020018b6001600160a01b0316638f840ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117d6919061399f565b81526020018b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611819573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061183d919061399f565b81526020018b6001600160a01b0316633b1d21a26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611880573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118a4919061399f565b81526020018615158152602001858152602001846001600160a01b031681526020018b6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611904573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119289190613c61565b60ff168152602081019390935260409092015298975050505050505050565b61194f612d18565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908516906370a0823190602401602060405180830381865afa158015611999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119bd919061399f565b6040516305eff7ef60e21b81526001600160a01b0385811660048301529192506000918616906317bfdfbc906024016020604051808303816000875af1158015611a0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a2f919061399f565b604051633af9e66960e01b81526001600160a01b038681166004830152919250600091871690633af9e669906024016020604051808303816000875af1158015611a7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa1919061399f565b90506000806000886001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0a9190613982565b6040516370a0823160e01b81526001600160a01b038a81166004830152919250908216906370a0823190602401602060405180830381865afa158015611b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b78919061399f565b604051636eb1769f60e11b81526001600160a01b038a811660048301528b811660248301529194509082169063dd62ed3e90604401602060405180830381865afa158015611bca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bee919061399f565b6040805160c0810182526001600160a01b038c168152602081019890985287019590955250506060840191909152608083015260a0820152905092915050565b604051631e6db74760e31b81526001600160a01b038281166004830152606091849182169063f36dba3890602401600060405180830381865afa158015611c79573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c419190810190613d0f565b80516060906000816001600160401b03811115611cc057611cc0612e17565b604051908082528060200260200182016040528015611cf957816020015b611ce6612d57565b815260200190600190039081611cde5790505b50905060005b82811015611d4e57611d29858281518110611d1c57611d1c6139b8565b60200260200101516111f9565b828281518110611d3b57611d3b6139b8565b6020908102919091010152600101611cff565b509392505050565b6000611d847f000000000000000000000000000000000000000000000000000000000000000063ffffffff16565b905090565b4390565b4290565b6060600083516001600160401b03811115611dae57611dae612e17565b604051908082528060200260200182016040528015611df357816020015b6040805180820190915260008082526020820152815260200190600190039081611dcc5790505b50905060005b845181101561071457611e2f604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b611e5c604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b7f000000000000000000000000000000000000000000000000000000000000000015611fdf57856001600160a01b0316638f693ec7888581518110611ea357611ea36139b8565b60200260200101516040518263ffffffff1660e01b8152600401611ed691906001600160a01b0391909116815260200190565b606060405180830381865afa158015611ef3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f179190613db4565b604085015260208401526001600160e01b0316825286516001600160a01b03871690638181494590899086908110611f5157611f516139b8565b60200260200101516040518263ffffffff1660e01b8152600401611f8491906001600160a01b0391909116815260200190565b606060405180830381865afa158015611fa1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fc59190613db4565b604084015260208301526001600160e01b0316815261214a565b856001600160a01b0316632c427b57888581518110612000576120006139b8565b60200260200101516040518263ffffffff1660e01b815260040161203391906001600160a01b0391909116815260200190565b606060405180830381865afa158015612050573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120749190613dfd565b63ffffffff90811660408601521660208401526001600160e01b0316825286516001600160a01b038716906392a18235908990869081106120b7576120b76139b8565b60200260200101516040518263ffffffff1660e01b81526004016120ea91906001600160a01b0391909116815260200190565b606060405180830381865afa158015612107573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061212b9190613dfd565b63ffffffff90811660408501521660208301526001600160e01b031681525b60006040518060200160405280898681518110612169576121696139b8565b60200260200101516001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121d2919061399f565b81525090506121fc8885815181106121ec576121ec6139b8565b60200260200101518885846122f1565b612220888581518110612211576122116139b8565b602002602001015188846124f2565b6000612248898681518110612237576122376139b8565b6020026020010151898c87866126e9565b905060006122718a8781518110612261576122616139b8565b60200260200101518a8d87612919565b60408051808201909152600080825260208201529091508a878151811061229a5761229a6139b8565b60209081029190910101516001600160a01b031681526122ba8284613b50565b6020820152875181908990899081106122d5576122d56139b8565b6020026020010181905250505050505050806001019050611df9565b604051637c05a7c560e01b81526001600160a01b03858116600483015260009190851690637c05a7c590602401602060405180830381865afa15801561233b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061235f919061399f565b9050600061236b611d56565b9050600084604001511180156123845750836040015181115b15612390575060408301515b60006123a0828660200151612b3d565b90506000811180156123b25750600083115b156124db576000612424886001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061241e919061399f565b86612b50565b905060006124328386612b6e565b90506000808311612452576040518060200160405280600081525061245c565b61245c8284612b7a565b9050600061248560405180602001604052808b600001516001600160e01b031681525083612bbf565b90506124c08160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612beb565b6001600160e01b0316895250505050602085018290526124e9565b80156124e957602085018290525b50505050505050565b604051631d31307360e21b81526001600160a01b038481166004830152600091908416906374c4c1cc90602401602060405180830381865afa15801561253c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612560919061399f565b9050600061256c611d56565b9050600083604001511180156125855750826040015181115b15612591575060408201515b60006125a1828560200151612b3d565b90506000811180156125b35750600083115b156126d3576000866001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156125f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061261c919061399f565b9050600061262a8386612b6e565b9050600080831161264a5760405180602001604052806000815250612654565b6126548284612b7a565b9050600061267d60405180602001604052808a600001516001600160e01b031681525083612bbf565b90506126b88160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612beb565b6001600160e01b0316885250505050602084018290526126e1565b80156126e157602084018290525b505050505050565b604080516020808201835284516001600160e01b031682528251908101928390526336fe846560e11b9092526001600160a01b0387811660248401528581166044840152600092839181908916636dfd08ca60648301602060405180830381865afa15801561275c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612780919061399f565b905280519091501580156128025750866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f19190613e40565b6001600160e01b0316826000015110155b1561287557866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612845573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128699190613e40565b6001600160e01b031681525b60006128818383612c27565b6040516395dd919360e01b81526001600160a01b0389811660048301529192506000916128fc91908c16906395dd919390602401602060405180830381865afa1580156128d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128f6919061399f565b87612b50565b9050600061290a8284612c53565b9b9a5050505050505050505050565b604080516020808201835283516001600160e01b0316825282519081019283905263552c097160e01b9092526001600160a01b038681166024840152848116604484015260009283918190881663552c097160648301602060405180830381865afa15801561298c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129b0919061399f565b90528051909150158015612a325750856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a219190613e40565b6001600160e01b0316826000015110155b15612aa557856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a999190613e40565b6001600160e01b031681525b6000612ab18383612c27565b6040516370a0823160e01b81526001600160a01b0388811660048301529192506000918a16906370a0823190602401602060405180830381865afa158015612afd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b21919061399f565b90506000612b2f8284612c53565b9a9950505050505050505050565b6000612b498284613e5b565b9392505050565b6000612b49612b6784670de0b6b3a7640000612b6e565b8351612c7d565b6000612b498284613b17565b6040805160208101909152600081526040518060200160405280612bb6612bb0866ec097ce7bc90715b34b9f1000000000612b6e565b85612c7d565b90529392505050565b6040805160208101909152600081526040518060200160405280612bb685600001518560000151612c89565b6000816001600160e01b03841115612c1f5760405162461bcd60e51b8152600401612c169190613e6e565b60405180910390fd5b509192915050565b6040805160208101909152600081526040518060200160405280612bb685600001518560000151612b3d565b60006ec097ce7bc90715b34b9f1000000000612c73848460000151612b6e565b612b499190613b2e565b6000612b498284613b2e565b6000612b498284613b50565b604051806101a001604052806060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160608152602001606081526020016060815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001606081525090565b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180610220016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b6001600160a01b0381168114612e0457600080fd5b50565b8035612e1281612def565b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715612e4f57612e4f612e17565b60405290565b604051606081016001600160401b0381118282101715612e4f57612e4f612e17565b604051601f8201601f191681016001600160401b0381118282101715612e9f57612e9f612e17565b604052919050565b60006001600160401b03821115612ec057612ec0612e17565b50601f01601f191660200190565b60008060408385031215612ee157600080fd5b8235612eec81612def565b91506020838101356001600160401b0380821115612f0957600080fd5b9085019060a08288031215612f1d57600080fd5b612f25612e2d565b823582811115612f3457600080fd5b83019150601f82018813612f4757600080fd5b8135612f5a612f5582612ea7565b612e77565b8181528986838601011115612f6e57600080fd5b818685018783013760008683830101528083525050612f8e848401612e07565b84820152612f9e60408401612e07565b60408201526060830135606082015260808301356080820152809450505050509250929050565b60005b83811015612fe0578181015183820152602001612fc8565b50506000910152565b60008151808452613001816020860160208601612fc5565b601f01601f19169290920160200192915050565b80516001600160a01b031682526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e0830152610100808201518184015250610120808201518184015250610140808201518184015250610160808201516130a08285018215159052565b505061018081810151908301526101a0808201516001600160a01b0316908301526101c080820151908301526101e0808201519083015261020090810151910152565b60008151808452602080850194506020840160005b8381101561311f5761310b878351613015565b6102209690960195908201906001016130f8565b509495945050505050565b60006101a0825181855261314082860182612fe9565b915050602083015161315d60208601826001600160a01b03169052565b50604083015161317860408601826001600160a01b03169052565b50606083015160608501526080830151608085015260a083015184820360a08601526131a48282612fe9565b91505060c083015184820360c08601526131be8282612fe9565b91505060e083015184820360e08601526131d88282612fe9565b915050610100808401516131f6828701826001600160a01b03169052565b5050610120838101519085015261014080840151908501526101608084015190850152610180808401518583038287015261323183826130e3565b9695505050505050565b602081526000612b49602083018461312a565b60008083601f84011261326057600080fd5b5081356001600160401b0381111561327757600080fd5b6020830191508360208260051b850101111561329257600080fd5b9250929050565b600080602083850312156132ac57600080fd5b82356001600160401b038111156132c257600080fd5b6132ce8582860161324e565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b8281101561332d5761331d84835180516001600160a01b03168252602090810151910152565b92840192908501906001016132f7565b5091979650505050505050565b60006020828403121561334c57600080fd5b8135612b4981612def565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156133ae57603f1988860301845261339c85835161312a565b94509285019290850190600101613380565b5092979650505050505050565b602080825282516001600160a01b03168282015282810151604080840191909152808401516060808501528051608085018190526000939291830191849160a08701905b808410156134395761342582865180516001600160a01b03168252602090810151910152565b9385019360019390930192908201906133ff565b50979650505050505050565b6000806040838503121561345857600080fd5b823561346381612def565b9150602083013561347381612def565b809150509250929050565b60008060006060848603121561349357600080fd5b833561349e81612def565b925060208401356134ae81612def565b915060408401356134be81612def565b809150509250925092565b600060208083018184528085518083526040925060408601915060408160051b8701018488016000805b8481101561359657898403603f19018652825180516001600160a01b03908116865289820151168986015287810151888601526060908101516080918601829052805191860182905289019060a086019084905b808210156135815761356d83855180516001600160a01b03168252602090810151910152565b928b0192918a019160019190910190613547565b505096890196945050918701916001016134f3565b50919998505050505050505050565b6000806000604084860312156135ba57600080fd5b83356001600160401b038111156135d057600080fd5b6135dc8682870161324e565b90945092505060208401356134be81612def565b80516001600160a01b031682526020808201519083015260408082015190830152606080820151908301526080808201519083015260a090810151910152565b6020808252825182820181905260009190848201906040850190845b818110156136725761365f8385516135f0565b9284019260c0929092019160010161364c565b50909695505050505050565b81516001600160a01b03168152602080830151908201526040810161064f565b610220810161064f8284613015565b60c0810161064f82846135f0565b6020808252825182820181905260009190848201906040850190845b818110156136725783516001600160a01b0316835292840192918401916001016136d7565b60006001600160401b0382111561371557613715612e17565b5060051b60200190565b6000602080838503121561373257600080fd5b82356001600160401b0381111561374857600080fd5b8301601f8101851361375957600080fd5b8035613767612f55826136fc565b81815260059190911b8201830190838101908783111561378657600080fd5b928401925b828410156137ad57833561379e81612def565b8252928401929084019061378b565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b81811015613672576137e7838551613015565b9284019261022092909201916001016137d4565b6000602080838503121561380e57600080fd5b82516001600160401b0381111561382457600080fd5b8301601f8101851361383557600080fd5b8051613843612f55826136fc565b81815260059190911b8201830190838101908783111561386257600080fd5b928401925b828410156137ad57835161387a81612def565b82529284019290840190613867565b600082601f83011261389a57600080fd5b81516138a8612f5582612ea7565b8181528460208386010111156138bd57600080fd5b610c41826020830160208701612fc5565b6000602082840312156138e057600080fd5b81516001600160401b03808211156138f757600080fd5b908301906060828603121561390b57600080fd5b613913612e55565b82518281111561392257600080fd5b61392e87828601613889565b82525060208301518281111561394357600080fd5b61394f87828601613889565b60208301525060408301518281111561396757600080fd5b61397387828601613889565b60408301525095945050505050565b60006020828403121561399457600080fd5b8151612b4981612def565b6000602082840312156139b157600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600060a082840312156139e057600080fd5b6139e8612e2d565b905081516001600160401b03811115613a0057600080fd5b613a0c84828501613889565b8252506020820151613a1d81612def565b60208201526040820151613a3081612def565b80604083015250606082015160608201526080820151608082015292915050565b60006020808385031215613a6457600080fd5b82516001600160401b0380821115613a7b57600080fd5b818501915085601f830112613a8f57600080fd5b8151613a9d612f55826136fc565b81815260059190911b83018401908481019088831115613abc57600080fd5b8585015b83811015613af457805185811115613ad85760008081fd5b613ae68b89838a01016139ce565b845250918601918601613ac0565b5098975050505050505050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761064f5761064f613b01565b600082613b4b57634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561064f5761064f613b01565b600060208284031215613b7557600080fd5b81516001600160401b03811115613b8b57600080fd5b610c41848285016139ce565b60006020808385031215613baa57600080fd5b82516001600160401b03811115613bc057600080fd5b8301601f81018513613bd157600080fd5b8051613bdf612f55826136fc565b81815260059190911b82018301908381019087831115613bfe57600080fd5b928401925b828410156137ad578351613c1681612def565b82529284019290840190613c03565b80518015158114612e1257600080fd5b60008060408385031215613c4857600080fd5b613c5183613c25565b9150602083015190509250929050565b600060208284031215613c7357600080fd5b815160ff81168114612b4957600080fd5b634e487b7160e01b600052602160045260246000fd5b6001600160a01b03831681526040810160098310613cc857634e487b7160e01b600052602160045260246000fd5b8260208301529392505050565b600060208284031215613ce757600080fd5b612b4982613c25565b600060ff821660ff8103613d0657613d06613b01565b60010192915050565b60006020808385031215613d2257600080fd5b82516001600160401b03811115613d3857600080fd5b8301601f81018513613d4957600080fd5b8051613d57612f55826136fc565b81815260059190911b82018301908381019087831115613d7657600080fd5b928401925b828410156137ad578351613d8e81612def565b82529284019290840190613d7b565b80516001600160e01b0381168114612e1257600080fd5b600080600060608486031215613dc957600080fd5b613dd284613d9d565b925060208401519150604084015190509250925092565b805163ffffffff81168114612e1257600080fd5b600080600060608486031215613e1257600080fd5b613e1b84613d9d565b9250613e2960208501613de9565b9150613e3760408501613de9565b90509250925092565b600060208284031215613e5257600080fd5b612b4982613d9d565b8181038181111561064f5761064f613b01565b602081526000612b496020830184612fe956fea264697066735822122061714451543057e1497a8492e520f0a042cefe93b330caee6118564818e936f064736f6c63430008190033", + "args": [true, 0, "0x317c1A5739F39046E20b08ac9BeEa3f10fD43326"], + "numDeployments": 2, + "solcInputHash": "09f8b2889a382752688c03578bc27f8d", + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"timeBased_\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"blocksPerYear_\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"corePoolComptroller_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidBlocksPerYear\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTimeBasedConfiguration\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"blocksOrSecondsPerYear\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"corePoolComptroller\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"}],\"name\":\"getAllPools\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockNumberOrTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getPendingRewards\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"distributorAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"rewardTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalRewards\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.PendingReward[]\",\"name\":\"pendingRewards\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.RewardSummary[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getPoolBadDebt\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalBadDebtUsd\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"badDebtUsd\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.BadDebt[]\",\"name\":\"badDebts\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.BadDebtSummary\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolByComptroller\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolRegistryInterface.VenusPool\",\"name\":\"venusPool\",\"type\":\"tuple\"}],\"name\":\"getPoolDataFromVenusPool\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getPoolsSupportedByAsset\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getVTokenForAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isTimeBased\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"vTokenBalances\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalanceCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balanceOfUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenAllowance\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenBalances\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"vTokenBalancesAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalanceCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balanceOfUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenAllowance\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenBalances[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"vTokenMetadata\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"vTokenMetadataAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"vTokenUnderlyingPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"underlyingPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenUnderlyingPrice\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"vTokenUnderlyingPriceAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"underlyingPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenUnderlyingPrice[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"params\":{\"blocksPerYear_\":\"The number of blocks per year\",\"corePoolComptroller_\":\"The address of the core pool comptroller\",\"timeBased_\":\"A boolean indicating whether the contract is based on time or block.\"}},\"getAllPools(address)\":{\"details\":\"This function is not designed to be called in a transaction: it is too gas-intensive\",\"params\":{\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"Arrays of all Venus pools' data\"}},\"getBlockNumberOrTimestamp()\":{\"details\":\"Function to simply retrieve block number or block timestamp\",\"returns\":{\"_0\":\"Current block number or block timestamp\"}},\"getPendingRewards(address,address)\":{\"params\":{\"account\":\"The user account.\",\"comptrollerAddress\":\"address\"},\"returns\":{\"_0\":\"Pending rewards array\"}},\"getPoolBadDebt(address)\":{\"params\":{\"comptrollerAddress\":\"Address of the comptroller\"},\"returns\":{\"_0\":\"badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and a break down of bad debt by market\"}},\"getPoolByComptroller(address,address)\":{\"params\":{\"comptroller\":\"The Comptroller implementation address\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"PoolData structure containing the details of the pool\"}},\"getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))\":{\"params\":{\"poolRegistryAddress\":\"Address of the PoolRegistry\",\"venusPool\":\"The VenusPool Object from PoolRegistry\"},\"returns\":{\"_0\":\"Enriched PoolData\"}},\"getPoolsSupportedByAsset(address,address)\":{\"params\":{\"asset\":\"The underlying asset of vToken\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"A list of Comptroller contracts\"}},\"getVTokenForAsset(address,address,address)\":{\"params\":{\"asset\":\"The underlyingAsset of VToken\",\"comptroller\":\"The pool comptroller\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"Address of the vToken\"}},\"vTokenBalances(address,address)\":{\"params\":{\"account\":\"The user Account\",\"vToken\":\"vToken address\"},\"returns\":{\"_0\":\"A struct containing the balances data\"}},\"vTokenBalancesAll(address[],address)\":{\"params\":{\"account\":\"The user Account\",\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"A list of structs containing balances data\"}},\"vTokenMetadata(address)\":{\"params\":{\"vToken\":\"The address of vToken\"},\"returns\":{\"_0\":\"VTokenMetadata struct\"}},\"vTokenMetadataAll(address[])\":{\"params\":{\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"An array of VTokenMetadata structs\"}},\"vTokenUnderlyingPrice(address)\":{\"params\":{\"vToken\":\"vToken address\"},\"returns\":{\"_0\":\"The price data for each asset\"}},\"vTokenUnderlyingPriceAll(address[])\":{\"params\":{\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"An array containing the price data for each asset\"}}},\"title\":\"PoolLens\",\"version\":1},\"userdoc\":{\"errors\":{\"InvalidBlocksPerYear()\":[{\"notice\":\"Thrown when blocks per year is invalid\"}],\"InvalidTimeBasedConfiguration()\":[{\"notice\":\"Thrown when time based but blocks per year is provided\"}]},\"kind\":\"user\",\"methods\":{\"blocksOrSecondsPerYear()\":{\"notice\":\"Stores blocksPerYear if isTimeBased is true else secondsPerYear is stored\"},\"corePoolComptroller()\":{\"notice\":\"Address of the core pool comptroller (all markets are returned for this pool, including paused ones)\"},\"getAllPools(address)\":{\"notice\":\"Queries all pools with addtional details for each of them\"},\"getPendingRewards(address,address)\":{\"notice\":\"Returns the pending rewards for a user for a given pool.\"},\"getPoolBadDebt(address)\":{\"notice\":\"Returns a summary of a pool's bad debt broken down by market\"},\"getPoolByComptroller(address,address)\":{\"notice\":\"Queries the details of a pool identified by Comptroller address\"},\"getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))\":{\"notice\":\"Queries additional information for the pool\"},\"getPoolsSupportedByAsset(address,address)\":{\"notice\":\"Returns all pools that support the specified underlying asset\"},\"getVTokenForAsset(address,address,address)\":{\"notice\":\"Returns vToken holding the specified underlying asset in the specified pool\"},\"isTimeBased()\":{\"notice\":\"Acknowledges if a contract is time based or not\"},\"vTokenBalances(address,address)\":{\"notice\":\"Queries the user's supply/borrow balances in the specified vToken\"},\"vTokenBalancesAll(address[],address)\":{\"notice\":\"Queries the user's supply/borrow balances in vTokens\"},\"vTokenMetadata(address)\":{\"notice\":\"Returns the metadata of VToken\"},\"vTokenMetadataAll(address[])\":{\"notice\":\"Returns the metadata of all VTokens\"},\"vTokenUnderlyingPrice(address)\":{\"notice\":\"Returns the price data for the underlying asset of the specified vToken\"},\"vTokenUnderlyingPriceAll(address[])\":{\"notice\":\"Returns the price data for the underlying assets of the specified vTokens\"}},\"notice\":\"The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be looked up for specific pools and markets: - the vToken balance of a given user; - the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address; - the vToken address in a pool for a given asset; - a list of all pools that support an asset; - the underlying asset price of a vToken; - the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Lens/PoolLens.sol\":\"PoolLens\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"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\",\"keccak256\":\"0x9140dabc466abab21b48b72dbda26736b1183a310d0e677d3719d201df026510\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x359a1ab89b46b9aba7bcad3fb651924baf4893d15153049b9976b0fc9be1358e\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x07e881de3b9f6d2c07909f193f24b96c7fe4ea60013260f3f25aecd8bab3c2f8\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x75097e35253e7fb282ee4d7f27a80eaacfa759923185bf17302a89cbc059c5ef\",\"license\":\"MIT\"},\"@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\"},\"@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\",\"keccak256\":\"0xfe0fd441c84ac907cabc88db69ef04f6d7532d770c7e6a1dfe6e7d6305debb49\",\"license\":\"BSD-3-Clause\"},\"@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 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/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface IProtocolShareReserve {\\n /// @notice it represents the type of vToken income\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(\\n address comptroller,\\n address asset,\\n IncomeType incomeType\\n ) external;\\n}\\n\",\"keccak256\":\"0x0f341bbef8f12885d79b7acaad7aaf11b84809e8f6b059ef4efc011c8f6c39a5\",\"license\":\"BSD-3-Clause\"},\"@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\",\"keccak256\":\"0x57a2bbb9b8e02b1c0a5c0e305fef1328a22db56c3d4b148c362010a6e767243c\",\"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\"},\"@venusprotocol/venus-protocol/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\",\"keccak256\":\"0xd112f60183416ad796093b4a83a80ddc1b8b655965f02ae55ca82e2a0c68f97d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/venus-protocol/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\",\"keccak256\":\"0x5285c875114db2ea2be0b81b65722d5761806217022db733323c4e03365a95e7\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IPrime } from \\\"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\\\";\\n\\nimport { ComptrollerInterface, Action } from \\\"./ComptrollerInterface.sol\\\";\\nimport { ComptrollerStorage } from \\\"./ComptrollerStorage.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"./MaxLoopsLimitHelper.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title Comptroller\\n * @author Venus\\n * @notice The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating,\\n * and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts\\n * with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows\\n * or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing\\n * liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow,\\n * as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the\\n * markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market\\u2019s corresponding liquidation threshold,\\n * the borrow is eligible for liquidation.\\n *\\n * The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed\\n * the `minLiquidatableCollateral` for the `Comptroller`:\\n *\\n * - `healAccount()`: This function is called to seize all of a given user\\u2019s collateral, requiring the `msg.sender` repay a certain percentage\\n * of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed\\n * 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt\\n * and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool.\\n * - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation\\n * incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic\\n * verifying that the repay amount does not exceed the close factor.\\n */\\ncontract Comptroller is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n ComptrollerStorage,\\n ComptrollerInterface,\\n ExponentialNoError,\\n MaxLoopsLimitHelper\\n{\\n // PoolRegistry, immutable to save on gas\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable poolRegistry;\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(VToken indexed vToken, address indexed account);\\n\\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(VToken vToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa);\\n\\n /// @notice Emitted when liquidation threshold is changed by admin\\n event NewLiquidationThreshold(\\n VToken vToken,\\n uint256 oldLiquidationThresholdMantissa,\\n uint256 newLiquidationThresholdMantissa\\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 an action is paused on a market\\n event ActionPausedMarket(VToken vToken, Action action, bool pauseState);\\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 the collateral threshold (in USD) for non-batch liquidations is changed\\n event NewMinLiquidatableCollateral(uint256 oldMinLiquidatableCollateral, uint256 newMinLiquidatableCollateral);\\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 a rewards distributor is added\\n event NewRewardsDistributor(address indexed rewardsDistributor, address indexed rewardToken);\\n\\n /// @notice Emitted when a market is supported\\n event MarketSupported(VToken vToken);\\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 a market\\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\\n\\n /// @notice Emitted when a market is unlisted\\n event MarketUnlisted(address indexed vToken);\\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 Thrown when collateral factor exceeds the upper bound\\n error InvalidCollateralFactor();\\n\\n /// @notice Thrown when liquidation threshold exceeds the collateral factor\\n error InvalidLiquidationThreshold();\\n\\n /// @notice Thrown when the action is only available to specific sender, but the real sender was different\\n error UnexpectedSender(address expectedSender, address actualSender);\\n\\n /// @notice Thrown when the oracle returns an invalid price for some asset\\n error PriceError(address vToken);\\n\\n /// @notice Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\\n error SnapshotError(address vToken, address user);\\n\\n /// @notice Thrown when the market is not listed\\n error MarketNotListed(address market);\\n\\n /// @notice Thrown when a market has an unexpected comptroller\\n error ComptrollerMismatch();\\n\\n /// @notice Thrown when user is not member of market\\n error MarketNotCollateral(address vToken, address user);\\n\\n /// @notice Thrown when borrow action is not paused\\n error BorrowActionNotPaused();\\n\\n /// @notice Thrown when mint action is not paused\\n error MintActionNotPaused();\\n\\n /// @notice Thrown when redeem action is not paused\\n error RedeemActionNotPaused();\\n\\n /// @notice Thrown when repay action is not paused\\n error RepayActionNotPaused();\\n\\n /// @notice Thrown when seize action is not paused\\n error SeizeActionNotPaused();\\n\\n /// @notice Thrown when exit market action is not paused\\n error ExitMarketActionNotPaused();\\n\\n /// @notice Thrown when transfer action is not paused\\n error TransferActionNotPaused();\\n\\n /// @notice Thrown when enter market action is not paused\\n error EnterMarketActionNotPaused();\\n\\n /// @notice Thrown when liquidate action is not paused\\n error LiquidateActionNotPaused();\\n\\n /// @notice Thrown when borrow cap is not zero\\n error BorrowCapIsNotZero();\\n\\n /// @notice Thrown when supply cap is not zero\\n error SupplyCapIsNotZero();\\n\\n /// @notice Thrown when collateral factor is not zero\\n error CollateralFactorIsNotZero();\\n\\n /**\\n * @notice Thrown during the liquidation if user's total collateral amount is lower than\\n * a predefined threshold. In this case only batch liquidations (either liquidateAccount\\n * or healAccount) are available.\\n */\\n error MinimalCollateralViolated(uint256 expectedGreaterThan, uint256 actual);\\n error CollateralExceedsThreshold(uint256 expectedLessThanOrEqualTo, uint256 actual);\\n error InsufficientCollateral(uint256 collateralToSeize, uint256 availableCollateral);\\n\\n /// @notice Thrown when the account doesn't have enough liquidity to redeem or borrow\\n error InsufficientLiquidity();\\n\\n /// @notice Thrown when trying to liquidate a healthy account\\n error InsufficientShortfall();\\n\\n /// @notice Thrown when trying to repay more than allowed by close factor\\n error TooMuchRepay();\\n\\n /// @notice Thrown if the user is trying to exit a market in which they have an outstanding debt\\n error NonzeroBorrowBalance();\\n\\n /// @notice Thrown when trying to perform an action that is paused\\n error ActionPaused(address market, Action action);\\n\\n /// @notice Thrown when trying to add a market that is already listed\\n error MarketAlreadyListed(address market);\\n\\n /// @notice Thrown if the supply cap is exceeded\\n error SupplyCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if the borrow cap is exceeded\\n error BorrowCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if delegate approval status is already set to the requested value\\n error DelegationStatusUnchanged();\\n\\n /// @param poolRegistry_ Pool registry address\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n constructor(address poolRegistry_) {\\n ensureNonzeroAddress(poolRegistry_);\\n\\n poolRegistry = poolRegistry_;\\n _disableInitializers();\\n }\\n\\n /**\\n * @param loopLimit Limit for the loops can iterate to avoid the DOS\\n * @param accessControlManager Access control manager contract address\\n */\\n function initialize(uint256 loopLimit, address accessControlManager) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager);\\n\\n _setMaxLoopsLimit(loopLimit);\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation; enabling them to be used as collateral\\n * @param vTokens The list of addresses of the vToken markets to be enabled\\n * @return errors An array of NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketEntered is emitted for each market on success\\n * @custom:error ActionPaused error is thrown if entering any of the markets is paused\\n * @custom:error MarketNotListed error is thrown if any of the markets is not listed\\n * @custom:access Not restricted\\n */\\n function enterMarkets(address[] memory vTokens) external override returns (uint256[] memory) {\\n uint256 len = vTokens.length;\\n\\n uint256[] memory results = new uint256[](len);\\n for (uint256 i; i < len; ++i) {\\n VToken vToken = VToken(vTokens[i]);\\n\\n _addToMarket(vToken, msg.sender);\\n results[i] = NO_ERROR;\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Unlist a market by setting isListed to false\\n * @dev Checks if all actions are paused, borrow/supply caps is set to 0 and collateral factor is to 0.\\n * @param market The address of the market (token) to unlist\\n * @return uint256 Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketUnlisted is emitted on success\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error BorrowActionNotPaused error is thrown if borrow action is not paused\\n * @custom:error MintActionNotPaused error is thrown if mint action is not paused\\n * @custom:error RedeemActionNotPaused error is thrown if redeem action is not paused\\n * @custom:error RepayActionNotPaused error is thrown if repay action is not paused\\n * @custom:error EnterMarketActionNotPaused error is thrown if enter market action is not paused\\n * @custom:error LiquidateActionNotPaused error is thrown if liquidate action is not paused\\n * @custom:error BorrowCapIsNotZero error is thrown if borrow cap is not zero\\n * @custom:error SupplyCapIsNotZero error is thrown if supply cap is not zero\\n * @custom:error CollateralFactorIsNotZero error is thrown if collateral factor is not zero\\n */\\n function unlistMarket(address market) external returns (uint256) {\\n _checkAccessAllowed(\\\"unlistMarket(address)\\\");\\n\\n Market storage _market = markets[market];\\n\\n if (!_market.isListed) {\\n revert MarketNotListed(market);\\n }\\n\\n if (!actionPaused(market, Action.BORROW)) {\\n revert BorrowActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.MINT)) {\\n revert MintActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.REDEEM)) {\\n revert RedeemActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.REPAY)) {\\n revert RepayActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.SEIZE)) {\\n revert SeizeActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.ENTER_MARKET)) {\\n revert EnterMarketActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.LIQUIDATE)) {\\n revert LiquidateActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.TRANSFER)) {\\n revert TransferActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.EXIT_MARKET)) {\\n revert ExitMarketActionNotPaused();\\n }\\n\\n if (borrowCaps[market] != 0) {\\n revert BorrowCapIsNotZero();\\n }\\n\\n if (supplyCaps[market] != 0) {\\n revert SupplyCapIsNotZero();\\n }\\n\\n if (_market.collateralFactorMantissa != 0) {\\n revert CollateralFactorIsNotZero();\\n }\\n\\n _market.isListed = false;\\n emit MarketUnlisted(market);\\n\\n return NO_ERROR;\\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 * @custom:event DelegateUpdated emits on success\\n * @custom:error ZeroAddressNotAllowed is thrown when delegate address is zero\\n * @custom:error DelegationStatusUnchanged is thrown if approval status is already set to the requested value\\n * @custom:access Not restricted\\n */\\n function updateDelegate(address delegate, bool approved) external {\\n ensureNonzeroAddress(delegate);\\n if (approvedDelegates[msg.sender][delegate] == approved) {\\n revert DelegationStatusUnchanged();\\n }\\n\\n approvedDelegates[msg.sender][delegate] = approved;\\n emit DelegateUpdated(msg.sender, delegate, approved);\\n }\\n\\n /**\\n * @notice Removes asset from sender's account liquidity calculation; disabling them as collateral\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketExited is emitted on success\\n * @custom:error ActionPaused error is thrown if exiting the market is paused\\n * @custom:error NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function exitMarket(address vTokenAddress) external override returns (uint256) {\\n _checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\\n VToken vToken = VToken(vTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\\n (uint256 tokensHeld, uint256 amountOwed, ) = _safeGetAccountSnapshot(vToken, msg.sender);\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n revert NonzeroBorrowBalance();\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n _checkRedeemAllowed(vTokenAddress, msg.sender, tokensHeld);\\n\\n Market storage marketToExit = markets[address(vToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return 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 // load into memory for faster iteration\\n VToken[] memory userAssetList = accountAssets[msg.sender];\\n uint256 len = userAssetList.length;\\n\\n uint256 assetIndex = len;\\n for (uint256 i; i < len; ++i) {\\n if (userAssetList[i] == vToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n VToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.pop();\\n\\n emit MarketExited(vToken, msg.sender);\\n\\n return NO_ERROR;\\n }\\n\\n /*** Policy Hooks ***/\\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 * @custom:error ActionPaused error is thrown if supplying to this market is paused\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\\n * @custom:access Not restricted\\n */\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external override {\\n _checkActionPauseState(vToken, Action.MINT);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n uint256 supplyCap = supplyCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (supplyCap != type(uint256).max) {\\n uint256 vTokenSupply = VToken(vToken).totalSupply();\\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\\n if (nextTotalSupply > supplyCap) {\\n revert SupplyCapExceeded(vToken, supplyCap);\\n }\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, minter);\\n }\\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external override {\\n _checkActionPauseState(vToken, Action.REDEEM);\\n\\n _checkRedeemAllowed(vToken, redeemer, redeemTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, redeemer);\\n }\\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 if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(redeemer, vToken);\\n }\\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 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 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 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 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 * @custom:error ActionPaused error is thrown if borrowing is paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if there is not enough collateral to borrow\\n * @custom:error BorrowCapExceeded is thrown if the borrow cap will be exceeded should this borrow succeed\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted if vToken is enabled as collateral, otherwise only vToken\\n */\\n /// disable-eslint\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external override {\\n _checkActionPauseState(vToken, Action.BORROW);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (!markets[vToken].accountMembership[borrower]) {\\n // only vTokens may call borrowAllowed if borrower not in market\\n _checkSenderIs(vToken);\\n\\n // attempt to add borrower to the market or revert\\n _addToMarket(VToken(msg.sender), borrower);\\n }\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (oracle.getUnderlyingPrice(vToken) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 borrowCap = borrowCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (borrowCap != type(uint256).max) {\\n uint256 totalBorrows = VToken(vToken).totalBorrows();\\n uint256 badDebt = VToken(vToken).badDebt();\\n uint256 nextTotalBorrows = totalBorrows + borrowAmount + badDebt;\\n if (nextTotalBorrows > borrowCap) {\\n revert BorrowCapExceeded(vToken, borrowCap);\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n borrower,\\n VToken(vToken),\\n 0,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\n }\\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 borrower The account which would borrowed the asset\\n * @custom:error ActionPaused error is thrown if repayments are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:access Not restricted\\n */\\n function preRepayHook(address vToken, address borrower) external override {\\n _checkActionPauseState(vToken, Action.REPAY);\\n\\n oracle.updatePrice(vToken);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\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 borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n * @param skipLiquidityCheck Allows the borrow to be liquidated regardless of the account liquidity\\n * @custom:error ActionPaused error is thrown if liquidations are paused in this market\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor\\n * @custom:error MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations\\n * @custom:error InsufficientShortfall is thrown when trying to liquidate a healthy account\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n */\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external override {\\n // Pause Action.LIQUIDATE on BORROWED TOKEN to prevent liquidating it.\\n // If we want to pause liquidating to vTokenCollateral, we should pause\\n // Action.SEIZE on it\\n _checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(address(vTokenBorrowed));\\n }\\n if (!markets[vTokenCollateral].isListed) {\\n revert MarketNotListed(address(vTokenCollateral));\\n }\\n\\n uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\\n\\n /* Allow accounts to be liquidated if it is a forced liquidation */\\n if (skipLiquidityCheck || isForcedLiquidationEnabled[vTokenBorrowed]) {\\n if (repayAmount > borrowBalance) {\\n revert TooMuchRepay();\\n }\\n return;\\n }\\n\\n /* The borrower must have shortfall and collateral > threshold in order to be liquidatable */\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral <= minLiquidatableCollateral) {\\n /* The liquidator should use either liquidateAccount or healAccount */\\n revert MinimalCollateralViolated(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint256 maxClose = mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance);\\n if (repayAmount > maxClose) {\\n revert TooMuchRepay();\\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 seizerContract Contract that tries to seize the asset (either borrowed vToken or Comptroller)\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @custom:error ActionPaused error is thrown if seizing this type of collateral is paused\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error ComptrollerMismatch error is when seizer contract or seized asset belong to different pools\\n * @custom:access Not restricted\\n */\\n function preSeizeHook(\\n address vTokenCollateral,\\n address seizerContract,\\n address liquidator,\\n address borrower\\n ) external override {\\n // Pause Action.SEIZE on COLLATERAL to prevent seizing it.\\n // If we want to pause liquidating vTokenBorrowed, we should pause\\n // Action.LIQUIDATE on it\\n _checkActionPauseState(vTokenCollateral, Action.SEIZE);\\n\\n Market storage market = markets[vTokenCollateral];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(vTokenCollateral);\\n }\\n\\n if (seizerContract == address(this)) {\\n // If Comptroller is the seizer, just check if collateral's comptroller\\n // is equal to the current address\\n if (address(VToken(vTokenCollateral).comptroller()) != address(this)) {\\n revert ComptrollerMismatch();\\n }\\n } else {\\n // If the seizer is not the Comptroller, check that the seizer is a\\n // listed market, and that the markets' comptrollers match\\n if (!markets[seizerContract].isListed) {\\n revert MarketNotListed(seizerContract);\\n }\\n if (VToken(vTokenCollateral).comptroller() != VToken(seizerContract).comptroller()) {\\n revert ComptrollerMismatch();\\n }\\n }\\n\\n if (!market.accountMembership[borrower]) {\\n revert MarketNotCollateral(vTokenCollateral, borrower);\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vTokenCollateral);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, borrower);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, liquidator);\\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external override {\\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 _checkRedeemAllowed(vToken, src, transferTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, src);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, dst);\\n }\\n }\\n\\n /*** Pool-level operations ***/\\n\\n /**\\n * @notice Seizes all the remaining collateral, makes msg.sender repay the existing\\n * borrows, and treats the rest of the debt as bad debt (for each market).\\n * The sender has to repay a certain percentage of the debt, computed as\\n * collateral / (borrows * liquidationIncentive).\\n * @param user account to heal\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for healing\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function healAccount(address user) external {\\n VToken[] memory userAssets = getAssetsIn(user);\\n uint256 userAssetsCount = userAssets.length;\\n\\n address liquidator = msg.sender;\\n {\\n ResilientOracleInterface oracle_ = oracle;\\n // We need all user's markets to be fresh for the computations to be correct\\n for (uint256 i; i < userAssetsCount; ++i) {\\n userAssets[i].accrueInterest();\\n oracle_.updatePrice(address(userAssets[i]));\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(user, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n // percentage = collateral / (borrows * liquidation incentive)\\n Exp memory collateral = Exp({ mantissa: snapshot.totalCollateral });\\n Exp memory scaledBorrows = mul_(\\n Exp({ mantissa: snapshot.borrows }),\\n Exp({ mantissa: liquidationIncentiveMantissa })\\n );\\n\\n Exp memory percentage = div_(collateral, scaledBorrows);\\n if (lessThanExp(Exp({ mantissa: MANTISSA_ONE }), percentage)) {\\n revert CollateralExceedsThreshold(scaledBorrows.mantissa, collateral.mantissa);\\n }\\n\\n for (uint256 i; i < userAssetsCount; ++i) {\\n VToken market = userAssets[i];\\n\\n (uint256 tokens, uint256 borrowBalance, ) = _safeGetAccountSnapshot(market, user);\\n uint256 repaymentAmount = mul_ScalarTruncate(percentage, borrowBalance);\\n\\n // Seize the entire collateral\\n if (tokens != 0) {\\n market.seize(liquidator, user, tokens);\\n }\\n // Repay a certain percentage of the borrow, forgive the rest\\n if (borrowBalance != 0) {\\n market.healBorrow(liquidator, user, repaymentAmount);\\n }\\n }\\n }\\n\\n /**\\n * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than\\n * a predefined threshold, and the account collateral can be seized to cover all borrows. If\\n * the collateral is higher than the threshold, use regular liquidations. If the collateral is\\n * below the threshold, and the account is insolvent, use healAccount.\\n * @param borrower the borrower address\\n * @param orders an array of liquidation orders\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation\\n * @custom:error InsufficientCollateral error is thrown when there is not enough collateral to cover the debt\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function liquidateAccount(address borrower, LiquidationOrder[] calldata orders) external {\\n // We will accrue interest and update the oracle prices later during the liquidation\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n // You should use the regular vToken.liquidateBorrow(...) call\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n uint256 collateralToSeize = mul_ScalarTruncate(\\n Exp({ mantissa: liquidationIncentiveMantissa }),\\n snapshot.borrows\\n );\\n if (collateralToSeize >= snapshot.totalCollateral) {\\n // There is not enough collateral to seize. Use healBorrow to repay some part of the borrow\\n // and record bad debt.\\n revert InsufficientCollateral(collateralToSeize, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n uint256 ordersCount = orders.length;\\n\\n _ensureMaxLoops(ordersCount / 2);\\n\\n for (uint256 i; i < ordersCount; ++i) {\\n if (!markets[address(orders[i].vTokenBorrowed)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenBorrowed));\\n }\\n if (!markets[address(orders[i].vTokenCollateral)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenCollateral));\\n }\\n\\n LiquidationOrder calldata order = orders[i];\\n order.vTokenBorrowed.forceLiquidateBorrow(\\n msg.sender,\\n borrower,\\n order.repayAmount,\\n order.vTokenCollateral,\\n true\\n );\\n }\\n\\n VToken[] memory borrowMarkets = getAssetsIn(borrower);\\n uint256 marketsCount = borrowMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower);\\n require(borrowBalance == 0, \\\"Nonzero borrow balance after liquidation\\\");\\n }\\n }\\n\\n /**\\n * @notice Sets the closeFactor to use when liquidating borrows\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @custom:event Emits NewCloseFactor on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCloseFactor(uint256 newCloseFactorMantissa) external {\\n _checkAccessAllowed(\\\"setCloseFactor(uint256)\\\");\\n require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, \\\"Close factor greater than maximum close factor\\\");\\n require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, \\\"Close factor smaller than minimum close factor\\\");\\n\\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev This function is restricted by the AccessControlManager\\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 * @custom:event Emits NewCollateralFactor when collateral factor is updated\\n * and NewLiquidationThreshold when liquidation threshold is updated\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InvalidCollateralFactor error is thrown when collateral factor is too high\\n * @custom:error InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor\\n * @custom:error PriceError is thrown when the oracle returns an invalid price for the asset\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCollateralFactor(\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external {\\n _checkAccessAllowed(\\\"setCollateralFactor(address,uint256,uint256)\\\");\\n\\n // Verify market is listed\\n Market storage market = markets[address(vToken)];\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Check collateral factor <= 0.9\\n if (newCollateralFactorMantissa > MAX_COLLATERAL_FACTOR_MANTISSA) {\\n revert InvalidCollateralFactor();\\n }\\n\\n // Ensure that liquidation threshold <= 1\\n if (newLiquidationThresholdMantissa > MANTISSA_ONE) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // Ensure that liquidation threshold >= CF\\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n }\\n\\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\\n emit NewLiquidationThreshold(vToken, oldLiquidationThresholdMantissa, newLiquidationThresholdMantissa);\\n }\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev This function is restricted by the AccessControlManager\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @custom:event Emits NewLiquidationIncentive on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external {\\n require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, \\\"liquidation incentive should be greater than 1e18\\\");\\n\\n _checkAccessAllowed(\\\"setLiquidationIncentive(uint256)\\\");\\n\\n // Save current value for use in log\\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\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\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Only callable by the PoolRegistry\\n * @param vToken The address of the market (token) to list\\n * @custom:error MarketAlreadyListed is thrown if the market is already listed in this pool\\n * @custom:access Only PoolRegistry\\n */\\n function supportMarket(VToken vToken) external {\\n _checkSenderIs(poolRegistry);\\n\\n if (markets[address(vToken)].isListed) {\\n revert MarketAlreadyListed(address(vToken));\\n }\\n\\n require(vToken.isVToken(), \\\"Comptroller: Invalid vToken\\\"); // Sanity check to make sure its really a VToken\\n\\n Market storage newMarket = markets[address(vToken)];\\n newMarket.isListed = true;\\n newMarket.collateralFactorMantissa = 0;\\n newMarket.liquidationThresholdMantissa = 0;\\n\\n _addMarket(address(vToken));\\n\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n rewardsDistributors[i].initializeMarket(address(vToken));\\n }\\n\\n emit MarketSupported(vToken);\\n }\\n\\n /**\\n * @notice Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A borrow cap of type(uint256).max corresponds to unlimited borrowing.\\n * @dev Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed\\n until the total borrows amount goes below the new borrow cap\\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 type(uint256).max corresponds to unlimited borrowing.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\\n _checkAccessAllowed(\\\"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 _ensureMaxLoops(numMarkets);\\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 * @notice Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A supply cap of type(uint256).max corresponds to unlimited supply.\\n * @dev Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed\\n until the total supplies amount goes below the new supply cap\\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 type(uint256).max corresponds to unlimited supply.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\\n _checkAccessAllowed(\\\"setMarketSupplyCaps(address[],uint256[])\\\");\\n uint256 vTokensCount = vTokens.length;\\n\\n require(vTokensCount != 0, \\\"invalid number of markets\\\");\\n require(vTokensCount == newSupplyCaps.length, \\\"invalid number of markets\\\");\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Pause/unpause specified actions\\n * @dev This function is restricted by the AccessControlManager\\n * @param marketsList Markets to pause/unpause the actions on\\n * @param actionsList List of action ids to pause/unpause\\n * @param paused The new paused state (true=paused, false=unpaused)\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setActionsPaused(VToken[] calldata marketsList, Action[] calldata actionsList, bool paused) external {\\n _checkAccessAllowed(\\\"setActionsPaused(address[],uint256[],bool)\\\");\\n\\n uint256 marketsCount = marketsList.length;\\n uint256 actionsCount = actionsList.length;\\n\\n _ensureMaxLoops(marketsCount * actionsCount);\\n\\n for (uint256 marketIdx; marketIdx < marketsCount; ++marketIdx) {\\n for (uint256 actionIdx; actionIdx < actionsCount; ++actionIdx) {\\n _setActionPaused(address(marketsList[marketIdx]), actionsList[actionIdx], paused);\\n }\\n }\\n }\\n\\n /**\\n * @notice Set the given collateral threshold for non-batch liquidations. Regular liquidations\\n * will fail if the collateral amount is less than this threshold. Liquidators should use batch\\n * operations like liquidateAccount or healAccount.\\n * @dev This function is restricted by the AccessControlManager\\n * @param newMinLiquidatableCollateral The new min liquidatable collateral (in USD).\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external {\\n _checkAccessAllowed(\\\"setMinLiquidatableCollateral(uint256)\\\");\\n\\n uint256 oldMinLiquidatableCollateral = minLiquidatableCollateral;\\n minLiquidatableCollateral = newMinLiquidatableCollateral;\\n emit NewMinLiquidatableCollateral(oldMinLiquidatableCollateral, newMinLiquidatableCollateral);\\n }\\n\\n /**\\n * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor\\n * contracts with the same rewardToken, and there could be overlaping among them considering the last reward slot (block or second)\\n * @dev Only callable by the admin\\n * @param _rewardsDistributor Address of the RewardDistributor contract to add\\n * @custom:access Only Governance\\n * @custom:event Emits NewRewardsDistributor with distributor address\\n */\\n function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner {\\n require(!rewardsDistributorExists[address(_rewardsDistributor)], \\\"already exists\\\");\\n\\n uint256 rewardsDistributorsLen = rewardsDistributors.length;\\n _ensureMaxLoops(rewardsDistributorsLen + 1);\\n\\n rewardsDistributors.push(_rewardsDistributor);\\n rewardsDistributorExists[address(_rewardsDistributor)] = true;\\n\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n _rewardsDistributor.initializeMarket(address(allMarkets[i]));\\n }\\n\\n emit NewRewardsDistributor(address(_rewardsDistributor), address(_rewardsDistributor.rewardToken()));\\n }\\n\\n /**\\n * @notice Sets a new price oracle for the Comptroller\\n * @dev Only callable by the admin\\n * @param newOracle Address of the new price oracle to set\\n * @custom:event Emits NewPriceOracle on success\\n * @custom:error ZeroAddressNotAllowed is thrown when the new oracle address is zero\\n */\\n function setPriceOracle(ResilientOracleInterface newOracle) external onlyOwner {\\n ensureNonzeroAddress(address(newOracle));\\n\\n ResilientOracleInterface oldOracle = oracle;\\n oracle = newOracle;\\n emit NewPriceOracle(oldOracle, newOracle);\\n }\\n\\n /**\\n * @notice Set the for loop iteration limit to avoid DOS\\n * @param limit Limit for the max loops can execute at a time\\n */\\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Sets the prime token contract for the comptroller\\n * @param _prime Address of the Prime contract\\n */\\n function setPrimeToken(IPrime _prime) external onlyOwner {\\n ensureNonzeroAddress(address(_prime));\\n\\n emit NewPrimeToken(prime, _prime);\\n prime = _prime;\\n }\\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 * @param vTokenBorrowed Borrowed vToken\\n * @param enable Whether to enable forced liquidations\\n */\\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\\n _checkAccessAllowed(\\\"setForcedLiquidation(address,bool)\\\");\\n ensureNonzeroAddress(vTokenBorrowed);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(vTokenBorrowed);\\n }\\n\\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to liquidation threshold requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of liquidation threshold requirements,\\n * @return shortfall Account shortfall below liquidation threshold requirements\\n */\\n function getAccountLiquidity(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getLiquidationThreshold);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to collateral requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of collateral requirements,\\n * @return shortfall Account shortfall below collateral requirements\\n */\\n function getBorrowingPower(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getCollateralFactor);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Hypothetical account liquidity in excess of collateral requirements,\\n * @return shortfall 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 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n account,\\n VToken(vTokenModify),\\n redeemTokens,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\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 markets The list of market addresses\\n */\\n function getAllMarkets() external view override returns (VToken[] memory) {\\n return allMarkets;\\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 /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns whether the given account is entered in a given market\\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 market specified, 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 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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return tokensToSeize Number of vTokenCollateral tokens to be seized in a liquidation\\n * @custom:error PriceError if the oracle returns an invalid price\\n */\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view override returns (uint256 error, uint256 tokensToSeize) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint256 priceBorrowedMantissa = _safeGetUnderlyingPrice(VToken(vTokenBorrowed));\\n uint256 priceCollateralMantissa = _safeGetUnderlyingPrice(VToken(vTokenCollateral));\\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 uint256 exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint256 seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n\\n numerator = mul_(Exp({ mantissa: liquidationIncentiveMantissa }), Exp({ mantissa: priceBorrowedMantissa }));\\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\\n ratio = div_(numerator, denominator);\\n\\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\\n\\n return (NO_ERROR, seizeTokens);\\n }\\n\\n /**\\n * @notice Returns reward speed given a vToken\\n * @param vToken The vToken to get the reward speeds for\\n * @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors\\n */\\n function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {\\n uint256 rewardsDistributorsLength = rewardsDistributors.length;\\n rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);\\n for (uint256 i; i < rewardsDistributorsLength; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n address rewardToken = address(rewardsDistributor.rewardToken());\\n rewardSpeeds[i] = RewardSpeeds({\\n rewardToken: rewardToken,\\n supplySpeed: rewardsDistributor.rewardTokenSupplySpeeds(vToken),\\n borrowSpeed: rewardsDistributor.rewardTokenBorrowSpeeds(vToken)\\n });\\n }\\n return rewardSpeeds;\\n }\\n\\n /**\\n * @notice Return all reward distributors for this pool\\n * @return Array of RewardDistributor addresses\\n */\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory) {\\n return rewardsDistributors;\\n }\\n\\n /**\\n * @notice A marker method that returns true for a valid Comptroller contract\\n * @return Always true\\n */\\n function isComptroller() external pure override returns (bool) {\\n return true;\\n }\\n\\n /**\\n * @notice Update the prices of all the tokens associated with the provided account\\n * @param account Address of the account to get associated tokens with\\n */\\n function updatePrices(address account) public {\\n VToken[] memory vTokens = getAssetsIn(account);\\n uint256 vTokensCount = vTokens.length;\\n\\n ResilientOracleInterface oracle_ = oracle;\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n oracle_.updatePrice(address(vTokens[i]));\\n }\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param market vToken address\\n * @param action Action to check\\n * @return paused True if the action is paused otherwise false\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][action];\\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 list with the assets the account has entered\\n */\\n function getAssetsIn(address account) public 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 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 */\\n function _addToMarket(VToken vToken, address borrower) internal {\\n _checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = markets[address(vToken)];\\n\\n if (!marketToJoin.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return;\\n }\\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\\n /**\\n * @notice Internal function to validate that a market hasn't already been added\\n * and if it hasn't adds it\\n * @param vToken The market to support\\n */\\n function _addMarket(address vToken) internal {\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n if (allMarkets[i] == VToken(vToken)) {\\n revert MarketAlreadyListed(vToken);\\n }\\n }\\n allMarkets.push(VToken(vToken));\\n marketsCount = allMarkets.length;\\n _ensureMaxLoops(marketsCount);\\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 _setActionPaused(address market, Action action, bool paused) internal {\\n require(markets[market].isListed, \\\"cannot pause a market that is not listed\\\");\\n _actionPaused[market][action] = paused;\\n emit ActionPausedMarket(VToken(market), action, paused);\\n }\\n\\n /**\\n * @dev Internal function to check that vTokens can be safely redeemed for the underlying asset.\\n * @param vToken Address of the vTokens to redeem\\n * @param redeemer Account redeeming the tokens\\n * @param redeemTokens The number of tokens to redeem\\n */\\n function _checkRedeemAllowed(address vToken, address redeemer, uint256 redeemTokens) internal {\\n Market storage market = markets[vToken];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!market.accountMembership[redeemer]) {\\n return;\\n }\\n\\n // Update the prices of tokens\\n updatePrices(redeemer);\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n _getCollateralFactor\\n );\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n }\\n\\n /**\\n * @notice Get the total collateral, weighted collateral, borrow balance, liquidity, shortfall\\n * @param account The account to get the snapshot for\\n * @param weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n * liquidation threshold. Accepts the address of the vToken and returns the weight as Exp.\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getCurrentLiquiditySnapshot(\\n address account,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n return _getHypotheticalLiquiditySnapshot(account, VToken(address(0)), 0, 0, weight);\\n }\\n\\n /**\\n * @notice Determine what the supply/borrow balances 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 weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n liquidation threshold. Accepts the address of the VToken and returns the weight\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getHypotheticalLiquiditySnapshot(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n // For each asset the account is in\\n VToken[] memory assets = getAssetsIn(account);\\n uint256 assetsCount = assets.length;\\n\\n for (uint256 i; i < assetsCount; ++i) {\\n VToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the vToken\\n (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) = _safeGetAccountSnapshot(\\n asset,\\n account\\n );\\n\\n // Get the normalized price of the asset\\n Exp memory oraclePrice = Exp({ mantissa: _safeGetUnderlyingPrice(asset) });\\n\\n // Pre-compute conversion factors from vTokens -> usd\\n Exp memory vTokenPrice = mul_(Exp({ mantissa: exchangeRateMantissa }), oraclePrice);\\n Exp memory weightedVTokenPrice = mul_(weight(asset), vTokenPrice);\\n\\n // weightedCollateral += weightedVTokenPrice * vTokenBalance\\n snapshot.weightedCollateral = mul_ScalarTruncateAddUInt(\\n weightedVTokenPrice,\\n vTokenBalance,\\n snapshot.weightedCollateral\\n );\\n\\n // totalCollateral += vTokenPrice * vTokenBalance\\n snapshot.totalCollateral = mul_ScalarTruncateAddUInt(vTokenPrice, vTokenBalance, snapshot.totalCollateral);\\n\\n // borrows += oraclePrice * borrowBalance\\n snapshot.borrows = mul_ScalarTruncateAddUInt(oraclePrice, borrowBalance, snapshot.borrows);\\n\\n // Calculate effects of interacting with vTokenModify\\n if (asset == vTokenModify) {\\n // redeem effect\\n // effects += tokensToDenom * redeemTokens\\n snapshot.effects = mul_ScalarTruncateAddUInt(weightedVTokenPrice, redeemTokens, snapshot.effects);\\n\\n // borrow effect\\n // effects += oraclePrice * borrowAmount\\n snapshot.effects = mul_ScalarTruncateAddUInt(oraclePrice, borrowAmount, snapshot.effects);\\n }\\n }\\n\\n uint256 borrowPlusEffects = snapshot.borrows + snapshot.effects;\\n // These are safe, as the underflow condition is checked first\\n unchecked {\\n if (snapshot.weightedCollateral > borrowPlusEffects) {\\n snapshot.liquidity = snapshot.weightedCollateral - borrowPlusEffects;\\n snapshot.shortfall = 0;\\n } else {\\n snapshot.liquidity = 0;\\n snapshot.shortfall = borrowPlusEffects - snapshot.weightedCollateral;\\n }\\n }\\n\\n return snapshot;\\n }\\n\\n /**\\n * @dev Retrieves price from oracle for an asset and checks it is nonzero\\n * @param asset Address for asset to query price\\n * @return Underlying price\\n */\\n function _safeGetUnderlyingPrice(VToken asset) internal view returns (uint256) {\\n uint256 oraclePriceMantissa = oracle.getUnderlyingPrice(address(asset));\\n if (oraclePriceMantissa == 0) {\\n revert PriceError(address(asset));\\n }\\n return oraclePriceMantissa;\\n }\\n\\n /**\\n * @dev Return collateral factor for a market\\n * @param asset Address for asset\\n * @return Collateral factor as exponential\\n */\\n function _getCollateralFactor(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].collateralFactorMantissa });\\n }\\n\\n /**\\n * @dev Retrieves liquidation threshold for a market as an exponential\\n * @param asset Address for asset to liquidation threshold\\n * @return Liquidation threshold as exponential\\n */\\n function _getLiquidationThreshold(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].liquidationThresholdMantissa });\\n }\\n\\n /**\\n * @dev Returns supply and borrow balances of user in vToken, reverts on failure\\n * @param vToken Market to query\\n * @param user Account address\\n * @return vTokenBalance Balance of vTokens, the same as vToken.balanceOf(user)\\n * @return borrowBalance Borrowed amount, including the interest\\n * @return exchangeRateMantissa Stored exchange rate\\n */\\n function _safeGetAccountSnapshot(\\n VToken vToken,\\n address user\\n ) internal view returns (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) {\\n uint256 err;\\n (err, vTokenBalance, borrowBalance, exchangeRateMantissa) = vToken.getAccountSnapshot(user);\\n if (err != 0) {\\n revert SnapshotError(address(vToken), user);\\n }\\n return (vTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /// @notice Reverts if the call is not from expectedSender\\n /// @param expectedSender Expected transaction sender\\n function _checkSenderIs(address expectedSender) internal view {\\n if (msg.sender != expectedSender) {\\n revert UnexpectedSender(expectedSender, msg.sender);\\n }\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n /// @param market Market to check\\n /// @param action Action to check\\n function _checkActionPauseState(address market, Action action) private view {\\n if (actionPaused(market, action)) {\\n revert ActionPaused(market, action);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7c6e1c6264e4681f82a9ac1bcd9155197a930033291ee5561ad97a56006f5e9c\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.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\\n/**\\n * @title ComptrollerInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract.\\n */\\ninterface ComptrollerInterface {\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\\n\\n function exitMarket(address vToken) external returns (uint256);\\n\\n /*** Policy Hooks ***/\\n\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external;\\n\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external;\\n\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external;\\n\\n function preRepayHook(address vToken, address borrower) external;\\n\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external;\\n\\n function preSeizeHook(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower\\n ) external;\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\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 seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external;\\n\\n function isComptroller() external view returns (bool);\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 repayAmount\\n ) external view returns (uint256, uint256);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n}\\n\\n/**\\n * @title ComptrollerViewInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract, including only some util view functions.\\n */\\ninterface ComptrollerViewInterface {\\n function markets(address) external view returns (bool, uint256);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function closeFactorMantissa() external view returns (uint256);\\n\\n function liquidationIncentiveMantissa() external view returns (uint256);\\n\\n function minLiquidatableCollateral() external view returns (uint256);\\n\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function borrowCaps(address) external view returns (uint256);\\n\\n function supplyCaps(address) external view returns (uint256);\\n\\n function approvedDelegates(address user, address delegate) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xcbf7f9977472650c61345b7cbde23e81f626e1f8863bab4c6ce3dacfc7604919\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { IPrime } from \\\"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\\\";\\nimport { Action } from \\\"./ComptrollerInterface.sol\\\";\\n\\n/**\\n * @title ComptrollerStorage\\n * @author Venus\\n * @notice Storage layout for the `Comptroller` contract.\\n */\\ncontract ComptrollerStorage {\\n struct LiquidationOrder {\\n VToken vTokenCollateral;\\n VToken vTokenBorrowed;\\n uint256 repayAmount;\\n }\\n\\n struct AccountLiquiditySnapshot {\\n uint256 totalCollateral;\\n uint256 weightedCollateral;\\n uint256 borrows;\\n uint256 effects;\\n uint256 liquidity;\\n uint256 shortfall;\\n }\\n\\n struct RewardSpeeds {\\n address rewardToken;\\n uint256 supplySpeed;\\n uint256 borrowSpeed;\\n }\\n\\n struct Market {\\n // Whether or not this market is listed\\n bool isListed;\\n // 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 uint256 collateralFactorMantissa;\\n // 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 uint256 liquidationThresholdMantissa;\\n // Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n }\\n\\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 Per-account mapping of \\\"assets you are in\\\"\\n */\\n mapping(address => VToken[]) public accountAssets;\\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 /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\\n mapping(address => uint256) public borrowCaps;\\n\\n /// @notice Minimal collateral required for regular (non-batch) liquidations\\n uint256 public minLiquidatableCollateral;\\n\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\\n mapping(address => uint256) public supplyCaps;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(Action => bool)) internal _actionPaused;\\n\\n // List of Reward Distributors added\\n RewardsDistributor[] internal rewardsDistributors;\\n\\n // Used to check if rewards distributor is added\\n mapping(address => bool) internal rewardsDistributorExists;\\n\\n /// @notice Flag indicating whether forced liquidation enabled for a market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n\\n uint256 internal constant NO_ERROR = 0;\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant MIN_CLOSE_FACTOR_MANTISSA = 0.05e18; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant MAX_CLOSE_FACTOR_MANTISSA = 0.9e18; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.95e18; // 0.95\\n\\n /// Prime token address\\n IPrime public prime;\\n\\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 /**\\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[47] private __gap;\\n}\\n\",\"keccak256\":\"0x4df44cb65ac152bac2be4b4545430e703005a74a55b72e144100b16421bd8bfd\",\"license\":\"BSD-3-Clause\"},\"contracts/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title TokenErrorReporter\\n * @author Venus\\n * @notice Errors that can be thrown by the `VToken` contract.\\n */\\ncontract TokenErrorReporter {\\n uint256 public constant NO_ERROR = 0; // support legacy return codes\\n\\n error TransferNotAllowed();\\n\\n error MintFreshnessCheck();\\n\\n error RedeemFreshnessCheck();\\n error RedeemTransferOutNotPossible();\\n\\n error BorrowFreshnessCheck();\\n error BorrowCashNotAvailable();\\n error DelegateNotApproved();\\n\\n error RepayBorrowFreshnessCheck();\\n\\n error HealBorrowUnauthorized();\\n error ForceLiquidateBorrowUnauthorized();\\n\\n error LiquidateFreshnessCheck();\\n error LiquidateCollateralFreshnessCheck();\\n error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\\n error LiquidateLiquidatorIsBorrower();\\n error LiquidateCloseAmountIsZero();\\n error LiquidateCloseAmountIsUintMax();\\n\\n error LiquidateSeizeLiquidatorIsBorrower();\\n\\n error ProtocolSeizeShareTooBig();\\n\\n error SetReserveFactorFreshCheck();\\n error SetReserveFactorBoundsCheck();\\n\\n error AddReservesFactorFreshCheck(uint256 actualAddAmount);\\n\\n error ReduceReservesFreshCheck();\\n error ReduceReservesCashNotAvailable();\\n error ReduceReservesCashValidation();\\n\\n error SetInterestRateModelFreshCheck();\\n}\\n\",\"keccak256\":\"0x7a7ced1caaac2d9242659ebd50b99f308c725ce958ac9e11f7ada404b1d97a7b\",\"license\":\"BSD-3-Clause\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from \\\"./lib/constants.sol\\\";\\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 struct Exp {\\n uint256 mantissa;\\n }\\n\\n struct Double {\\n uint256 mantissa;\\n }\\n\\n uint256 internal constant EXP_SCALE = EXP_SCALE_;\\n uint256 internal constant DOUBLE_SCALE = 1e36;\\n uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;\\n uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint256) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / EXP_SCALE;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\\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 // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint256 scalar, uint256 addend) internal pure returns (uint256) {\\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 function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\\n require(n <= type(uint224).max, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\\n require(n <= type(uint32).max, 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_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a + b;\\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_(uint256 a, uint256 b) internal pure returns (uint256) {\\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) / EXP_SCALE });\\n }\\n\\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / EXP_SCALE;\\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) / DOUBLE_SCALE });\\n }\\n\\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / DOUBLE_SCALE;\\n }\\n\\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a * b;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return div_(mul_(a, EXP_SCALE), 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, DOUBLE_SCALE), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return div_(mul_(a, DOUBLE_SCALE), b.mantissa);\\n }\\n\\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a / b;\\n }\\n\\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });\\n }\\n}\\n\",\"keccak256\":\"0x8afbe8a24fe3539c124e718681ed3dcebd24c40dd53095786c0155998213b9b0\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModel.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\nabstract contract InterestRateModel {\\n /**\\n * @notice Calculates the current borrow interest rate per slot (block or second)\\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 amount of reserves the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per slot (block or second)\\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 amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\\n * @return Always true\\n */\\n function isInterestRateModel() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xc4fda1ab75ebe4b187b707c4f10c58780f343cf343c537f641dc75d3cd28ab51\",\"license\":\"BSD-3-Clause\"},\"contracts/Lens/PoolLens.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { IERC20Metadata } from \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Action, ComptrollerInterface, ComptrollerViewInterface } from \\\"../ComptrollerInterface.sol\\\";\\nimport { PoolRegistryInterface } from \\\"../Pool/PoolRegistryInterface.sol\\\";\\nimport { PoolRegistry } from \\\"../Pool/PoolRegistry.sol\\\";\\nimport { RewardsDistributor } from \\\"../Rewards/RewardsDistributor.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\n\\n/**\\n * @title PoolLens\\n * @author Venus\\n * @notice The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information\\n * for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be\\n * looked up for specific pools and markets:\\n- the vToken balance of a given user;\\n- the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address;\\n- the vToken address in a pool for a given asset;\\n- a list of all pools that support an asset;\\n- the underlying asset price of a vToken;\\n- the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\\n */\\ncontract PoolLens is ExponentialNoError, TimeManagerV8 {\\n /**\\n * @dev Struct for PoolDetails.\\n */\\n struct PoolData {\\n string name;\\n address creator;\\n address comptroller;\\n uint256 blockPosted;\\n uint256 timestampPosted;\\n string category;\\n string logoURL;\\n string description;\\n address priceOracle;\\n uint256 closeFactor;\\n uint256 liquidationIncentive;\\n uint256 minLiquidatableCollateral;\\n VTokenMetadata[] vTokens;\\n }\\n\\n /**\\n * @dev Struct for VToken.\\n */\\n struct VTokenMetadata {\\n address vToken;\\n uint256 exchangeRateCurrent;\\n uint256 supplyRatePerBlockOrTimestamp;\\n uint256 borrowRatePerBlockOrTimestamp;\\n uint256 reserveFactorMantissa;\\n uint256 supplyCaps;\\n uint256 borrowCaps;\\n uint256 totalBorrows;\\n uint256 totalReserves;\\n uint256 totalSupply;\\n uint256 totalCash;\\n bool isListed;\\n uint256 collateralFactorMantissa;\\n address underlyingAssetAddress;\\n uint256 vTokenDecimals;\\n uint256 underlyingDecimals;\\n uint256 pausedActions;\\n }\\n\\n /**\\n * @dev Struct for VTokenBalance.\\n */\\n struct VTokenBalances {\\n address vToken;\\n uint256 balanceOf;\\n uint256 borrowBalanceCurrent;\\n uint256 balanceOfUnderlying;\\n uint256 tokenBalance;\\n uint256 tokenAllowance;\\n }\\n\\n /**\\n * @dev Struct for underlyingPrice of VToken.\\n */\\n struct VTokenUnderlyingPrice {\\n address vToken;\\n uint256 underlyingPrice;\\n }\\n\\n /**\\n * @dev Struct with pending reward info for a market.\\n */\\n struct PendingReward {\\n address vTokenAddress;\\n uint256 amount;\\n }\\n\\n /**\\n * @dev Struct with reward distribution totals for a single reward token and distributor.\\n */\\n struct RewardSummary {\\n address distributorAddress;\\n address rewardTokenAddress;\\n uint256 totalRewards;\\n PendingReward[] pendingRewards;\\n }\\n\\n /**\\n * @dev Struct used in RewardDistributor to save last updated market state.\\n */\\n struct RewardTokenState {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number or timestamp the index was last updated at\\n uint256 blockOrTimestamp;\\n // The block number or timestamp at which to stop rewards\\n uint256 lastRewardingBlockOrTimestamp;\\n }\\n\\n /**\\n * @dev Struct with bad debt of a market denominated\\n */\\n struct BadDebt {\\n address vTokenAddress;\\n uint256 badDebtUsd;\\n }\\n\\n /**\\n * @dev Struct with bad debt total denominated in usd for a pool and an array of BadDebt structs for each market\\n */\\n struct BadDebtSummary {\\n address comptroller;\\n uint256 totalBadDebtUsd;\\n BadDebt[] badDebts;\\n }\\n\\n /// @notice Address of the core pool comptroller (all markets are returned for this pool, including paused ones)\\n address public immutable corePoolComptroller;\\n\\n /**\\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @param corePoolComptroller_ The address of the core pool comptroller\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(\\n bool timeBased_,\\n uint256 blocksPerYear_,\\n address corePoolComptroller_\\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\\n corePoolComptroller = corePoolComptroller_;\\n }\\n\\n /**\\n * @notice Queries the user's supply/borrow balances in vTokens\\n * @param vTokens The list of vToken addresses\\n * @param account The user Account\\n * @return A list of structs containing balances data\\n */\\n function vTokenBalancesAll(VToken[] calldata vTokens, address account) external returns (VTokenBalances[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenBalances[] memory res = new VTokenBalances[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenBalances(vTokens[i], account);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Queries all pools with addtional details for each of them\\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @return Arrays of all Venus pools' data\\n */\\n function getAllPools(address poolRegistryAddress) external view returns (PoolData[] memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n PoolRegistry.VenusPool[] memory venusPools = poolRegistryInterface.getAllPools();\\n uint256 poolLength = venusPools.length;\\n\\n PoolData[] memory poolDataItems = new PoolData[](poolLength);\\n\\n for (uint256 i; i < poolLength; ++i) {\\n PoolRegistry.VenusPool memory venusPool = venusPools[i];\\n PoolData memory poolData = getPoolDataFromVenusPool(poolRegistryAddress, venusPool);\\n poolDataItems[i] = poolData;\\n }\\n\\n return poolDataItems;\\n }\\n\\n /**\\n * @notice Queries the details of a pool identified by Comptroller address\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param comptroller The Comptroller implementation address\\n * @return PoolData structure containing the details of the pool\\n */\\n function getPoolByComptroller(\\n address poolRegistryAddress,\\n address comptroller\\n ) external view returns (PoolData memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return getPoolDataFromVenusPool(poolRegistryAddress, poolRegistryInterface.getPoolByComptroller(comptroller));\\n }\\n\\n /**\\n * @notice Returns vToken holding the specified underlying asset in the specified pool\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param comptroller The pool comptroller\\n * @param asset The underlyingAsset of VToken\\n * @return Address of the vToken\\n */\\n function getVTokenForAsset(\\n address poolRegistryAddress,\\n address comptroller,\\n address asset\\n ) external view returns (address) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return poolRegistryInterface.getVTokenForAsset(comptroller, asset);\\n }\\n\\n /**\\n * @notice Returns all pools that support the specified underlying asset\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param asset The underlying asset of vToken\\n * @return A list of Comptroller contracts\\n */\\n function getPoolsSupportedByAsset(\\n address poolRegistryAddress,\\n address asset\\n ) external view returns (address[] memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return poolRegistryInterface.getPoolsSupportedByAsset(asset);\\n }\\n\\n /**\\n * @notice Returns the price data for the underlying assets of the specified vTokens\\n * @param vTokens The list of vToken addresses\\n * @return An array containing the price data for each asset\\n */\\n function vTokenUnderlyingPriceAll(\\n VToken[] calldata vTokens\\n ) external view returns (VTokenUnderlyingPrice[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenUnderlyingPrice[] memory res = new VTokenUnderlyingPrice[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenUnderlyingPrice(vTokens[i]);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Returns the pending rewards for a user for a given pool.\\n * @param account The user account.\\n * @param comptrollerAddress address\\n * @return Pending rewards array\\n */\\n function getPendingRewards(\\n address account,\\n address comptrollerAddress\\n ) external view returns (RewardSummary[] memory) {\\n VToken[] memory markets = _getMarkets(ComptrollerInterface(comptrollerAddress));\\n RewardsDistributor[] memory rewardsDistributors = ComptrollerViewInterface(comptrollerAddress)\\n .getRewardDistributors();\\n RewardSummary[] memory rewardSummary = new RewardSummary[](rewardsDistributors.length);\\n for (uint256 i; i < rewardsDistributors.length; ++i) {\\n RewardSummary memory reward;\\n reward.distributorAddress = address(rewardsDistributors[i]);\\n reward.rewardTokenAddress = address(rewardsDistributors[i].rewardToken());\\n reward.totalRewards = rewardsDistributors[i].rewardTokenAccrued(account);\\n reward.pendingRewards = _calculateNotDistributedAwards(account, markets, rewardsDistributors[i]);\\n rewardSummary[i] = reward;\\n }\\n return rewardSummary;\\n }\\n\\n /**\\n * @notice Returns a summary of a pool's bad debt broken down by market\\n *\\n * @param comptrollerAddress Address of the comptroller\\n *\\n * @return badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and\\n * a break down of bad debt by market\\n */\\n function getPoolBadDebt(address comptrollerAddress) external view returns (BadDebtSummary memory) {\\n uint256 totalBadDebtUsd;\\n\\n // Get every listed market in the pool\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\\n VToken[] memory markets = _getMarkets(ComptrollerInterface(comptrollerAddress));\\n ResilientOracleInterface priceOracle = comptroller.oracle();\\n\\n BadDebt[] memory badDebts = new BadDebt[](markets.length);\\n\\n BadDebtSummary memory badDebtSummary;\\n badDebtSummary.comptroller = comptrollerAddress;\\n badDebtSummary.badDebts = badDebts;\\n\\n // // Calculate the bad debt is USD per market\\n for (uint256 i; i < markets.length; ++i) {\\n BadDebt memory badDebt;\\n badDebt.vTokenAddress = address(markets[i]);\\n badDebt.badDebtUsd =\\n (VToken(address(markets[i])).badDebt() * priceOracle.getUnderlyingPrice(address(markets[i]))) /\\n EXP_SCALE;\\n badDebtSummary.badDebts[i] = badDebt;\\n totalBadDebtUsd = totalBadDebtUsd + badDebt.badDebtUsd;\\n }\\n\\n badDebtSummary.totalBadDebtUsd = totalBadDebtUsd;\\n\\n return badDebtSummary;\\n }\\n\\n /**\\n * @notice Queries the user's supply/borrow balances in the specified vToken\\n * @param vToken vToken address\\n * @param account The user Account\\n * @return A struct containing the balances data\\n */\\n function vTokenBalances(VToken vToken, address account) public returns (VTokenBalances memory) {\\n uint256 balanceOf = vToken.balanceOf(account);\\n uint256 borrowBalanceCurrent = vToken.borrowBalanceCurrent(account);\\n uint256 balanceOfUnderlying = vToken.balanceOfUnderlying(account);\\n uint256 tokenBalance;\\n uint256 tokenAllowance;\\n\\n IERC20 underlying = IERC20(vToken.underlying());\\n tokenBalance = underlying.balanceOf(account);\\n tokenAllowance = underlying.allowance(account, address(vToken));\\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 Queries additional information for the pool\\n * @param poolRegistryAddress Address of the PoolRegistry\\n * @param venusPool The VenusPool Object from PoolRegistry\\n * @return Enriched PoolData\\n */\\n function getPoolDataFromVenusPool(\\n address poolRegistryAddress,\\n PoolRegistry.VenusPool memory venusPool\\n ) public view returns (PoolData memory) {\\n // Get tokens in the Pool\\n ComptrollerInterface comptrollerInstance = ComptrollerInterface(venusPool.comptroller);\\n\\n VToken[] memory vTokens = _getMarkets(comptrollerInstance);\\n\\n VTokenMetadata[] memory vTokenMetadataItems = vTokenMetadataAll(vTokens);\\n\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n\\n PoolRegistry.VenusPoolMetaData memory venusPoolMetaData = poolRegistryInterface.getVenusPoolMetadata(\\n venusPool.comptroller\\n );\\n\\n ComptrollerViewInterface comptrollerViewInstance = ComptrollerViewInterface(venusPool.comptroller);\\n\\n PoolData memory poolData = PoolData({\\n name: venusPool.name,\\n creator: venusPool.creator,\\n comptroller: venusPool.comptroller,\\n blockPosted: venusPool.blockPosted,\\n timestampPosted: venusPool.timestampPosted,\\n category: venusPoolMetaData.category,\\n logoURL: venusPoolMetaData.logoURL,\\n description: venusPoolMetaData.description,\\n vTokens: vTokenMetadataItems,\\n priceOracle: address(comptrollerViewInstance.oracle()),\\n closeFactor: comptrollerViewInstance.closeFactorMantissa(),\\n liquidationIncentive: comptrollerViewInstance.liquidationIncentiveMantissa(),\\n minLiquidatableCollateral: comptrollerViewInstance.minLiquidatableCollateral()\\n });\\n\\n return poolData;\\n }\\n\\n /**\\n * @notice Returns the metadata of VToken\\n * @param vToken The address of vToken\\n * @return VTokenMetadata struct\\n */\\n function vTokenMetadata(VToken vToken) public view returns (VTokenMetadata memory) {\\n uint256 exchangeRateCurrent = vToken.exchangeRateStored();\\n address comptrollerAddress = address(vToken.comptroller());\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\\n (bool isListed, uint256 collateralFactorMantissa) = comptroller.markets(address(vToken));\\n\\n address underlyingAssetAddress = vToken.underlying();\\n uint256 underlyingDecimals = IERC20Metadata(underlyingAssetAddress).decimals();\\n\\n uint256 pausedActions;\\n for (uint8 i; i <= uint8(type(Action).max); ++i) {\\n uint256 paused = ComptrollerInterface(comptrollerAddress).actionPaused(address(vToken), Action(i)) ? 1 : 0;\\n pausedActions |= paused << i;\\n }\\n\\n uint256 supplyRatePerBlock;\\n\\n if (vToken.totalSupply() > 0) {\\n supplyRatePerBlock = vToken.supplyRatePerBlock();\\n }\\n\\n return\\n VTokenMetadata({\\n vToken: address(vToken),\\n exchangeRateCurrent: exchangeRateCurrent,\\n supplyRatePerBlockOrTimestamp: supplyRatePerBlock,\\n borrowRatePerBlockOrTimestamp: vToken.borrowRatePerBlock(),\\n reserveFactorMantissa: vToken.reserveFactorMantissa(),\\n supplyCaps: comptroller.supplyCaps(address(vToken)),\\n borrowCaps: comptroller.borrowCaps(address(vToken)),\\n totalBorrows: vToken.totalBorrows(),\\n totalReserves: vToken.totalReserves(),\\n totalSupply: vToken.totalSupply(),\\n totalCash: vToken.getCash(),\\n isListed: isListed,\\n collateralFactorMantissa: collateralFactorMantissa,\\n underlyingAssetAddress: underlyingAssetAddress,\\n vTokenDecimals: vToken.decimals(),\\n underlyingDecimals: underlyingDecimals,\\n pausedActions: pausedActions\\n });\\n }\\n\\n /**\\n * @notice Returns the metadata of all VTokens\\n * @param vTokens The list of vToken addresses\\n * @return An array of VTokenMetadata structs\\n */\\n function vTokenMetadataAll(VToken[] memory vTokens) public view returns (VTokenMetadata[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenMetadata[] memory res = new VTokenMetadata[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenMetadata(vTokens[i]);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Returns the price data for the underlying asset of the specified vToken\\n * @param vToken vToken address\\n * @return The price data for each asset\\n */\\n function vTokenUnderlyingPrice(VToken vToken) public view returns (VTokenUnderlyingPrice memory) {\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(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 Returns markets from a comptroller. For the core pool, all markets are returned.\\n * For other pools, markets with zero internalCash are filtered.\\n * @param comptroller The comptroller to query\\n * @return An array of VToken addresses\\n */\\n function _getMarkets(ComptrollerInterface comptroller) internal view returns (VToken[] memory) {\\n VToken[] memory allMarkets = comptroller.getAllMarkets();\\n\\n if (address(comptroller) == corePoolComptroller) {\\n return allMarkets;\\n }\\n\\n // Single-loop filter: pack active markets to the front of allMarkets\\n uint256 count;\\n uint256 len = allMarkets.length;\\n for (uint256 i; i < len; ++i) {\\n if (allMarkets[i].internalCash() > 0) {\\n allMarkets[count] = allMarkets[i];\\n ++count;\\n }\\n }\\n\\n // Trim the array to the active count\\n assembly {\\n mstore(allMarkets, count)\\n }\\n\\n return allMarkets;\\n }\\n\\n function _calculateNotDistributedAwards(\\n address account,\\n VToken[] memory markets,\\n RewardsDistributor rewardsDistributor\\n ) internal view returns (PendingReward[] memory) {\\n PendingReward[] memory pendingRewards = new PendingReward[](markets.length);\\n\\n for (uint256 i; i < markets.length; ++i) {\\n // Market borrow and supply state we will modify update in-memory, in order to not modify storage\\n RewardTokenState memory borrowState;\\n RewardTokenState memory supplyState;\\n\\n if (isTimeBased) {\\n (\\n borrowState.index,\\n borrowState.blockOrTimestamp,\\n borrowState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenBorrowStateTimeBased(address(markets[i]));\\n (\\n supplyState.index,\\n supplyState.blockOrTimestamp,\\n supplyState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenSupplyStateTimeBased(address(markets[i]));\\n } else {\\n (\\n borrowState.index,\\n borrowState.blockOrTimestamp,\\n borrowState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenBorrowState(address(markets[i]));\\n (\\n supplyState.index,\\n supplyState.blockOrTimestamp,\\n supplyState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenSupplyState(address(markets[i]));\\n }\\n\\n Exp memory marketBorrowIndex = Exp({ mantissa: markets[i].borrowIndex() });\\n\\n // Update market supply and borrow index in-memory\\n updateMarketBorrowIndex(address(markets[i]), rewardsDistributor, borrowState, marketBorrowIndex);\\n updateMarketSupplyIndex(address(markets[i]), rewardsDistributor, supplyState);\\n\\n // Calculate pending rewards\\n uint256 borrowReward = calculateBorrowerReward(\\n address(markets[i]),\\n rewardsDistributor,\\n account,\\n borrowState,\\n marketBorrowIndex\\n );\\n uint256 supplyReward = calculateSupplierReward(\\n address(markets[i]),\\n rewardsDistributor,\\n account,\\n supplyState\\n );\\n\\n PendingReward memory pendingReward;\\n pendingReward.vTokenAddress = address(markets[i]);\\n pendingReward.amount = borrowReward + supplyReward;\\n pendingRewards[i] = pendingReward;\\n }\\n return pendingRewards;\\n }\\n\\n function updateMarketBorrowIndex(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n RewardTokenState memory borrowState,\\n Exp memory marketBorrowIndex\\n ) internal view {\\n uint256 borrowSpeed = rewardsDistributor.rewardTokenBorrowSpeeds(vToken);\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (\\n borrowState.lastRewardingBlockOrTimestamp > 0 &&\\n blockNumberOrTimestamp > borrowState.lastRewardingBlockOrTimestamp\\n ) {\\n blockNumberOrTimestamp = borrowState.lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, borrowState.blockOrTimestamp);\\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\\n // Remove the total earned interest rate since the opening of the market from total borrows\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, borrowSpeed);\\n Double memory ratio = borrowAmount > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\\n } else if (deltaBlocksOrTimestamp > 0) {\\n borrowState.blockOrTimestamp = blockNumberOrTimestamp;\\n }\\n }\\n\\n function updateMarketSupplyIndex(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n RewardTokenState memory supplyState\\n ) internal view {\\n uint256 supplySpeed = rewardsDistributor.rewardTokenSupplySpeeds(vToken);\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (\\n supplyState.lastRewardingBlockOrTimestamp > 0 &&\\n blockNumberOrTimestamp > supplyState.lastRewardingBlockOrTimestamp\\n ) {\\n blockNumberOrTimestamp = supplyState.lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, supplyState.blockOrTimestamp);\\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, supplySpeed);\\n Double memory ratio = supplyTokens > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\\n } else if (deltaBlocksOrTimestamp > 0) {\\n supplyState.blockOrTimestamp = blockNumberOrTimestamp;\\n }\\n }\\n\\n function calculateBorrowerReward(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n address borrower,\\n RewardTokenState memory borrowState,\\n Exp memory marketBorrowIndex\\n ) internal view returns (uint256) {\\n Double memory borrowIndex = Double({ mantissa: borrowState.index });\\n Double memory borrowerIndex = Double({\\n mantissa: rewardsDistributor.rewardTokenBorrowerIndex(vToken, borrower)\\n });\\n if (borrowerIndex.mantissa == 0 && borrowIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set\\n borrowerIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\\n }\\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n return borrowerDelta;\\n }\\n\\n function calculateSupplierReward(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n address supplier,\\n RewardTokenState memory supplyState\\n ) internal view returns (uint256) {\\n Double memory supplyIndex = Double({ mantissa: supplyState.index });\\n Double memory supplierIndex = Double({\\n mantissa: rewardsDistributor.rewardTokenSupplierIndex(vToken, supplier)\\n });\\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\\n // Covers the case where users supplied tokens before the market's supply state index was set\\n supplierIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\\n }\\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n return supplierDelta;\\n }\\n}\\n\",\"keccak256\":\"0xfe3f00ebb7f0b5c98ee03cf1cfa1a013a56984cf6879373c70a74b3d9d0db399\",\"license\":\"BSD-3-Clause\"},\"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\",\"keccak256\":\"0x4c25e30635485d162177effa384eee51768b0141a567a0da16ff6ad673274166\",\"license\":\"BSD-3-Clause\"},\"contracts/Pool/PoolRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\nimport { PoolRegistryInterface } from \\\"./PoolRegistryInterface.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"../lib/validators.sol\\\";\\n\\n/**\\n * @title PoolRegistry\\n * @author Venus\\n * @notice The Isolated Pools architecture centers around the `PoolRegistry` contract. The `PoolRegistry` maintains a directory of isolated lending\\n * pools and can perform actions like creating and registering new pools, adding new markets to existing pools, setting and updating the pool's required\\n * metadata, and providing the getter methods to get information on the pools.\\n *\\n * Isolated lending has three main components: PoolRegistry, pools, and markets. The PoolRegistry is responsible for managing pools.\\n * It can create new pools, update pool metadata and manage markets within pools. PoolRegistry contains getter methods to get the details of\\n * any existing pool like `getVTokenForAsset` and `getPoolsSupportedByAsset`. It also contains methods for updating pool metadata (`updatePoolMetadata`)\\n * and setting pool name (`setPoolName`).\\n *\\n * The directory of pools is managed through two mappings: `_poolByComptroller` which is a hashmap with the comptroller address as the key and `VenusPool` as\\n * the value and `_poolsByID` which is an array of comptroller addresses. Individual pools can be accessed by calling `getPoolByComptroller` with the pool's\\n * comptroller address. `_poolsByID` is used to iterate through all of the pools.\\n *\\n * PoolRegistry also contains a map of asset addresses called `_supportedPools` that maps to an array of assets suppored by each pool. This array of pools by\\n * asset is retrieved by calling `getPoolsSupportedByAsset`.\\n *\\n * PoolRegistry registers new isolated pools in the directory with the `createRegistryPool` method. Isolated pools are composed of independent markets with\\n * specific assets and custom risk management configurations according to their markets.\\n */\\ncontract PoolRegistry is Ownable2StepUpgradeable, AccessControlledV8, PoolRegistryInterface {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n struct AddMarketInput {\\n VToken vToken;\\n uint256 collateralFactor;\\n uint256 liquidationThreshold;\\n uint256 initialSupply;\\n address vTokenReceiver;\\n uint256 supplyCap;\\n uint256 borrowCap;\\n }\\n\\n uint256 internal constant MAX_POOL_NAME_LENGTH = 100;\\n\\n /**\\n * @notice Maps pool's comptroller address to metadata.\\n */\\n mapping(address => VenusPoolMetaData) public metadata;\\n\\n /**\\n * @dev Maps pool ID to pool's comptroller address\\n */\\n mapping(uint256 => address) private _poolsByID;\\n\\n /**\\n * @dev Total number of pools created.\\n */\\n uint256 private _numberOfPools;\\n\\n /**\\n * @dev Maps comptroller address to Venus pool Index.\\n */\\n mapping(address => VenusPool) private _poolByComptroller;\\n\\n /**\\n * @dev Maps pool's comptroller address to asset to vToken.\\n */\\n mapping(address => mapping(address => address)) private _vTokens;\\n\\n /**\\n * @dev Maps asset to list of supported pools.\\n */\\n mapping(address => address[]) private _supportedPools;\\n\\n /**\\n * @notice Emitted when a new Venus pool is added to the directory.\\n */\\n event PoolRegistered(address indexed comptroller, VenusPool pool);\\n\\n /**\\n * @notice Emitted when a pool name is set.\\n */\\n event PoolNameSet(address indexed comptroller, string oldName, string newName);\\n\\n /**\\n * @notice Emitted when a pool metadata is updated.\\n */\\n event PoolMetadataUpdated(\\n address indexed comptroller,\\n VenusPoolMetaData oldMetadata,\\n VenusPoolMetaData newMetadata\\n );\\n\\n /**\\n * @notice Emitted when a Market is added to the pool.\\n */\\n event MarketAdded(address indexed comptroller, address indexed vTokenAddress);\\n\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor() {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializes the deployer to owner\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(address accessControlManager_) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n /**\\n * @notice Adds a new Venus pool to the directory\\n * @dev Price oracle must be configured before adding a pool\\n * @param name The name of the pool\\n * @param comptroller Pool's Comptroller contract\\n * @param closeFactor The pool's close factor (scaled by 1e18)\\n * @param liquidationIncentive The pool's liquidation incentive (scaled by 1e18)\\n * @param minLiquidatableCollateral Minimal collateral for regular (non-batch) liquidations flow\\n * @return index The index of the registered Venus pool\\n * @custom:error ZeroAddressNotAllowed is thrown when Comptroller address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\\n */\\n function addPool(\\n string calldata name,\\n Comptroller comptroller,\\n uint256 closeFactor,\\n uint256 liquidationIncentive,\\n uint256 minLiquidatableCollateral\\n ) external virtual returns (uint256 index) {\\n _checkAccessAllowed(\\\"addPool(string,address,uint256,uint256,uint256)\\\");\\n // Input validation\\n ensureNonzeroAddress(address(comptroller));\\n ensureNonzeroAddress(address(comptroller.oracle()));\\n\\n uint256 poolId = _registerPool(name, address(comptroller));\\n\\n // Set Venus pool parameters\\n comptroller.setCloseFactor(closeFactor);\\n comptroller.setLiquidationIncentive(liquidationIncentive);\\n comptroller.setMinLiquidatableCollateral(minLiquidatableCollateral);\\n\\n return poolId;\\n }\\n\\n /**\\n * @notice Add a market to an existing pool and then mint to provide initial supply\\n * @param input The structure describing the parameters for adding a market to a pool\\n * @custom:error ZeroAddressNotAllowed is thrown when vToken address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when vTokenReceiver address is zero\\n */\\n function addMarket(AddMarketInput memory input) external {\\n _checkAccessAllowed(\\\"addMarket(AddMarketInput)\\\");\\n ensureNonzeroAddress(address(input.vToken));\\n ensureNonzeroAddress(input.vTokenReceiver);\\n require(input.initialSupply > 0, \\\"PoolRegistry: initialSupply is zero\\\");\\n\\n VToken vToken = input.vToken;\\n address vTokenAddress = address(vToken);\\n address comptrollerAddress = address(vToken.comptroller());\\n Comptroller comptroller = Comptroller(comptrollerAddress);\\n address underlyingAddress = vToken.underlying();\\n IERC20Upgradeable underlying = IERC20Upgradeable(underlyingAddress);\\n\\n require(_poolByComptroller[comptrollerAddress].creator != address(0), \\\"PoolRegistry: Pool not registered\\\");\\n // solhint-disable-next-line reason-string\\n require(\\n _vTokens[comptrollerAddress][underlyingAddress] == address(0),\\n \\\"PoolRegistry: Market already added for asset comptroller combination\\\"\\n );\\n\\n comptroller.supportMarket(vToken);\\n comptroller.setCollateralFactor(vToken, input.collateralFactor, input.liquidationThreshold);\\n\\n uint256[] memory newSupplyCaps = new uint256[](1);\\n uint256[] memory newBorrowCaps = new uint256[](1);\\n VToken[] memory vTokens = new VToken[](1);\\n\\n newSupplyCaps[0] = input.supplyCap;\\n newBorrowCaps[0] = input.borrowCap;\\n vTokens[0] = vToken;\\n\\n comptroller.setMarketSupplyCaps(vTokens, newSupplyCaps);\\n comptroller.setMarketBorrowCaps(vTokens, newBorrowCaps);\\n\\n _vTokens[comptrollerAddress][underlyingAddress] = vTokenAddress;\\n _supportedPools[underlyingAddress].push(comptrollerAddress);\\n\\n uint256 amountToSupply = _transferIn(underlying, msg.sender, input.initialSupply);\\n underlying.forceApprove(vTokenAddress, 0);\\n underlying.forceApprove(vTokenAddress, amountToSupply);\\n vToken.mintBehalf(input.vTokenReceiver, amountToSupply);\\n\\n emit MarketAdded(comptrollerAddress, vTokenAddress);\\n }\\n\\n /**\\n * @notice Modify existing Venus pool name\\n * @param comptroller Pool's Comptroller\\n * @param name New pool name\\n */\\n function setPoolName(address comptroller, string calldata name) external {\\n _checkAccessAllowed(\\\"setPoolName(address,string)\\\");\\n _ensureValidName(name);\\n VenusPool storage pool = _poolByComptroller[comptroller];\\n string memory oldName = pool.name;\\n pool.name = name;\\n emit PoolNameSet(comptroller, oldName, name);\\n }\\n\\n /**\\n * @notice Update metadata of an existing pool\\n * @param comptroller Pool's Comptroller\\n * @param metadata_ New pool metadata\\n */\\n function updatePoolMetadata(address comptroller, VenusPoolMetaData calldata metadata_) external {\\n _checkAccessAllowed(\\\"updatePoolMetadata(address,VenusPoolMetaData)\\\");\\n VenusPoolMetaData memory oldMetadata = metadata[comptroller];\\n metadata[comptroller] = metadata_;\\n emit PoolMetadataUpdated(comptroller, oldMetadata, metadata_);\\n }\\n\\n /**\\n * @notice Returns arrays of all Venus pools' data\\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\\n * @return A list of all pools within PoolRegistry, with details for each pool\\n */\\n function getAllPools() external view override returns (VenusPool[] memory) {\\n uint256 numberOfPools_ = _numberOfPools; // storage load to save gas\\n VenusPool[] memory _pools = new VenusPool[](numberOfPools_);\\n for (uint256 i = 1; i <= numberOfPools_; ++i) {\\n address comptroller = _poolsByID[i];\\n _pools[i - 1] = (_poolByComptroller[comptroller]);\\n }\\n return _pools;\\n }\\n\\n /**\\n * @param comptroller The comptroller proxy address associated to the pool\\n * @return Returns Venus pool\\n */\\n function getPoolByComptroller(address comptroller) external view override returns (VenusPool memory) {\\n return _poolByComptroller[comptroller];\\n }\\n\\n /**\\n * @param comptroller comptroller of Venus pool\\n * @return Returns Metadata of Venus pool\\n */\\n function getVenusPoolMetadata(address comptroller) external view override returns (VenusPoolMetaData memory) {\\n return metadata[comptroller];\\n }\\n\\n function getVTokenForAsset(address comptroller, address asset) external view override returns (address) {\\n return _vTokens[comptroller][asset];\\n }\\n\\n function getPoolsSupportedByAsset(address asset) external view override returns (address[] memory) {\\n return _supportedPools[asset];\\n }\\n\\n /**\\n * @dev Adds a new Venus pool to the directory (without checking msg.sender).\\n * @param name The name of the pool\\n * @param comptroller The pool's Comptroller proxy contract address\\n * @return The index of the registered Venus pool\\n */\\n function _registerPool(string calldata name, address comptroller) internal returns (uint256) {\\n VenusPool storage storedPool = _poolByComptroller[comptroller];\\n\\n require(storedPool.creator == address(0), \\\"PoolRegistry: Pool already exists in the directory.\\\");\\n _ensureValidName(name);\\n\\n ++_numberOfPools;\\n uint256 numberOfPools_ = _numberOfPools; // cache on stack to save storage read gas\\n\\n VenusPool memory pool = VenusPool(name, msg.sender, comptroller, block.number, block.timestamp);\\n\\n _poolsByID[numberOfPools_] = comptroller;\\n _poolByComptroller[comptroller] = pool;\\n\\n emit PoolRegistered(comptroller, pool);\\n return numberOfPools_;\\n }\\n\\n function _transferIn(IERC20Upgradeable token, address from, uint256 amount) internal returns (uint256) {\\n uint256 balanceBefore = token.balanceOf(address(this));\\n token.safeTransferFrom(from, address(this), amount);\\n uint256 balanceAfter = token.balanceOf(address(this));\\n return balanceAfter - balanceBefore;\\n }\\n\\n function _ensureValidName(string calldata name) internal pure {\\n require(bytes(name).length <= MAX_POOL_NAME_LENGTH, \\\"Pool's name is too large\\\");\\n }\\n}\\n\",\"keccak256\":\"0xafbb871f7b4db3ef439d846baa5f18a136192f9b43ea695c81262a77b06c4b25\",\"license\":\"BSD-3-Clause\"},\"contracts/Pool/PoolRegistryInterface.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 /**\\n * @notice Struct for a Venus interest rate pool metadata.\\n */\\n struct VenusPoolMetaData {\\n string category;\\n string logoURL;\\n string description;\\n }\\n\\n /// @notice Get all pools in PoolRegistry\\n function getAllPools() external view returns (VenusPool[] memory);\\n\\n /// @notice Get a pool by comptroller address\\n function getPoolByComptroller(address comptroller) external view returns (VenusPool memory);\\n\\n /// @notice Get the address of the VToken contract in the Pool where the underlying token is the provided 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 /// @notice Get the metadata of a Pool by comptroller address\\n function getVenusPoolMetadata(address comptroller) external view returns (VenusPoolMetaData memory);\\n}\\n\",\"keccak256\":\"0x7b39cda3b372a686501ce3c2aad288c6af410148110318249d75d4516729c92c\",\"license\":\"BSD-3-Clause\"},\"contracts/Rewards/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\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 { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"../MaxLoopsLimitHelper.sol\\\";\\nimport { RewardsDistributorStorage } from \\\"./RewardsDistributorStorage.sol\\\";\\n\\n/**\\n * @title `RewardsDistributor`\\n * @author Venus\\n * @notice Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol.\\n * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward\\n * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool.\\n * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward\\n * token to be released each slot (block or second) for borrowers and suppliers, which is distributed based on a user\\u2019s percentage of the borrows or supplies\\n * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting\\n * their contributor reward token speed, which similarly allocates a fixed amount of reward token per slot (block or second).\\n *\\n * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed\\n * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized\\n * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\\n */\\ncontract RewardsDistributor is\\n ExponentialNoError,\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n MaxLoopsLimitHelper,\\n RewardsDistributorStorage,\\n TimeManagerV8\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice The initial REWARD TOKEN index for a market\\n uint224 public constant INITIAL_INDEX = 1e36;\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a supplier\\n event DistributedSupplierRewardToken(\\n VToken indexed vToken,\\n address indexed supplier,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenSupplyIndex\\n );\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a borrower\\n event DistributedBorrowerRewardToken(\\n VToken indexed vToken,\\n address indexed borrower,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenBorrowIndex\\n );\\n\\n /// @notice Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when REWARD TOKEN is granted by admin\\n event RewardTokenGranted(address indexed recipient, uint256 amount);\\n\\n /// @notice Emitted when a new REWARD TOKEN speed is set for a contributor\\n event ContributorRewardTokenSpeedUpdated(address indexed contributor, uint256 newSpeed);\\n\\n /// @notice Emitted when a market is initialized\\n event MarketInitialized(address indexed vToken);\\n\\n /// @notice Emitted when a reward token supply index is updated\\n event RewardTokenSupplyIndexUpdated(address indexed vToken);\\n\\n /// @notice Emitted when a reward token borrow index is updated\\n event RewardTokenBorrowIndexUpdated(address indexed vToken, Exp marketBorrowIndex);\\n\\n /// @notice Emitted when a reward for contributor is updated\\n event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued);\\n\\n /// @notice Emitted when a reward token last rewarding block for supply is updated\\n event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding block for borrow is updated\\n event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding timestamp for supply is updated\\n event SupplyLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\\n\\n /// @notice Emitted when a reward token last rewarding timestamp for borrow is updated\\n event BorrowLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\\n\\n modifier onlyComptroller() {\\n require(address(comptroller) == msg.sender, \\\"Only comptroller can call this function\\\");\\n _;\\n }\\n\\n /**\\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice RewardsDistributor initializer\\n * @dev Initializes the deployer to owner\\n * @param comptroller_ Comptroller to attach the reward distributor to\\n * @param rewardToken_ Reward token to distribute\\n * @param loopsLimit_ Maximum number of iterations for the loops in this contract\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(\\n Comptroller comptroller_,\\n IERC20Upgradeable rewardToken_,\\n uint256 loopsLimit_,\\n address accessControlManager_\\n ) external initializer {\\n comptroller = comptroller_;\\n rewardToken = rewardToken_;\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n\\n _setMaxLoopsLimit(loopsLimit_);\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken\\n * @param vToken The address of the vToken to be initialized\\n * @custom:event MarketInitialized emits on success\\n * @custom:access Only Comptroller\\n */\\n function initializeMarket(address vToken) external onlyComptroller {\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n isTimeBased\\n ? _initializeMarketTimestampBased(vToken, blockNumberOrTimestamp)\\n : _initializeMarketBlockBased(vToken, safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\"));\\n\\n emit MarketInitialized(vToken);\\n }\\n\\n /*** Reward Token Distribution ***/\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them\\n * Borrowers will begin to accrue after the first interaction with the protocol.\\n * @dev This function should only be called when the user has a borrow position in the market\\n * (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook)\\n * We avoid an external call to check if they are in the market to save gas because this function is called in many places\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function distributeBorrowerRewardToken(\\n address vToken,\\n address borrower,\\n Exp memory marketBorrowIndex\\n ) external onlyComptroller {\\n _distributeBorrowerRewardToken(vToken, borrower, marketBorrowIndex);\\n }\\n\\n function updateRewardTokenSupplyIndex(address vToken) external onlyComptroller {\\n _updateRewardTokenSupplyIndex(vToken);\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the recipient\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\\n * @param recipient The address of the recipient to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n */\\n function grantRewardToken(address recipient, uint256 amount) external onlyOwner {\\n uint256 amountLeft = _grantRewardToken(recipient, amount);\\n require(amountLeft == 0, \\\"insufficient rewardToken for grant\\\");\\n emit RewardTokenGranted(recipient, amount);\\n }\\n\\n function updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) external onlyComptroller {\\n _updateRewardTokenBorrowIndex(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN borrow and supply speeds for the specified markets\\n * @param vTokens The markets whose REWARD TOKEN speed to update\\n * @param supplySpeeds New supply-side REWARD TOKEN speed for the corresponding market\\n * @param borrowSpeeds New borrow-side REWARD TOKEN speed for the corresponding market\\n */\\n function setRewardTokenSpeeds(\\n VToken[] memory vTokens,\\n uint256[] memory supplySpeeds,\\n uint256[] memory borrowSpeeds\\n ) external {\\n _checkAccessAllowed(\\\"setRewardTokenSpeeds(address[],uint256[],uint256[])\\\");\\n uint256 numTokens = vTokens.length;\\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \\\"invalid setRewardTokenSpeeds\\\");\\n\\n for (uint256 i; i < numTokens; ++i) {\\n _setRewardTokenSpeed(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for the specified markets, used when contract is block based\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market\\n * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market\\n */\\n function setLastRewardingBlocks(\\n VToken[] calldata vTokens,\\n uint32[] calldata supplyLastRewardingBlocks,\\n uint32[] calldata borrowLastRewardingBlocks\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlocks(address[],uint32[],uint32[])\\\");\\n require(!isTimeBased, \\\"Block-based operation only\\\");\\n\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length,\\n \\\"RewardsDistributor::setLastRewardingBlocks invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlock(vTokens[i], supplyLastRewardingBlocks[i], borrowLastRewardingBlocks[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block timestamp for the specified markets, used when contract is time based\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlockTimestamps New supply-side REWARD TOKEN last rewarding block timestamp for the corresponding market\\n * @param borrowLastRewardingBlockTimestamps New borrow-side REWARD TOKEN last rewarding block timestamp for the corresponding market\\n */\\n function setLastRewardingBlockTimestamps(\\n VToken[] calldata vTokens,\\n uint256[] calldata supplyLastRewardingBlockTimestamps,\\n uint256[] calldata borrowLastRewardingBlockTimestamps\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlockTimestamps(address[],uint256[],uint256[])\\\");\\n require(isTimeBased, \\\"Time-based operation only\\\");\\n\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlockTimestamps.length &&\\n numTokens == borrowLastRewardingBlockTimestamps.length,\\n \\\"RewardsDistributor::setLastRewardingBlockTimestamps invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlockTimestamp(\\n vTokens[i],\\n supplyLastRewardingBlockTimestamps[i],\\n borrowLastRewardingBlockTimestamps[i]\\n );\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single contributor\\n * @param contributor The contributor whose REWARD TOKEN speed to update\\n * @param rewardTokenSpeed New REWARD TOKEN speed for contributor\\n */\\n function setContributorRewardTokenSpeed(address contributor, uint256 rewardTokenSpeed) external onlyOwner {\\n // note that REWARD TOKEN speed could be set to 0 to halt liquidity rewards for a contributor\\n updateContributorRewards(contributor);\\n if (rewardTokenSpeed == 0) {\\n // release storage\\n delete lastContributorBlock[contributor];\\n } else {\\n lastContributorBlock[contributor] = getBlockNumberOrTimestamp();\\n }\\n rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed;\\n\\n emit ContributorRewardTokenSpeedUpdated(contributor, rewardTokenSpeed);\\n }\\n\\n function distributeSupplierRewardToken(address vToken, address supplier) external onlyComptroller {\\n _distributeSupplierRewardToken(vToken, supplier);\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in all markets\\n * @param holder The address to claim REWARD TOKEN for\\n */\\n function claimRewardToken(address holder) external {\\n return claimRewardToken(holder, comptroller.getAllMarkets());\\n }\\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) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Calculate additional accrued REWARD TOKEN for a contributor since last accrual\\n * @param contributor The address to calculate contributor rewards for\\n */\\n function updateContributorRewards(address contributor) public {\\n uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, lastContributorBlock[contributor]);\\n if (deltaBlocksOrTimestamp > 0 && rewardTokenSpeed > 0) {\\n uint256 newAccrued = mul_(deltaBlocksOrTimestamp, rewardTokenSpeed);\\n uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued);\\n\\n rewardTokenAccrued[contributor] = contributorAccrued;\\n lastContributorBlock[contributor] = blockNumberOrTimestamp;\\n\\n emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]);\\n }\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in the specified markets\\n * @param holder The address to claim REWARD TOKEN for\\n * @param vTokens The list of markets to claim REWARD TOKEN in\\n */\\n function claimRewardToken(address holder, VToken[] memory vTokens) public {\\n uint256 vTokensCount = vTokens.length;\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n VToken vToken = vTokens[i];\\n require(comptroller.isMarketListed(vToken), \\\"market must be listed\\\");\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n _distributeBorrowerRewardToken(address(vToken), holder, borrowIndex);\\n _updateRewardTokenSupplyIndex(address(vToken));\\n _distributeSupplierRewardToken(address(vToken), holder);\\n }\\n rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for a single market.\\n * @param vToken market's whose reward token last rewarding block to be updated\\n * @param supplyLastRewardingBlock New supply-side REWARD TOKEN last rewarding block for market\\n * @param borrowLastRewardingBlock New borrow-side REWARD TOKEN last rewarding block for market\\n */\\n function _setLastRewardingBlock(\\n VToken vToken,\\n uint32 supplyLastRewardingBlock,\\n uint32 borrowLastRewardingBlock\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockNumber = getBlockNumberOrTimestamp();\\n\\n require(supplyLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n require(borrowLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n\\n uint32 currentSupplyLastRewardingBlock = rewardTokenSupplyState[address(vToken)].lastRewardingBlock;\\n uint32 currentBorrowLastRewardingBlock = rewardTokenBorrowState[address(vToken)].lastRewardingBlock;\\n\\n require(\\n currentSupplyLastRewardingBlock == 0 || currentSupplyLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlock == 0 || currentBorrowLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlock != supplyLastRewardingBlock) {\\n rewardTokenSupplyState[address(vToken)].lastRewardingBlock = supplyLastRewardingBlock;\\n emit SupplyLastRewardingBlockUpdated(address(vToken), supplyLastRewardingBlock);\\n }\\n\\n if (currentBorrowLastRewardingBlock != borrowLastRewardingBlock) {\\n rewardTokenBorrowState[address(vToken)].lastRewardingBlock = borrowLastRewardingBlock;\\n emit BorrowLastRewardingBlockUpdated(address(vToken), borrowLastRewardingBlock);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding timestamp for a single market.\\n * @param vToken market's whose reward token last rewarding timestamp to be updated\\n * @param supplyLastRewardingBlockTimestamp New supply-side REWARD TOKEN last rewarding timestamp for market\\n * @param borrowLastRewardingBlockTimestamp New borrow-side REWARD TOKEN last rewarding timestamp for market\\n */\\n function _setLastRewardingBlockTimestamp(\\n VToken vToken,\\n uint256 supplyLastRewardingBlockTimestamp,\\n uint256 borrowLastRewardingBlockTimestamp\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockTimestamp = getBlockNumberOrTimestamp();\\n\\n require(\\n supplyLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"setting last rewarding timestamp in the past is not allowed\\\"\\n );\\n require(\\n borrowLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"setting last rewarding timestamp in the past is not allowed\\\"\\n );\\n\\n uint256 currentSupplyLastRewardingBlockTimestamp = rewardTokenSupplyStateTimeBased[address(vToken)]\\n .lastRewardingTimestamp;\\n uint256 currentBorrowLastRewardingBlockTimestamp = rewardTokenBorrowStateTimeBased[address(vToken)]\\n .lastRewardingTimestamp;\\n\\n require(\\n currentSupplyLastRewardingBlockTimestamp == 0 || currentSupplyLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlockTimestamp == 0 || currentBorrowLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlockTimestamp != supplyLastRewardingBlockTimestamp) {\\n rewardTokenSupplyStateTimeBased[address(vToken)].lastRewardingTimestamp = supplyLastRewardingBlockTimestamp;\\n emit SupplyLastRewardingBlockTimestampUpdated(address(vToken), supplyLastRewardingBlockTimestamp);\\n }\\n\\n if (currentBorrowLastRewardingBlockTimestamp != borrowLastRewardingBlockTimestamp) {\\n rewardTokenBorrowStateTimeBased[address(vToken)].lastRewardingTimestamp = borrowLastRewardingBlockTimestamp;\\n emit BorrowLastRewardingBlockTimestampUpdated(address(vToken), borrowLastRewardingBlockTimestamp);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single market.\\n * @param vToken market's whose reward token rate to be updated\\n * @param supplySpeed New supply-side REWARD TOKEN speed for market\\n * @param borrowSpeed New borrow-side REWARD TOKEN speed for market\\n */\\n function _setRewardTokenSpeed(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n if (rewardTokenSupplySpeeds[address(vToken)] != supplySpeed) {\\n // Supply speed updated so let's update supply state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n _updateRewardTokenSupplyIndex(address(vToken));\\n\\n // Update speed and emit event\\n rewardTokenSupplySpeeds[address(vToken)] = supplySpeed;\\n emit RewardTokenSupplySpeedUpdated(vToken, supplySpeed);\\n }\\n\\n if (rewardTokenBorrowSpeeds[address(vToken)] != borrowSpeed) {\\n // Borrow speed updated so let's update borrow state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n\\n // Update speed and emit event\\n rewardTokenBorrowSpeeds[address(vToken)] = borrowSpeed;\\n emit RewardTokenBorrowSpeedUpdated(vToken, borrowSpeed);\\n }\\n }\\n\\n /**\\n * @notice Calculate REWARD TOKEN 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 REWARD TOKEN to\\n */\\n function _distributeSupplierRewardToken(address vToken, address supplier) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\\n\\n uint256 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\\n uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier];\\n\\n // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenSupplierIndex[vToken][supplier] = supplyIndex;\\n\\n if (supplierIndex == 0 && supplyIndex >= INITIAL_INDEX) {\\n // Covers the case where users supplied tokens before the market's supply state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when supplier rewards were first\\n // set for the market.\\n supplierIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per vToken accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\\n\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerVToken\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n\\n uint256 supplierAccrued = add_(rewardTokenAccrued[supplier], supplierDelta);\\n rewardTokenAccrued[supplier] = supplierAccrued;\\n\\n emit DistributedSupplierRewardToken(VToken(vToken), supplier, supplierDelta, supplierAccrued, supplyIndex);\\n }\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them.\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function _distributeBorrowerRewardToken(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\\n\\n uint256 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\\n uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower];\\n\\n // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenBorrowerIndex[vToken][borrower] = borrowIndex;\\n\\n if (borrowerIndex == 0 && borrowIndex >= INITIAL_INDEX) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when borrower rewards were first\\n // set for the market.\\n borrowerIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per borrowed unit accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\\n\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerBorrowedUnit\\n if (borrowerAmount != 0) {\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n\\n uint256 borrowerAccrued = add_(rewardTokenAccrued[borrower], borrowerDelta);\\n rewardTokenAccrued[borrower] = borrowerAccrued;\\n\\n emit DistributedBorrowerRewardToken(VToken(vToken), borrower, borrowerDelta, borrowerAccrued, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the user.\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all.\\n * @param user The address of the user to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n * @return The amount of REWARD TOKEN which was NOT transferred to the user\\n */\\n function _grantRewardToken(address user, uint256 amount) internal returns (uint256) {\\n uint256 rewardTokenRemaining = rewardToken.balanceOf(address(this));\\n if (amount > 0 && amount <= rewardTokenRemaining) {\\n rewardToken.safeTransfer(user, amount);\\n return 0;\\n }\\n return amount;\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the supply index\\n * @param vToken The market whose supply index to update\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenSupplyIndex(address vToken) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\\n\\n uint256 supplySpeed = rewardTokenSupplySpeeds[vToken];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (!isTimeBased) {\\n safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\");\\n }\\n\\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\\n ? supplyStateTimeBased.lastRewardingTimestamp\\n : uint256(supplyState.lastRewardingBlock);\\n\\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(\\n blockNumberOrTimestamp,\\n (isTimeBased ? supplyStateTimeBased.timestamp : uint256(supplyState.block))\\n );\\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, supplySpeed);\\n Double memory ratio = supplyTokens > 0\\n ? fraction(accruedSinceUpdate, supplyTokens)\\n : Double({ mantissa: 0 });\\n uint224 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\\n uint224 index = safe224(\\n add_(Double({ mantissa: supplyIndex }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n\\n if (isTimeBased) {\\n supplyStateTimeBased.index = index;\\n supplyStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n supplyState.index = index;\\n supplyState.block = uint32(blockNumberOrTimestamp);\\n }\\n } else if (deltaBlocksOrTimestamp > 0) {\\n isTimeBased ? supplyStateTimeBased.timestamp = blockNumberOrTimestamp : supplyState.block = uint32(\\n blockNumberOrTimestamp\\n );\\n }\\n\\n emit RewardTokenSupplyIndexUpdated(vToken);\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the borrow index\\n * @param vToken The market whose borrow index to update\\n * @param marketBorrowIndex The current global borrow index of vToken\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\\n\\n uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (!isTimeBased) {\\n safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\");\\n }\\n\\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\\n ? borrowStateTimeBased.lastRewardingTimestamp\\n : uint256(borrowState.lastRewardingBlock);\\n\\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(\\n blockNumberOrTimestamp,\\n (isTimeBased ? borrowStateTimeBased.timestamp : uint256(borrowState.block))\\n );\\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, borrowSpeed);\\n Double memory ratio = borrowAmount > 0\\n ? fraction(accruedSinceUpdate, borrowAmount)\\n : Double({ mantissa: 0 });\\n uint224 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\\n uint224 index = safe224(\\n add_(Double({ mantissa: borrowIndex }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n\\n if (isTimeBased) {\\n borrowStateTimeBased.index = index;\\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n borrowState.index = index;\\n borrowState.block = uint32(blockNumberOrTimestamp);\\n }\\n } else if (deltaBlocksOrTimestamp > 0) {\\n if (isTimeBased) {\\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n borrowState.block = uint32(blockNumberOrTimestamp);\\n }\\n }\\n\\n emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken called when contract is block-based\\n * @param vToken The address of the vToken to be initialized\\n * @param blockNumber current block number\\n */\\n function _initializeMarketBlockBased(address vToken, uint32 blockNumber) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n RewardToken storage borrowState = rewardTokenBorrowState[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 = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block numbers\\n */\\n supplyState.block = borrowState.block = blockNumber;\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken called when contract is time-based\\n * @param vToken The address of the vToken to be initialized\\n * @param blockTimestamp current block timestamp\\n */\\n function _initializeMarketTimestampBased(address vToken, uint256 blockTimestamp) internal {\\n TimeBasedRewardToken storage supplyState = rewardTokenSupplyStateTimeBased[vToken];\\n TimeBasedRewardToken storage borrowState = rewardTokenBorrowStateTimeBased[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 = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block timestamp\\n */\\n supplyState.timestamp = borrowState.timestamp = blockTimestamp;\\n }\\n}\\n\",\"keccak256\":\"0x3cc824e59c923cfe25c4f1a875959b7e9410cde8e73cd405de13f301298c697f\",\"license\":\"BSD-3-Clause\"},\"contracts/Rewards/RewardsDistributorStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\n\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\n\\n/**\\n * @title RewardsDistributorStorage\\n * @author Venus\\n * @dev Storage for RewardsDistributor\\n */\\ncontract RewardsDistributorStorage {\\n struct RewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number the index was last updated at\\n uint32 block;\\n // The block number at which to stop rewards\\n uint32 lastRewardingBlock;\\n }\\n\\n struct TimeBasedRewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block timestamp the index was last updated at\\n uint256 timestamp;\\n // The block timestamp at which to stop rewards\\n uint256 lastRewardingTimestamp;\\n }\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => RewardToken) public rewardTokenSupplyState;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex;\\n\\n /// @notice The REWARD TOKEN accrued but not yet transferred to each user\\n mapping(address => uint256) public rewardTokenAccrued;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding borrow market per slot (block or second)\\n mapping(address => uint256) public rewardTokenBorrowSpeeds;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding supply market per slot (block or second)\\n mapping(address => uint256) public rewardTokenSupplySpeeds;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => RewardToken) public rewardTokenBorrowState;\\n\\n /// @notice The portion of REWARD TOKEN that each contributor receives per slot (block or second)\\n mapping(address => uint256) public rewardTokenContributorSpeeds;\\n\\n /// @notice Last slot (block or second) at which a contributor's REWARD TOKEN rewards have been allocated\\n mapping(address => uint256) public lastContributorBlock;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex;\\n\\n Comptroller internal comptroller;\\n\\n IERC20Upgradeable public rewardToken;\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => TimeBasedRewardToken) public rewardTokenSupplyStateTimeBased;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => TimeBasedRewardToken) public rewardTokenBorrowStateTimeBased;\\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[37] private __gap;\\n}\\n\",\"keccak256\":\"0x70e5015a78a2acf95277949c8b4796e10b9ac194130be006d5e5217e158070c0\",\"license\":\"BSD-3-Clause\"},\"contracts/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\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 { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"@venusprotocol/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\\\";\\n\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { ComptrollerInterface, ComptrollerViewInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"./ErrorReporter.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title VToken\\n * @author Venus\\n * @notice Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview,\\n * each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of\\n * the pool. The main actions a user regularly interacts with in a market are:\\n\\n- mint/redeem of vTokens;\\n- transfer of vTokens;\\n- borrow/repay a loan on an underlying asset;\\n- liquidate a borrow or liquidate/heal an account.\\n\\n * A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`.\\n * The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted\\n * `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken`\\n * as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that\\n * a user may borrow up to a portion of their collateral determined by the market\\u2019s collateral factor. However, if their borrowed amount exceeds an amount\\n * calculated using the market\\u2019s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also\\n * pay off interest accrued on the borrow.\\n * \\n * The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller`\\n * and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a\\n * total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`.\\n * Both functions settle all of an account\\u2019s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of\\n * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\\n */\\ncontract VToken is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n VTokenInterface,\\n ExponentialNoError,\\n TokenErrorReporter,\\n TimeManagerV8\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5%\\n\\n // Maximum fraction of interest that can be set aside for reserves\\n uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18;\\n\\n // Maximum borrow rate that can ever be applied per slot(block or second)\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n uint256 internal immutable MAX_BORROW_RATE_MANTISSA;\\n\\n /**\\n * Reentrancy Guard **\\n */\\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 * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @param maxBorrowRateMantissa_ The maximum value of borrowing rate mantissa\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(\\n bool timeBased_,\\n uint256 blocksPerYear_,\\n uint256 maxBorrowRateMantissa_\\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n require(maxBorrowRateMantissa_ <= 1e18, \\\"Max borrow rate must be <= 1e18\\\");\\n\\n MAX_BORROW_RATE_MANTISSA = maxBorrowRateMantissa_;\\n _disableInitializers();\\n }\\n\\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_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n */\\n function initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) external initializer {\\n ensureNonzeroAddress(admin_);\\n\\n // Initialize the market\\n _initialize(\\n underlying_,\\n comptroller_,\\n interestRateModel_,\\n initialExchangeRateMantissa_,\\n name_,\\n symbol_,\\n decimals_,\\n admin_,\\n accessControlManager_,\\n riskManagement,\\n reserveFactorMantissa_\\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 * @return success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, msg.sender, dst, amount);\\n return true;\\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 success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, src, dst, amount);\\n return true;\\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 (uint256.max means infinite)\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Increase approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param addedValue The number of additional tokens spender can transfer\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function increaseAllowance(address spender, uint256 addedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 newAllowance = transferAllowances[src][spender];\\n newAllowance += addedValue;\\n transferAllowances[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n return true;\\n }\\n\\n /**\\n * @notice Decreases approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param subtractedValue The number of tokens to remove from total approval\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 currentAllowance = transferAllowances[src][spender];\\n require(currentAllowance >= subtractedValue, \\\"decreased allowance below zero\\\");\\n unchecked {\\n currentAllowance -= subtractedValue;\\n }\\n\\n transferAllowances[src][spender] = currentAllowance;\\n\\n emit Approval(src, spender, currentAllowance);\\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 amount The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint256) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return totalBorrows The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\\n accrueInterest();\\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 borrowBalance The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n return _borrowBalanceStored(account);\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function mint(uint256 mintAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _mintFresh(msg.sender, msg.sender, mintAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param minter User whom the supply will be attributed to\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when minter address is zero\\n */\\n function mintBehalf(address minter, uint256 mintAmount) external override nonReentrant returns (uint256) {\\n ensureNonzeroAddress(minter);\\n\\n accrueInterest();\\n\\n _mintFresh(msg.sender, minter, mintAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function redeem(uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _redeemFresh(msg.sender, msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function redeemBehalf(address redeemer, uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n _ensureSenderIsDelegateOf(redeemer);\\n\\n accrueInterest();\\n\\n _redeemFresh(redeemer, msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\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 receive from redeeming vTokens\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n */\\n function redeemUnderlying(uint256 redeemAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _redeemFresh(msg.sender, msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function redeemUnderlyingBehalf(\\n address redeemer,\\n uint256 redeemAmount\\n ) external override nonReentrant returns (uint256) {\\n _ensureSenderIsDelegateOf(redeemer);\\n\\n accrueInterest();\\n\\n _redeemFresh(redeemer, msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function borrow(uint256 borrowAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _borrowFresh(msg.sender, msg.sender, borrowAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error DelegateNotApproved is thrown if caller is not approved delegate\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function borrowBehalf(address borrower, uint256 borrowAmount) external override returns (uint256) {\\n _ensureSenderIsDelegateOf(borrower);\\n accrueInterest();\\n\\n _borrowFresh(borrower, msg.sender, borrowAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrow(uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n return NO_ERROR;\\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, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _repayBorrowFresh(msg.sender, borrower, repayAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Not restricted\\n */\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external override returns (uint256) {\\n _liquidateBorrow(msg.sender, borrower, repayAmount, vTokenCollateral, false);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice sets protocol share accumulated from liquidations\\n * @dev must be equal or less than liquidation incentive - 1\\n * @param newProtocolSeizeShareMantissa_ new protocol share mantissa\\n * @custom:event Emits NewProtocolSeizeShare event on success\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error ProtocolSeizeShareTooBig is thrown when the new seize share is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa_) external {\\n _checkAccessAllowed(\\\"setProtocolSeizeShare(uint256)\\\");\\n uint256 liquidationIncentive = ComptrollerViewInterface(address(comptroller)).liquidationIncentiveMantissa();\\n if (newProtocolSeizeShareMantissa_ + MANTISSA_ONE > liquidationIncentive) {\\n revert ProtocolSeizeShareTooBig();\\n }\\n\\n uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\\n protocolSeizeShareMantissa = newProtocolSeizeShareMantissa_;\\n emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa_);\\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 * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n * @custom:event Emits NewReserveFactor event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant {\\n _checkAccessAllowed(\\\"setReserveFactor(uint256)\\\");\\n\\n accrueInterest();\\n _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to the protocol reserve contract\\n * @dev Gracefully return if reserves already reduced in accrueInterest\\n * @param reduceAmount Amount of reduction to reserves\\n * @custom:event Emits ReservesReduced event; may emit AccrueInterest\\n * @custom:error ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash\\n * @custom:error ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\\n * @custom:access Not restricted\\n */\\n function reduceReserves(uint256 reduceAmount) external override nonReentrant {\\n accrueInterest();\\n if (reduceReservesBlockNumber == getBlockNumberOrTimestamp()) return;\\n _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice The sender adds to reserves.\\n * @param addAmount The amount of underlying token to add as reserves\\n * @custom:event Emits ReservesAdded event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function addReserves(uint256 addAmount) external override nonReentrant {\\n accrueInterest();\\n _addReservesFresh(addAmount);\\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 * @custom:event Emits NewMarketInterestRateModel event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external override {\\n _checkAccessAllowed(\\\"setInterestRateModel(address)\\\");\\n\\n accrueInterest();\\n _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially\\n * \\\"forgiving\\\" the borrower. Healing is a situation that should rarely happen. However, some pools\\n * may list risky assets or be configured improperly \\u2013 we want to still handle such cases gracefully.\\n * We assume that Comptroller does the seizing, so this function is only available to Comptroller.\\n * @dev This function does not call any Comptroller hooks (like \\\"healAllowed\\\"), because we assume\\n * the Comptroller does all the necessary checks before calling this function.\\n * @param payer account who repays the debt\\n * @param borrower account to heal\\n * @param repayAmount amount to repay\\n * @custom:event Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\\n * @custom:error HealBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:access Only Comptroller\\n */\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external override nonReentrant {\\n if (repayAmount != 0) {\\n comptroller.preRepayHook(address(this), borrower);\\n }\\n\\n if (msg.sender != address(comptroller)) {\\n revert HealBorrowUnauthorized();\\n }\\n\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 totalBorrowsNew = totalBorrows;\\n\\n uint256 actualRepayAmount;\\n if (repayAmount != 0) {\\n // _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // We violate checks-effects-interactions here to account for tokens that take transfer fees\\n actualRepayAmount = _doTransferIn(payer, repayAmount);\\n totalBorrowsNew = totalBorrowsNew - actualRepayAmount;\\n emit RepayBorrow(\\n payer,\\n borrower,\\n actualRepayAmount,\\n accountBorrowsPrev - actualRepayAmount,\\n totalBorrowsNew\\n );\\n }\\n\\n // The transaction will fail if trying to repay too much\\n uint256 badDebtDelta = accountBorrowsPrev - actualRepayAmount;\\n if (badDebtDelta != 0) {\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld + badDebtDelta;\\n totalBorrowsNew = totalBorrowsNew - badDebtDelta;\\n badDebt = badDebtNew;\\n\\n // We treat healing as \\\"repayment\\\", where vToken is the payer\\n emit RepayBorrow(address(this), borrower, badDebtDelta, 0, totalBorrowsNew);\\n emit BadDebtIncreased(borrower, badDebtDelta, badDebtOld, badDebtNew);\\n }\\n\\n accountBorrows[borrower].principal = 0;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n emit HealBorrow(payer, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice The extended version of liquidations, callable only by Comptroller. May skip\\n * the close factor check. The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Only Comptroller\\n */\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) external override {\\n if (msg.sender != address(comptroller)) {\\n revert ForceLiquidateBorrowUnauthorized();\\n }\\n _liquidateBorrow(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\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 * @custom:event Emits Transfer, ReservesAdded events\\n * @custom:error LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:access Not restricted\\n */\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external override nonReentrant {\\n _seize(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Updates bad debt\\n * @dev Called only when bad debt is recovered from auction. Updates internal cash balance.\\n * @param recoveredAmount_ The amount of bad debt recovered\\n * @custom:event Emits BadDebtRecovered event\\n * @custom:access Only Shortfall contract\\n */\\n function badDebtRecovered(uint256 recoveredAmount_) external {\\n require(msg.sender == shortfall, \\\"only shortfall contract can update bad debt\\\");\\n require(recoveredAmount_ <= badDebt, \\\"more than bad debt recovered from auction\\\");\\n\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld - recoveredAmount_;\\n badDebt = badDebtNew;\\n internalCash += recoveredAmount_;\\n\\n emit BadDebtRecovered(badDebtOld, badDebtNew);\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protocolShareReserve_ The address of the protocol share reserve contract\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n * @custom:access Only Governance\\n */\\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\\n _setProtocolShareReserve(protocolShareReserve_);\\n }\\n\\n /**\\n * @notice Sets shortfall contract address\\n * @param shortfall_ The address of the shortfall contract\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:access Only Governance\\n */\\n function setShortfallContract(address shortfall_) external onlyOwner {\\n _setShortfallContract(shortfall_);\\n }\\n\\n /**\\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\\n * @param token The address of the ERC-20 token to sweep\\n * @custom:access Only Governance\\n */\\n function sweepToken(IERC20Upgradeable token) external override {\\n require(msg.sender == owner(), \\\"VToken::sweepToken: only admin can sweep tokens\\\");\\n require(address(token) != underlying, \\\"VToken::sweepToken: can not sweep underlying token\\\");\\n uint256 balance = token.balanceOf(address(this));\\n token.safeTransfer(owner(), balance);\\n\\n emit SweepToken(address(token));\\n }\\n\\n /**\\n * @notice Sync internalCash with the actual underlying token balance\\n * @dev Used for one-time migration after upgrade to initialize internalCash\\n * @custom:event Emits CashSynced\\n * @custom:access Controlled by AccessControlManager\\n */\\n function syncCash() external override nonReentrant {\\n _checkAccessAllowed(\\\"syncCash()\\\");\\n uint256 oldInternalCash = internalCash;\\n uint256 actualCash = IERC20Upgradeable(underlying).balanceOf(address(this));\\n internalCash = actualCash;\\n emit CashSynced(oldInternalCash, actualCash);\\n }\\n\\n /**\\n * @notice A public function to set new threshold of slot(block or second) difference after which funds will be sent to the protocol share reserve\\n * @param _newReduceReservesBlockOrTimestampDelta slot(block or second) difference value\\n * @custom:access Only Governance\\n */\\n function setReduceReservesBlockDelta(uint256 _newReduceReservesBlockOrTimestampDelta) external {\\n _checkAccessAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n require(_newReduceReservesBlockOrTimestampDelta > 0, \\\"Invalid Input\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, _newReduceReservesBlockOrTimestampDelta);\\n reduceReservesBlockDelta = _newReduceReservesBlockOrTimestampDelta;\\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 amount 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 amount 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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return vTokenBalance User's balance of vTokens\\n * @return borrowBalance Amount owed in terms of underlying\\n * @return exchangeRate Stored exchange rate\\n */\\n function getAccountSnapshot(\\n address account\\n )\\n external\\n view\\n override\\n returns (uint256 error, uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRate)\\n {\\n return (NO_ERROR, accountTokens[account], _borrowBalanceStored(account), _exchangeRateStored());\\n }\\n\\n /**\\n * @notice Get the internally tracked cash balance of this vToken in the underlying asset\\n * @return cash The quantity of underlying asset tracked internally by this contract\\n */\\n function getCash() external view override returns (uint256) {\\n return _getCashPrior();\\n }\\n\\n /**\\n * @notice Returns the current per slot(block or second) borrow interest rate for this vToken\\n * @return rate The borrow interest rate per slot(block or second), scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint256) {\\n return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt);\\n }\\n\\n /**\\n * @notice Returns the current per-slot(block or second) supply interest rate for this v\\n * @return rate The supply interest rate per slot(block or second), scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint256) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPrior(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa,\\n badDebt\\n );\\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 borrowBalance The calculated balance\\n */\\n function borrowBalanceStored(address account) external view override returns (uint256) {\\n return _borrowBalanceStored(account);\\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 exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() external view override returns (uint256) {\\n return _exchangeRateStored();\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\\n accrueInterest();\\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 slot(block or second)\\n * up to the current slot(block or second) and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentSlot - reduceReservesBlockNumber >= slotDelta\\n * @return Always NO_ERROR\\n * @custom:event Emits AccrueInterest event on success\\n * @custom:access Not restricted\\n */\\n function accrueInterest() public virtual override returns (uint256) {\\n /* Remember the initial block number or timestamp */\\n uint256 currentSlotNumber = getBlockNumberOrTimestamp();\\n uint256 accrualSlotNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualSlotNumberPrior == currentSlotNumber) {\\n return NO_ERROR;\\n }\\n\\n /* Read the previous values out of storage */\\n uint256 cashPrior = _getCashPrior();\\n uint256 borrowsPrior = totalBorrows;\\n uint256 reservesPrior = totalReserves;\\n uint256 borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt);\\n require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of slots elapsed since the last accrual */\\n uint256 slotDelta = currentSlotNumber - accrualSlotNumberPrior;\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * slotDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), slotDelta);\\n uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\\n uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;\\n uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentSlotNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n if (currentSlotNumber - reduceReservesBlockNumber >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentSlotNumber;\\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 NO_ERROR;\\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 or timestamp\\n * @param payer The address of the account which is sending the assets for supply\\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 */\\n function _mintFresh(address payer, address minter, uint256 mintAmount) internal {\\n /* Fail if mint not allowed */\\n comptroller.preMintHook(address(this), minter, mintAmount);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert MintFreshnessCheck();\\n }\\n\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\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 * `_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 uint256 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 uint256 mintTokens = div_(actualMintAmount, exchangeRate);\\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 * And write them into storage\\n */\\n totalSupply = totalSupply + mintTokens;\\n uint256 balanceAfter = accountTokens[minter] + mintTokens;\\n accountTokens[minter] = balanceAfter;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, actualMintAmount, mintTokens, balanceAfter);\\n emit Transfer(address(0), minter, mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, actualMintAmount, mintTokens);\\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 Comptroller.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current slot(block or second)\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the underlying 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 */\\n function _redeemFresh(address redeemer, address receiver, uint256 redeemTokensIn, uint256 redeemAmountIn) internal {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert RedeemFreshnessCheck();\\n }\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n\\n uint256 redeemTokens;\\n uint256 redeemAmount;\\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 */\\n redeemTokens = redeemTokensIn;\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n */\\n redeemTokens = div_(redeemAmountIn, exchangeRate);\\n\\n uint256 _redeemAmount = mul_(redeemTokens, exchangeRate);\\n if (_redeemAmount != 0 && _redeemAmount != redeemAmountIn) redeemTokens++; // round up\\n }\\n\\n // redeemAmount = exchangeRate * redeemTokens\\n redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokens);\\n\\n // Revert if amount is zero\\n if (redeemAmount == 0) {\\n revert(\\\"redeemAmount is zero\\\");\\n }\\n\\n /* Fail if redeem not allowed */\\n comptroller.preRedeemHook(address(this), redeemer, redeemTokens);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (_getCashPrior() - totalReserves < redeemAmount) {\\n revert RedeemTransferOutNotPossible();\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\\n */\\n totalSupply = totalSupply - redeemTokens;\\n uint256 balanceAfter = accountTokens[redeemer] - redeemTokens;\\n accountTokens[redeemer] = balanceAfter;\\n\\n /*\\n * We invoke _doTransferOut for the receiver and the redeemAmount.\\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 _doTransferOut(receiver, redeemAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), redeemTokens);\\n emit Redeem(redeemer, redeemAmount, redeemTokens, balanceAfter);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, redeemAmount, redeemTokens);\\n }\\n\\n /**\\n * @notice Users or their delegates borrow assets from the protocol\\n * @param borrower User who borrows the assets\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param borrowAmount The amount of the underlying asset to borrow\\n */\\n function _borrowFresh(address borrower, address receiver, uint256 borrowAmount) internal {\\n /* Fail if borrow not allowed */\\n comptroller.preBorrowHook(address(this), borrower, borrowAmount);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert BorrowFreshnessCheck();\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (_getCashPrior() - totalReserves < borrowAmount) {\\n revert BorrowCashNotAvailable();\\n }\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowNew = accountBorrow + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;\\n uint256 totalBorrowsNew = totalBorrows + borrowAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\\n `*/\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /*\\n * We invoke _doTransferOut for the receiver and the borrowAmount.\\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, accountBorrowsNew, totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\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 underlying tokens being returned, or type(uint256).max for the full outstanding amount\\n * @return (uint) the actual repayment amount.\\n */\\n function _repayBorrowFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256) {\\n /* Fail if repayBorrow not allowed */\\n comptroller.preRepayHook(address(this), borrower);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert RepayBorrowFreshnessCheck();\\n }\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n\\n uint256 repayAmountFinal = repayAmount >= accountBorrowsPrev ? accountBorrowsPrev : 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 * 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 uint256 actualRepayAmount = _doTransferIn(payer, repayAmountFinal);\\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 uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\\n uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, actualRepayAmount, borrowIndex);\\n\\n return actualRepayAmount;\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal nonReentrant {\\n accrueInterest();\\n\\n uint256 error = vTokenCollateral.accrueInterest();\\n if (error != NO_ERROR) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n revert LiquidateAccrueCollateralInterestFailed(error);\\n }\\n\\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal {\\n /* Fail if liquidate not allowed */\\n comptroller.preLiquidateHook(\\n address(this),\\n address(vTokenCollateral),\\n borrower,\\n repayAmount,\\n skipLiquidityCheck\\n );\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert LiquidateFreshnessCheck();\\n }\\n\\n /* Verify vTokenCollateral market's slot(block or second) number equals current slot(block or second) number */\\n if (vTokenCollateral.accrualBlockNumber() != getBlockNumberOrTimestamp()) {\\n revert LiquidateCollateralFreshnessCheck();\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateLiquidatorIsBorrower();\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n revert LiquidateCloseAmountIsZero();\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n revert LiquidateCloseAmountIsUintMax();\\n }\\n\\n /* Fail if repayBorrow fails */\\n uint256 actualRepayAmount = _repayBorrowFresh(liquidator, borrower, repayAmount);\\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.liquidateCalculateSeizeTokens(\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n require(amountSeizeError == 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, call _seize internally to avoid re-entrancy, otherwise make an external call\\n if (address(vTokenCollateral) == address(this)) {\\n _seize(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\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\\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 * It's absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerContract The contract seizing the collateral (either borrowed vToken or Comptroller)\\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 */\\n function _seize(address seizerContract, address liquidator, address borrower, uint256 seizeTokens) internal {\\n /* Fail if seize not allowed */\\n comptroller.preSeizeHook(address(this), seizerContract, liquidator, borrower);\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateSeizeLiquidatorIsBorrower();\\n }\\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 uint256 liquidationIncentiveMantissa = ComptrollerViewInterface(address(comptroller))\\n .liquidationIncentiveMantissa();\\n uint256 numerator = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));\\n uint256 protocolSeizeTokens = div_(numerator, Exp({ mantissa: liquidationIncentiveMantissa }));\\n uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n uint256 protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the calculated values into storage */\\n totalSupply = totalSupply - protocolSeizeTokens;\\n accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\\n accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\\n\\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, protocolSeizeAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.LIQUIDATION\\n );\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\\n emit ProtocolSeize(borrower, protocolShareReserve, protocolSeizeAmount);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerContract, liquidator, borrower, seizeTokens);\\n }\\n\\n function _setComptroller(ComptrollerInterface newComptroller) internal {\\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\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n */\\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal {\\n // Verify market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert SetReserveFactorFreshCheck();\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > MAX_RESERVE_FACTOR_MANTISSA) {\\n revert SetReserveFactorBoundsCheck();\\n }\\n\\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\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 actualAddAmount The actual amount added, excluding the potential token fees\\n */\\n function _addReservesFresh(uint256 addAmount) internal returns (uint256) {\\n // totalReserves + actualAddAmount\\n uint256 totalReservesNew;\\n uint256 actualAddAmount;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert AddReservesFactorFreshCheck(actualAddAmount);\\n }\\n\\n actualAddAmount = _doTransferIn(msg.sender, addAmount);\\n totalReservesNew = totalReserves + actualAddAmount;\\n totalReserves = totalReservesNew;\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n return actualAddAmount;\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to the protocol reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n */\\n function _reduceReservesFresh(uint256 reduceAmount) internal {\\n if (reduceAmount == 0) {\\n return;\\n }\\n // totalReserves - reduceAmount\\n uint256 totalReservesNew;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert ReduceReservesFreshCheck();\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (_getCashPrior() < reduceAmount) {\\n revert ReduceReservesCashNotAvailable();\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n revert ReduceReservesCashValidation();\\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 // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, reduceAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit SpreadReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal {\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert SetInterestRateModelFreshCheck();\\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\\n /**\\n * Safe Token **\\n */\\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 returns (uint256) {\\n IERC20Upgradeable token = IERC20Upgradeable(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 * @param to Receiver of the underlying tokens\\n * @param amount Amount of underlying to transfer\\n */\\n function _doTransferOut(address to, uint256 amount) internal virtual {\\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\\n internalCash -= amount;\\n token.safeTransfer(to, amount);\\n }\\n\\n /**\\n * @notice Transfer `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 */\\n function _transferTokens(address spender, address src, address dst, uint256 tokens) internal {\\n /* Fail if transfer not allowed */\\n comptroller.preTransferHook(address(this), src, dst, tokens);\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n revert TransferNotAllowed();\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint256 startingAllowance;\\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 uint256 allowanceNew = startingAllowance - tokens;\\n uint256 srcTokensNew = accountTokens[src] - tokens;\\n uint256 dstTokensNew = accountTokens[dst] + tokens;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n\\n accountTokens[src] = srcTokensNew;\\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\\n /**\\n * @notice Initialize the 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_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n */\\n function _initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\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 _setComptroller(comptroller_);\\n\\n // Initialize slot(block or second) number and borrow index (slot(block or second) number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumberOrTimestamp();\\n borrowIndex = MANTISSA_ONE;\\n\\n // Set the interest rate model (depends on slot(block or second) number / borrow index)\\n _setInterestRateModelFresh(interestRateModel_);\\n\\n _setReserveFactorFresh(reserveFactorMantissa_);\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n _setShortfallContract(riskManagement.shortfall);\\n _setProtocolShareReserve(riskManagement.protocolShareReserve);\\n protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA;\\n\\n // Set underlying and sanity check it\\n underlying = underlying_;\\n IERC20Upgradeable(underlying).totalSupply();\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n _transferOwnership(admin_);\\n }\\n\\n function _setShortfallContract(address shortfall_) internal {\\n ensureNonzeroAddress(shortfall_);\\n address oldShortfall = shortfall;\\n shortfall = shortfall_;\\n emit NewShortfallContract(oldShortfall, shortfall_);\\n }\\n\\n function _setProtocolShareReserve(address payable protocolShareReserve_) internal {\\n ensureNonzeroAddress(protocolShareReserve_);\\n address oldProtocolShareReserve = address(protocolShareReserve);\\n protocolShareReserve = protocolShareReserve_;\\n emit NewProtocolShareReserve(oldProtocolShareReserve, address(protocolShareReserve_));\\n }\\n\\n function _ensureSenderIsDelegateOf(address user) internal view {\\n if (!ComptrollerViewInterface(address(comptroller)).approvedDelegates(user, msg.sender)) {\\n revert DelegateNotApproved();\\n }\\n }\\n\\n /**\\n * @notice Gets the internally tracked cash balance of this market\\n * @dev Returns the internalCash state variable, which is updated on transfers in/out\\n * @return The quantity of underlying tokens tracked internally by this contract\\n */\\n function _getCashPrior() internal view virtual returns (uint256) {\\n return internalCash;\\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 borrowBalance the calculated balance\\n */\\n function _borrowBalanceStored(address account) internal view returns (uint256) {\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot memory 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 0;\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;\\n\\n return principalTimesIndex / borrowSnapshot.interestIndex;\\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 exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function _exchangeRateStored() internal view virtual returns (uint256) {\\n uint256 _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return initialExchangeRateMantissa;\\n }\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply\\n */\\n uint256 totalCash = _getCashPrior();\\n uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;\\n uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply;\\n\\n return exchangeRate;\\n }\\n}\\n\",\"keccak256\":\"0x7267f5337062ad01a5011f7725a86cc2ad0351cca0aaceadc167341f168cdef2\",\"license\":\"BSD-3-Clause\"},\"contracts/VTokenInterfaces.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\\nimport { ComptrollerInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title VTokenStorage\\n * @author Venus\\n * @notice Storage layout used by the `VToken` contract\\n */\\n// solhint-disable-next-line max-states-count\\ncontract VTokenStorage {\\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 uint256 principal;\\n uint256 interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\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 Protocol share Reserve contract address\\n */\\n address payable public protocolShareReserve;\\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 InterestRateModel public interestRateModel;\\n\\n // Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n uint256 internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint256 public reserveFactorMantissa;\\n\\n /**\\n * @notice Slot(block or second) number that interest was last accrued at\\n */\\n uint256 public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint256 public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint256 public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint256 public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint256 public totalSupply;\\n\\n /**\\n * @notice Total bad debt of the market\\n */\\n uint256 public badDebt;\\n\\n // Official record of token balances for each account\\n mapping(address => uint256) internal accountTokens;\\n\\n // Approved token transfer amounts on behalf of others\\n mapping(address => mapping(address => uint256)) internal transferAllowances;\\n\\n // Mapping of account addresses to outstanding borrow balances\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint256 public protocolSeizeShareMantissa;\\n\\n /**\\n * @notice Storage of Shortfall contract address\\n */\\n address public shortfall;\\n\\n /**\\n * @notice delta slot (block or second) after which reserves will be reduced\\n */\\n uint256 public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last slot (block or second) number at which reserves were reduced\\n */\\n uint256 public reduceReservesBlockNumber;\\n\\n /**\\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\\n * @dev Updated via _doTransferIn(), _doTransferOut(), syncCash(), and badDebtRecovered(). Must be initialized via syncCash() 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[47] private __gap;\\n}\\n\\n/**\\n * @title VTokenInterface\\n * @author Venus\\n * @notice Interface implemented by the `VToken` contract\\n */\\nabstract contract VTokenInterface is VTokenStorage {\\n struct RiskManagementInit {\\n address shortfall;\\n address payable protocolShareReserve;\\n }\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address indexed minter, uint256 mintAmount, uint256 mintTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address indexed borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(\\n address indexed payer,\\n address indexed borrower,\\n uint256 repayAmount,\\n uint256 accountBorrows,\\n uint256 totalBorrows\\n );\\n\\n /**\\n * @notice Event emitted when bad debt is accumulated on a market\\n * @param borrower borrower to \\\"forgive\\\"\\n * @param badDebtDelta amount of new bad debt recorded\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtIncreased(address indexed borrower, uint256 badDebtDelta, uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when bad debt is recovered via an auction\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtRecovered(uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address indexed liquidator,\\n address indexed borrower,\\n uint256 repayAmount,\\n address indexed vTokenCollateral,\\n uint256 seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface indexed oldComptroller, ComptrollerInterface indexed newComptroller);\\n\\n /**\\n * @notice Event emitted when shortfall contract address is changed\\n */\\n event NewShortfallContract(address indexed oldShortfall, address indexed newShortfall);\\n\\n /**\\n * @notice Event emitted when protocol share reserve contract address is changed\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModel indexed oldInterestRateModel,\\n InterestRateModel indexed newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when protocol seize share is changed\\n */\\n event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address indexed benefactor, uint256 addAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the spread reserves are reduced\\n */\\n event SpreadReservesReduced(address indexed protocolShareReserve, uint256 reduceAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /**\\n * @notice Event emitted when healing the borrow\\n */\\n event HealBorrow(address indexed payer, address indexed borrower, uint256 repayAmount);\\n\\n /**\\n * @notice Event emitted when tokens are swept\\n */\\n event SweepToken(address indexed token);\\n\\n /**\\n * @notice Event emitted when reduce reserves slot (block or second) delta is changed\\n */\\n event NewReduceReservesBlockDelta(\\n uint256 oldReduceReservesBlockOrTimestampDelta,\\n uint256 newReduceReservesBlockOrTimestampDelta\\n );\\n\\n /**\\n * @notice Event emitted when liquidation reserves are reduced\\n */\\n event ProtocolSeize(address indexed from, address indexed to, uint256 amount);\\n\\n /**\\n * @notice Event emitted when internalCash is synced with actual token balance\\n */\\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\\n\\n /*** User Interface ***/\\n\\n function mint(uint256 mintAmount) external virtual returns (uint256);\\n\\n function mintBehalf(address minter, uint256 mintAllowed) external virtual returns (uint256);\\n\\n function redeem(uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemBehalf(address redeemer, uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);\\n\\n function redeemUnderlyingBehalf(address redeemer, uint256 redeemAmount) external virtual returns (uint256);\\n\\n function borrow(uint256 borrowAmount) external virtual returns (uint256);\\n\\n function borrowBehalf(address borrwwer, uint256 borrowAmount) external virtual returns (uint256);\\n\\n function repayBorrow(uint256 repayAmount) external virtual returns (uint256);\\n\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external virtual returns (uint256);\\n\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external virtual;\\n\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipCloseFactorCheck\\n ) external virtual;\\n\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external virtual;\\n\\n function transfer(address dst, uint256 amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint256 amount) external virtual returns (bool);\\n\\n function accrueInterest() external virtual returns (uint256);\\n\\n function sweepToken(IERC20Upgradeable token) external virtual;\\n\\n /*** Admin Functions ***/\\n\\n function setReserveFactor(uint256 newReserveFactorMantissa) external virtual;\\n\\n function reduceReserves(uint256 reduceAmount) external virtual;\\n\\n function exchangeRateCurrent() external virtual returns (uint256);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint256);\\n\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external virtual;\\n\\n function addReserves(uint256 addAmount) external virtual;\\n\\n function syncCash() external virtual;\\n\\n function totalBorrowsCurrent() external virtual returns (uint256);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint256);\\n\\n function approve(address spender, uint256 amount) external virtual returns (bool);\\n\\n function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool);\\n\\n function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint256);\\n\\n function balanceOf(address owner) external view virtual returns (uint256);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint256, uint256, uint256, uint256);\\n\\n function borrowRatePerBlock() external view virtual returns (uint256);\\n\\n function supplyRatePerBlock() external view virtual returns (uint256);\\n\\n function borrowBalanceStored(address account) external view virtual returns (uint256);\\n\\n function exchangeRateStored() external view virtual returns (uint256);\\n\\n function getCash() external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is a VToken contract (for inspection)\\n * @return Always true\\n */\\n function isVToken() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x155684e9cb12cdd8be63d2314c9452b68ee44ff98a00e0d65cd1fd7d0bdd4391\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\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\",\"keccak256\":\"0x54ab3a6f3bc87569ed12370f3470a1ec84cea9796d4d0ccf3d07dd4280c044aa\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/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 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\",\"keccak256\":\"0x93bdd5cfb100f0f9a1d446857e23c3633df6ab12c266333c978428edd96b1367\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x61010060405234801561001157600080fd5b50604051614176380380614176833981016040819052610030916100e9565b82828115801561003e575080155b1561005c576040516302723dfb60e21b815260040160405180910390fd5b81801561006857508015155b156100865760405163ae0fcab360e01b815260040160405180910390fd5b81151560a05281610097578061009d565b6301e133805b608052816100b4576100e160201b611d0c176100bf565b6100e560201b611d10175b6001600160401b031660c05250506001600160a01b031660e0525061013d9050565b4390565b4290565b6000806000606084860312156100fe57600080fd5b8351801515811461010e57600080fd5b6020850151604086015191945092506001600160a01b038116811461013257600080fd5b809150509250925092565b60805160a05160c05160e051613ff2610184600039600081816102e80152611d8201526000611ce00152600081816102b10152611f80015260006101dc0152613ff26000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c80637c51b642116100a2578063c7ad089511610071578063c7ad0895146102ac578063d26998e9146102e3578063d77ebf961461030a578063e0a67f111461032a578063e1d146fb1461034a57600080fd5b80637c51b6421461022c5780637c84e3b31461024c578063aa5dbd231461026c578063b31242391461028c57600080fd5b806347d86a81116100de57806347d86a811461019957806355dd9515146101ac5780636857249c146101d75780637a27db571461020c57600080fd5b80630d3ae318146101105780631f884fdf14610139578063345954dc146101595780633e3e399c14610179575b600080fd5b61012361011e366004612ff0565b610352565b604051610130919061335d565b60405180910390f35b61014c6101473660046133bb565b610626565b60405161013091906133fc565b61016c61016736600461345c565b6106ee565b6040516101309190613479565b61018c61018736600461345c565b610821565b60405161013091906134dd565b6101236101a7366004613567565b610b30565b6101bf6101ba3660046135a0565b610bb7565b6040516001600160a01b039091168152602001610130565b6101fe7f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610130565b61021f61021a366004613567565b610c37565b60405161013091906135eb565b61023f61023a3660046136c7565b610ee7565b6040516101309190613752565b61025f61025a36600461345c565b610fa0565b60405161013091906137a0565b61027f61027a36600461345c565b61110a565b60405161013091906137c0565b61029f61029a366004613567565b6118ca565b60405161013091906137cf565b6102d37f000000000000000000000000000000000000000000000000000000000000000081565b6040519015158152602001610130565b6101bf7f000000000000000000000000000000000000000000000000000000000000000081565b61031d610318366004613567565b611bb1565b60405161013091906137dd565b61033d610338366004613841565b611c24565b60405161013091906138da565b6101fe611cd9565b61035a612db7565b6040820151600061036a82611d14565b9050600061037782611c24565b60408681015190516328ebbe8b60e21b81526001600160a01b039182166004820152919250879160009183169063a3aefa2c90602401600060405180830381865afa1580156103ca573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526103f29190810190613962565b90506000876040015190506000604051806101a001604052808a6000015181526020018a602001516001600160a01b031681526020018a604001516001600160a01b031681526020018a6060015181526020018a608001518152602001846000015181526020018460200151815260200184604001518152602001836001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104cf9190613a16565b6001600160a01b03168152602001836001600160a01b031663e87554466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561051b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053f9190613a33565b8152602001836001600160a01b0316634ada90af6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610582573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105a69190613a33565b8152602001836001600160a01b031663db5c65de6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060d9190613a33565b8152602001959095525092955050505050505b92915050565b6060816000816001600160401b0381111561064357610643612f39565b60405190808252806020026020018201604052801561068857816020015b60408051808201909152600080825260208201528152602001906001900390816106615790505b50905060005b828110156106e5576106c08686838181106106ab576106ab613a4c565b905060200201602081019061025a919061345c565b8282815181106106d2576106d2613a4c565b602090810291909101015260010161068e565b50949350505050565b606060008290506000816001600160a01b031663d88ff1f46040518163ffffffff1660e01b8152600401600060405180830381865afa158015610735573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261075d9190810190613ae5565b80519091506000816001600160401b0381111561077c5761077c612f39565b6040519080825280602002602001820160405280156107b557816020015b6107a2612db7565b81526020019060019003908161079a5790505b50905060005b828110156108175760008482815181106107d7576107d7613a4c565b6020026020010151905060006107ed8983610352565b90508084848151811061080257610802613a4c565b602090810291909101015250506001016107bb565b5095945050505050565b60408051606080820183526000808352602083018190529282015290828161084882611d14565b90506000826001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561088a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ae9190613a16565b9050600082516001600160401b038111156108cb576108cb612f39565b60405190808252806020026020018201604052801561091057816020015b60408051808201909152600080825260208201528152602001906001900390816108e95790505b509050610940604051806060016040528060006001600160a01b0316815260200160008152602001606081525090565b6001600160a01b03881681526040810182905260005b8451811015610b1c57604080518082019091526000808252602082015285828151811061098557610985613a4c565b602002602001015181600001906001600160a01b031690816001600160a01b031681525050670de0b6b3a7640000856001600160a01b031663fc57d4df8885815181106109d4576109d4613a4c565b60200260200101516040518263ffffffff1660e01b8152600401610a0791906001600160a01b0391909116815260200190565b602060405180830381865afa158015610a24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a489190613a33565b878481518110610a5a57610a5a613a4c565b60200260200101516001600160a01b031663bbcac5576040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac39190613a33565b610acd9190613bab565b610ad79190613bc2565b60208201526040830151805182919084908110610af657610af6613a4c565b6020026020010181905250806020015188610b119190613be4565b975050600101610956565b506020810195909552509295945050505050565b610b38612db7565b604051637aee632d60e01b81526001600160a01b0383811660048301528491610baf91839190821690637aee632d90602401600060405180830381865afa158015610b87573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261011e9190810190613bf7565b949350505050565b60405163266e0a7f60e01b81526001600160a01b0383811660048301528281166024830152600091859182169063266e0a7f90604401602060405180830381865afa158015610c0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2e9190613a16565b95945050505050565b60606000610c4483611d14565b90506000836001600160a01b03166361252fd16040518163ffffffff1660e01b8152600401600060405180830381865afa158015610c86573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cae9190810190613c2b565b9050600081516001600160401b03811115610ccb57610ccb612f39565b604051908082528060200260200182016040528015610d1c57816020015b6040805160808101825260008082526020808301829052928201526060808201528252600019909201910181610ce95790505b50905060005b8251811015610817576040805160808101825260008082526020820181905291810191909152606080820152838281518110610d6057610d60613a4c565b60209081029190910101516001600160a01b031681528351849083908110610d8a57610d8a613a4c565b60200260200101516001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dcf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df39190613a16565b6001600160a01b031660208201528351849083908110610e1557610e15613a4c565b6020908102919091010151604051631627ee8960e01b81526001600160a01b038a8116600483015290911690631627ee8990602401602060405180830381865afa158015610e67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8b9190613a33565b816040018181525050610eb88886868581518110610eab57610eab613a4c565b6020026020010151611eb3565b816060018190525080838381518110610ed357610ed3613a4c565b602090810291909101015250600101610d22565b6060826000816001600160401b03811115610f0457610f04612f39565b604051908082528060200260200182016040528015610f3d57816020015b610f2a612e3a565b815260200190600190039081610f225790505b50905060005b8281101561081757610f7b878783818110610f6057610f60613a4c565b9050602002016020810190610f75919061345c565b866118ca565b828281518110610f8d57610f8d613a4c565b6020908102919091010152600101610f43565b60408051808201909152600080825260208201526000826001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ff4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110189190613a16565b90506000816001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561105a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061107e9190613a16565b6040805180820182526001600160a01b03808816808352925163fc57d4df60e01b815260048101939093529293509160208301919084169063fc57d4df90602401602060405180830381865afa1580156110dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111009190613a33565b9052949350505050565b611112612e79565b6000826001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611152573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111769190613a33565b90506000836001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111dc9190613a16565b604051638e8f294b60e01b81526001600160a01b03868116600483015291925082916000918291841690638e8f294b906024016040805180830381865afa15801561122b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061124f9190613cc9565b915091506000876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611293573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b79190613a16565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061131d9190613cf5565b60ff1690506000805b600860ff8216116113e3576000886001600160a01b031663e85a29608d8460ff16600881111561135857611358613d18565b6040518363ffffffff1660e01b8152600401611375929190613d2e565b602060405180830381865afa158015611392573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b69190613d69565b6113c15760006113c4565b60015b60ff9081169083161b9290921791506113dc81613d84565b9050611326565b506000808b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611425573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114499190613a33565b11156114b4578a6001600160a01b031663ae9d70b06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561148d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114b19190613a33565b90505b6040518061022001604052808c6001600160a01b031681526020018a81526020018281526020018c6001600160a01b031663f8f9da286040518163ffffffff1660e01b8152600401602060405180830381865afa158015611519573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153d9190613a33565b81526020018c6001600160a01b031663173b99046040518163ffffffff1660e01b8152600401602060405180830381865afa158015611580573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a49190613a33565b81526040516302c3bcbb60e01b81526001600160a01b038e811660048301526020909201918a16906302c3bcbb90602401602060405180830381865afa1580156115f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116169190613a33565b815260405163252c221960e11b81526001600160a01b038e811660048301526020909201918a1690634a58443290602401602060405180830381865afa158015611664573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116889190613a33565b81526020018c6001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ef9190613a33565b81526020018c6001600160a01b0316638f840ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611732573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117569190613a33565b81526020018c6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611799573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117bd9190613a33565b81526020018c6001600160a01b0316633b1d21a26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611800573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118249190613a33565b81526020018715158152602001868152602001856001600160a01b031681526020018c6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611884573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118a89190613cf5565b60ff168152602001848152602001838152509950505050505050505050919050565b6118d2612e3a565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908516906370a0823190602401602060405180830381865afa15801561191c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119409190613a33565b6040516305eff7ef60e21b81526001600160a01b0385811660048301529192506000918616906317bfdfbc906024016020604051808303816000875af115801561198e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b29190613a33565b604051633af9e66960e01b81526001600160a01b038681166004830152919250600091871690633af9e669906024016020604051808303816000875af1158015611a00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a249190613a33565b90506000806000886001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a8d9190613a16565b6040516370a0823160e01b81526001600160a01b038a81166004830152919250908216906370a0823190602401602060405180830381865afa158015611ad7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611afb9190613a33565b604051636eb1769f60e11b81526001600160a01b038a811660048301528b811660248301529194509082169063dd62ed3e90604401602060405180830381865afa158015611b4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b719190613a33565b6040805160c0810182526001600160a01b038c168152602081019890985287019590955250506060840191909152608083015260a0820152905092915050565b604051631e6db74760e31b81526001600160a01b038281166004830152606091849182169063f36dba3890602401600060405180830381865afa158015611bfc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610baf9190810190613da3565b80516060906000816001600160401b03811115611c4357611c43612f39565b604051908082528060200260200182016040528015611c7c57816020015b611c69612e79565b815260200190600190039081611c615790505b50905060005b82811015611cd157611cac858281518110611c9f57611c9f613a4c565b602002602001015161110a565b828281518110611cbe57611cbe613a4c565b6020908102919091010152600101611c82565b509392505050565b6000611d077f000000000000000000000000000000000000000000000000000000000000000063ffffffff16565b905090565b4390565b4290565b60606000826001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015611d56573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d7e9190810190613e31565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031603611dbf5792915050565b8051600090815b81811015611ea9576000848281518110611de257611de2613a4c565b60200260200101516001600160a01b03166322abdbf56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e4b9190613a33565b1115611ea157838181518110611e6357611e63613a4c565b6020026020010151848481518110611e7d57611e7d613a4c565b6001600160a01b0390921660209283029190910190910152611e9e83613ebf565b92505b600101611dc6565b5050815292915050565b6060600083516001600160401b03811115611ed057611ed0612f39565b604051908082528060200260200182016040528015611f1557816020015b6040805180820190915260008082526020820152815260200190600190039081611eee5790505b50905060005b84518110156106e557611f51604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b611f7e604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b7f00000000000000000000000000000000000000000000000000000000000000001561210157856001600160a01b0316638f693ec7888581518110611fc557611fc5613a4c565b60200260200101516040518263ffffffff1660e01b8152600401611ff891906001600160a01b0391909116815260200190565b606060405180830381865afa158015612015573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120399190613eef565b604085015260208401526001600160e01b0316825286516001600160a01b0387169063818149459089908690811061207357612073613a4c565b60200260200101516040518263ffffffff1660e01b81526004016120a691906001600160a01b0391909116815260200190565b606060405180830381865afa1580156120c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e79190613eef565b604084015260208301526001600160e01b0316815261226c565b856001600160a01b0316632c427b5788858151811061212257612122613a4c565b60200260200101516040518263ffffffff1660e01b815260040161215591906001600160a01b0391909116815260200190565b606060405180830381865afa158015612172573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121969190613f38565b63ffffffff90811660408601521660208401526001600160e01b0316825286516001600160a01b038716906392a18235908990869081106121d9576121d9613a4c565b60200260200101516040518263ffffffff1660e01b815260040161220c91906001600160a01b0391909116815260200190565b606060405180830381865afa158015612229573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061224d9190613f38565b63ffffffff90811660408501521660208301526001600160e01b031681525b6000604051806020016040528089868151811061228b5761228b613a4c565b60200260200101516001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122f49190613a33565b815250905061231e88858151811061230e5761230e613a4c565b6020026020010151888584612413565b61234288858151811061233357612333613a4c565b60200260200101518884612614565b600061236a89868151811061235957612359613a4c565b6020026020010151898c878661280b565b905060006123938a878151811061238357612383613a4c565b60200260200101518a8d87612a3b565b60408051808201909152600080825260208201529091508a87815181106123bc576123bc613a4c565b60209081029190910101516001600160a01b031681526123dc8284613be4565b6020820152875181908990899081106123f7576123f7613a4c565b6020026020010181905250505050505050806001019050611f1b565b604051637c05a7c560e01b81526001600160a01b03858116600483015260009190851690637c05a7c590602401602060405180830381865afa15801561245d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124819190613a33565b9050600061248d611cd9565b9050600084604001511180156124a65750836040015181115b156124b2575060408301515b60006124c2828660200151612c5f565b90506000811180156124d45750600083115b156125fd576000612546886001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561251c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125409190613a33565b86612c72565b905060006125548386612c90565b90506000808311612574576040518060200160405280600081525061257e565b61257e8284612c9c565b905060006125a760405180602001604052808b600001516001600160e01b031681525083612ce1565b90506125e28160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612d0d565b6001600160e01b03168952505050506020850182905261260b565b801561260b57602085018290525b50505050505050565b604051631d31307360e21b81526001600160a01b038481166004830152600091908416906374c4c1cc90602401602060405180830381865afa15801561265e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126829190613a33565b9050600061268e611cd9565b9050600083604001511180156126a75750826040015181115b156126b3575060408201515b60006126c3828560200151612c5f565b90506000811180156126d55750600083115b156127f5576000866001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561271a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061273e9190613a33565b9050600061274c8386612c90565b9050600080831161276c5760405180602001604052806000815250612776565b6127768284612c9c565b9050600061279f60405180602001604052808a600001516001600160e01b031681525083612ce1565b90506127da8160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612d0d565b6001600160e01b031688525050505060208401829052612803565b801561280357602084018290525b505050505050565b604080516020808201835284516001600160e01b031682528251908101928390526336fe846560e11b9092526001600160a01b0387811660248401528581166044840152600092839181908916636dfd08ca60648301602060405180830381865afa15801561287e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a29190613a33565b905280519091501580156129245750866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129139190613f7b565b6001600160e01b0316826000015110155b1561299757866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061298b9190613f7b565b6001600160e01b031681525b60006129a38383612d49565b6040516395dd919360e01b81526001600160a01b038981166004830152919250600091612a1e91908c16906395dd919390602401602060405180830381865afa1580156129f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a189190613a33565b87612c72565b90506000612a2c8284612d75565b9b9a5050505050505050505050565b604080516020808201835283516001600160e01b0316825282519081019283905263552c097160e01b9092526001600160a01b038681166024840152848116604484015260009283918190881663552c097160648301602060405180830381865afa158015612aae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ad29190613a33565b90528051909150158015612b545750856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b439190613f7b565b6001600160e01b0316826000015110155b15612bc757856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bbb9190613f7b565b6001600160e01b031681525b6000612bd38383612d49565b6040516370a0823160e01b81526001600160a01b0388811660048301529192506000918a16906370a0823190602401602060405180830381865afa158015612c1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c439190613a33565b90506000612c518284612d75565b9a9950505050505050505050565b6000612c6b8284613f96565b9392505050565b6000612c6b612c8984670de0b6b3a7640000612c90565b8351612d9f565b6000612c6b8284613bab565b6040805160208101909152600081526040518060200160405280612cd8612cd2866ec097ce7bc90715b34b9f1000000000612c90565b85612d9f565b90529392505050565b6040805160208101909152600081526040518060200160405280612cd885600001518560000151612dab565b6000816001600160e01b03841115612d415760405162461bcd60e51b8152600401612d389190613fa9565b60405180910390fd5b509192915050565b6040805160208101909152600081526040518060200160405280612cd885600001518560000151612c5f565b60006ec097ce7bc90715b34b9f1000000000612d95848460000151612c90565b612c6b9190613bc2565b6000612c6b8284613bc2565b6000612c6b8284613be4565b604051806101a001604052806060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160608152602001606081526020016060815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001606081525090565b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180610220016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b6001600160a01b0381168114612f2657600080fd5b50565b8035612f3481612f11565b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715612f7157612f71612f39565b60405290565b604051606081016001600160401b0381118282101715612f7157612f71612f39565b604051601f8201601f191681016001600160401b0381118282101715612fc157612fc1612f39565b604052919050565b60006001600160401b03821115612fe257612fe2612f39565b50601f01601f191660200190565b6000806040838503121561300357600080fd5b823561300e81612f11565b91506020838101356001600160401b038082111561302b57600080fd5b9085019060a0828803121561303f57600080fd5b613047612f4f565b82358281111561305657600080fd5b83019150601f8201881361306957600080fd5b813561307c61307782612fc9565b612f99565b818152898683860101111561309057600080fd5b8186850187830137600086838301015280835250506130b0848401612f29565b848201526130c060408401612f29565b60408201526060830135606082015260808301356080820152809450505050509250929050565b60005b838110156131025781810151838201526020016130ea565b50506000910152565b600081518084526131238160208601602086016130e7565b601f01601f19169290920160200192915050565b80516001600160a01b031682526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e0830152610100808201518184015250610120808201518184015250610140808201518184015250610160808201516131c28285018215159052565b505061018081810151908301526101a0808201516001600160a01b0316908301526101c080820151908301526101e0808201519083015261020090810151910152565b60008151808452602080850194506020840160005b838110156132415761322d878351613137565b61022096909601959082019060010161321a565b509495945050505050565b60006101a082518185526132628286018261310b565b915050602083015161327f60208601826001600160a01b03169052565b50604083015161329a60408601826001600160a01b03169052565b50606083015160608501526080830151608085015260a083015184820360a08601526132c6828261310b565b91505060c083015184820360c08601526132e0828261310b565b91505060e083015184820360e08601526132fa828261310b565b91505061010080840151613318828701826001600160a01b03169052565b505061012083810151908501526101408084015190850152610160808401519085015261018080840151858303828701526133538382613205565b9695505050505050565b602081526000612c6b602083018461324c565b60008083601f84011261338257600080fd5b5081356001600160401b0381111561339957600080fd5b6020830191508360208260051b85010111156133b457600080fd5b9250929050565b600080602083850312156133ce57600080fd5b82356001600160401b038111156133e457600080fd5b6133f085828601613370565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b8281101561344f5761343f84835180516001600160a01b03168252602090810151910152565b9284019290850190600101613419565b5091979650505050505050565b60006020828403121561346e57600080fd5b8135612c6b81612f11565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156134d057603f198886030184526134be85835161324c565b945092850192908501906001016134a2565b5092979650505050505050565b602080825282516001600160a01b03168282015282810151604080840191909152808401516060808501528051608085018190526000939291830191849160a08701905b8084101561355b5761354782865180516001600160a01b03168252602090810151910152565b938501936001939093019290820190613521565b50979650505050505050565b6000806040838503121561357a57600080fd5b823561358581612f11565b9150602083013561359581612f11565b809150509250929050565b6000806000606084860312156135b557600080fd5b83356135c081612f11565b925060208401356135d081612f11565b915060408401356135e081612f11565b809150509250925092565b600060208083018184528085518083526040925060408601915060408160051b8701018488016000805b848110156136b857898403603f19018652825180516001600160a01b03908116865289820151168986015287810151888601526060908101516080918601829052805191860182905289019060a086019084905b808210156136a35761368f83855180516001600160a01b03168252602090810151910152565b928b0192918a019160019190910190613669565b50509689019694505091870191600101613615565b50919998505050505050505050565b6000806000604084860312156136dc57600080fd5b83356001600160401b038111156136f257600080fd5b6136fe86828701613370565b90945092505060208401356135e081612f11565b80516001600160a01b031682526020808201519083015260408082015190830152606080820151908301526080808201519083015260a090810151910152565b6020808252825182820181905260009190848201906040850190845b8181101561379457613781838551613712565b9284019260c0929092019160010161376e565b50909695505050505050565b81516001600160a01b031681526020808301519082015260408101610620565b61022081016106208284613137565b60c081016106208284613712565b6020808252825182820181905260009190848201906040850190845b818110156137945783516001600160a01b0316835292840192918401916001016137f9565b60006001600160401b0382111561383757613837612f39565b5060051b60200190565b6000602080838503121561385457600080fd5b82356001600160401b0381111561386a57600080fd5b8301601f8101851361387b57600080fd5b80356138896130778261381e565b81815260059190911b820183019083810190878311156138a857600080fd5b928401925b828410156138cf5783356138c081612f11565b825292840192908401906138ad565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561379457613909838551613137565b9284019261022092909201916001016138f6565b600082601f83011261392e57600080fd5b815161393c61307782612fc9565b81815284602083860101111561395157600080fd5b610baf8260208301602087016130e7565b60006020828403121561397457600080fd5b81516001600160401b038082111561398b57600080fd5b908301906060828603121561399f57600080fd5b6139a7612f77565b8251828111156139b657600080fd5b6139c28782860161391d565b8252506020830151828111156139d757600080fd5b6139e38782860161391d565b6020830152506040830151828111156139fb57600080fd5b613a078782860161391d565b60408301525095945050505050565b600060208284031215613a2857600080fd5b8151612c6b81612f11565b600060208284031215613a4557600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600060a08284031215613a7457600080fd5b613a7c612f4f565b905081516001600160401b03811115613a9457600080fd5b613aa08482850161391d565b8252506020820151613ab181612f11565b60208201526040820151613ac481612f11565b80604083015250606082015160608201526080820151608082015292915050565b60006020808385031215613af857600080fd5b82516001600160401b0380821115613b0f57600080fd5b818501915085601f830112613b2357600080fd5b8151613b316130778261381e565b81815260059190911b83018401908481019088831115613b5057600080fd5b8585015b83811015613b8857805185811115613b6c5760008081fd5b613b7a8b89838a0101613a62565b845250918601918601613b54565b5098975050505050505050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761062057610620613b95565b600082613bdf57634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561062057610620613b95565b600060208284031215613c0957600080fd5b81516001600160401b03811115613c1f57600080fd5b610baf84828501613a62565b60006020808385031215613c3e57600080fd5b82516001600160401b03811115613c5457600080fd5b8301601f81018513613c6557600080fd5b8051613c736130778261381e565b81815260059190911b82018301908381019087831115613c9257600080fd5b928401925b828410156138cf578351613caa81612f11565b82529284019290840190613c97565b80518015158114612f3457600080fd5b60008060408385031215613cdc57600080fd5b613ce583613cb9565b9150602083015190509250929050565b600060208284031215613d0757600080fd5b815160ff81168114612c6b57600080fd5b634e487b7160e01b600052602160045260246000fd5b6001600160a01b03831681526040810160098310613d5c57634e487b7160e01b600052602160045260246000fd5b8260208301529392505050565b600060208284031215613d7b57600080fd5b612c6b82613cb9565b600060ff821660ff8103613d9a57613d9a613b95565b60010192915050565b60006020808385031215613db657600080fd5b82516001600160401b03811115613dcc57600080fd5b8301601f81018513613ddd57600080fd5b8051613deb6130778261381e565b81815260059190911b82018301908381019087831115613e0a57600080fd5b928401925b828410156138cf578351613e2281612f11565b82529284019290840190613e0f565b60006020808385031215613e4457600080fd5b82516001600160401b03811115613e5a57600080fd5b8301601f81018513613e6b57600080fd5b8051613e796130778261381e565b81815260059190911b82018301908381019087831115613e9857600080fd5b928401925b828410156138cf578351613eb081612f11565b82529284019290840190613e9d565b600060018201613ed157613ed1613b95565b5060010190565b80516001600160e01b0381168114612f3457600080fd5b600080600060608486031215613f0457600080fd5b613f0d84613ed8565b925060208401519150604084015190509250925092565b805163ffffffff81168114612f3457600080fd5b600080600060608486031215613f4d57600080fd5b613f5684613ed8565b9250613f6460208501613f24565b9150613f7260408501613f24565b90509250925092565b600060208284031215613f8d57600080fd5b612c6b82613ed8565b8181038181111561062057610620613b95565b602081526000612c6b602083018461310b56fea264697066735822122096dca9ef030f65331631c7305d4d9405c1d0b56d48eb3787508d19369d85297764736f6c63430008190033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061010b5760003560e01c80637c51b642116100a2578063c7ad089511610071578063c7ad0895146102ac578063d26998e9146102e3578063d77ebf961461030a578063e0a67f111461032a578063e1d146fb1461034a57600080fd5b80637c51b6421461022c5780637c84e3b31461024c578063aa5dbd231461026c578063b31242391461028c57600080fd5b806347d86a81116100de57806347d86a811461019957806355dd9515146101ac5780636857249c146101d75780637a27db571461020c57600080fd5b80630d3ae318146101105780631f884fdf14610139578063345954dc146101595780633e3e399c14610179575b600080fd5b61012361011e366004612ff0565b610352565b604051610130919061335d565b60405180910390f35b61014c6101473660046133bb565b610626565b60405161013091906133fc565b61016c61016736600461345c565b6106ee565b6040516101309190613479565b61018c61018736600461345c565b610821565b60405161013091906134dd565b6101236101a7366004613567565b610b30565b6101bf6101ba3660046135a0565b610bb7565b6040516001600160a01b039091168152602001610130565b6101fe7f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610130565b61021f61021a366004613567565b610c37565b60405161013091906135eb565b61023f61023a3660046136c7565b610ee7565b6040516101309190613752565b61025f61025a36600461345c565b610fa0565b60405161013091906137a0565b61027f61027a36600461345c565b61110a565b60405161013091906137c0565b61029f61029a366004613567565b6118ca565b60405161013091906137cf565b6102d37f000000000000000000000000000000000000000000000000000000000000000081565b6040519015158152602001610130565b6101bf7f000000000000000000000000000000000000000000000000000000000000000081565b61031d610318366004613567565b611bb1565b60405161013091906137dd565b61033d610338366004613841565b611c24565b60405161013091906138da565b6101fe611cd9565b61035a612db7565b6040820151600061036a82611d14565b9050600061037782611c24565b60408681015190516328ebbe8b60e21b81526001600160a01b039182166004820152919250879160009183169063a3aefa2c90602401600060405180830381865afa1580156103ca573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526103f29190810190613962565b90506000876040015190506000604051806101a001604052808a6000015181526020018a602001516001600160a01b031681526020018a604001516001600160a01b031681526020018a6060015181526020018a608001518152602001846000015181526020018460200151815260200184604001518152602001836001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104cf9190613a16565b6001600160a01b03168152602001836001600160a01b031663e87554466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561051b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053f9190613a33565b8152602001836001600160a01b0316634ada90af6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610582573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105a69190613a33565b8152602001836001600160a01b031663db5c65de6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060d9190613a33565b8152602001959095525092955050505050505b92915050565b6060816000816001600160401b0381111561064357610643612f39565b60405190808252806020026020018201604052801561068857816020015b60408051808201909152600080825260208201528152602001906001900390816106615790505b50905060005b828110156106e5576106c08686838181106106ab576106ab613a4c565b905060200201602081019061025a919061345c565b8282815181106106d2576106d2613a4c565b602090810291909101015260010161068e565b50949350505050565b606060008290506000816001600160a01b031663d88ff1f46040518163ffffffff1660e01b8152600401600060405180830381865afa158015610735573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261075d9190810190613ae5565b80519091506000816001600160401b0381111561077c5761077c612f39565b6040519080825280602002602001820160405280156107b557816020015b6107a2612db7565b81526020019060019003908161079a5790505b50905060005b828110156108175760008482815181106107d7576107d7613a4c565b6020026020010151905060006107ed8983610352565b90508084848151811061080257610802613a4c565b602090810291909101015250506001016107bb565b5095945050505050565b60408051606080820183526000808352602083018190529282015290828161084882611d14565b90506000826001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561088a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ae9190613a16565b9050600082516001600160401b038111156108cb576108cb612f39565b60405190808252806020026020018201604052801561091057816020015b60408051808201909152600080825260208201528152602001906001900390816108e95790505b509050610940604051806060016040528060006001600160a01b0316815260200160008152602001606081525090565b6001600160a01b03881681526040810182905260005b8451811015610b1c57604080518082019091526000808252602082015285828151811061098557610985613a4c565b602002602001015181600001906001600160a01b031690816001600160a01b031681525050670de0b6b3a7640000856001600160a01b031663fc57d4df8885815181106109d4576109d4613a4c565b60200260200101516040518263ffffffff1660e01b8152600401610a0791906001600160a01b0391909116815260200190565b602060405180830381865afa158015610a24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a489190613a33565b878481518110610a5a57610a5a613a4c565b60200260200101516001600160a01b031663bbcac5576040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac39190613a33565b610acd9190613bab565b610ad79190613bc2565b60208201526040830151805182919084908110610af657610af6613a4c565b6020026020010181905250806020015188610b119190613be4565b975050600101610956565b506020810195909552509295945050505050565b610b38612db7565b604051637aee632d60e01b81526001600160a01b0383811660048301528491610baf91839190821690637aee632d90602401600060405180830381865afa158015610b87573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261011e9190810190613bf7565b949350505050565b60405163266e0a7f60e01b81526001600160a01b0383811660048301528281166024830152600091859182169063266e0a7f90604401602060405180830381865afa158015610c0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2e9190613a16565b95945050505050565b60606000610c4483611d14565b90506000836001600160a01b03166361252fd16040518163ffffffff1660e01b8152600401600060405180830381865afa158015610c86573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cae9190810190613c2b565b9050600081516001600160401b03811115610ccb57610ccb612f39565b604051908082528060200260200182016040528015610d1c57816020015b6040805160808101825260008082526020808301829052928201526060808201528252600019909201910181610ce95790505b50905060005b8251811015610817576040805160808101825260008082526020820181905291810191909152606080820152838281518110610d6057610d60613a4c565b60209081029190910101516001600160a01b031681528351849083908110610d8a57610d8a613a4c565b60200260200101516001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dcf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df39190613a16565b6001600160a01b031660208201528351849083908110610e1557610e15613a4c565b6020908102919091010151604051631627ee8960e01b81526001600160a01b038a8116600483015290911690631627ee8990602401602060405180830381865afa158015610e67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8b9190613a33565b816040018181525050610eb88886868581518110610eab57610eab613a4c565b6020026020010151611eb3565b816060018190525080838381518110610ed357610ed3613a4c565b602090810291909101015250600101610d22565b6060826000816001600160401b03811115610f0457610f04612f39565b604051908082528060200260200182016040528015610f3d57816020015b610f2a612e3a565b815260200190600190039081610f225790505b50905060005b8281101561081757610f7b878783818110610f6057610f60613a4c565b9050602002016020810190610f75919061345c565b866118ca565b828281518110610f8d57610f8d613a4c565b6020908102919091010152600101610f43565b60408051808201909152600080825260208201526000826001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ff4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110189190613a16565b90506000816001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561105a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061107e9190613a16565b6040805180820182526001600160a01b03808816808352925163fc57d4df60e01b815260048101939093529293509160208301919084169063fc57d4df90602401602060405180830381865afa1580156110dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111009190613a33565b9052949350505050565b611112612e79565b6000826001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611152573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111769190613a33565b90506000836001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111dc9190613a16565b604051638e8f294b60e01b81526001600160a01b03868116600483015291925082916000918291841690638e8f294b906024016040805180830381865afa15801561122b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061124f9190613cc9565b915091506000876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611293573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b79190613a16565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061131d9190613cf5565b60ff1690506000805b600860ff8216116113e3576000886001600160a01b031663e85a29608d8460ff16600881111561135857611358613d18565b6040518363ffffffff1660e01b8152600401611375929190613d2e565b602060405180830381865afa158015611392573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b69190613d69565b6113c15760006113c4565b60015b60ff9081169083161b9290921791506113dc81613d84565b9050611326565b506000808b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611425573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114499190613a33565b11156114b4578a6001600160a01b031663ae9d70b06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561148d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114b19190613a33565b90505b6040518061022001604052808c6001600160a01b031681526020018a81526020018281526020018c6001600160a01b031663f8f9da286040518163ffffffff1660e01b8152600401602060405180830381865afa158015611519573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153d9190613a33565b81526020018c6001600160a01b031663173b99046040518163ffffffff1660e01b8152600401602060405180830381865afa158015611580573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a49190613a33565b81526040516302c3bcbb60e01b81526001600160a01b038e811660048301526020909201918a16906302c3bcbb90602401602060405180830381865afa1580156115f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116169190613a33565b815260405163252c221960e11b81526001600160a01b038e811660048301526020909201918a1690634a58443290602401602060405180830381865afa158015611664573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116889190613a33565b81526020018c6001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ef9190613a33565b81526020018c6001600160a01b0316638f840ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611732573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117569190613a33565b81526020018c6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611799573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117bd9190613a33565b81526020018c6001600160a01b0316633b1d21a26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611800573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118249190613a33565b81526020018715158152602001868152602001856001600160a01b031681526020018c6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611884573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118a89190613cf5565b60ff168152602001848152602001838152509950505050505050505050919050565b6118d2612e3a565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908516906370a0823190602401602060405180830381865afa15801561191c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119409190613a33565b6040516305eff7ef60e21b81526001600160a01b0385811660048301529192506000918616906317bfdfbc906024016020604051808303816000875af115801561198e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b29190613a33565b604051633af9e66960e01b81526001600160a01b038681166004830152919250600091871690633af9e669906024016020604051808303816000875af1158015611a00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a249190613a33565b90506000806000886001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a8d9190613a16565b6040516370a0823160e01b81526001600160a01b038a81166004830152919250908216906370a0823190602401602060405180830381865afa158015611ad7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611afb9190613a33565b604051636eb1769f60e11b81526001600160a01b038a811660048301528b811660248301529194509082169063dd62ed3e90604401602060405180830381865afa158015611b4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b719190613a33565b6040805160c0810182526001600160a01b038c168152602081019890985287019590955250506060840191909152608083015260a0820152905092915050565b604051631e6db74760e31b81526001600160a01b038281166004830152606091849182169063f36dba3890602401600060405180830381865afa158015611bfc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610baf9190810190613da3565b80516060906000816001600160401b03811115611c4357611c43612f39565b604051908082528060200260200182016040528015611c7c57816020015b611c69612e79565b815260200190600190039081611c615790505b50905060005b82811015611cd157611cac858281518110611c9f57611c9f613a4c565b602002602001015161110a565b828281518110611cbe57611cbe613a4c565b6020908102919091010152600101611c82565b509392505050565b6000611d077f000000000000000000000000000000000000000000000000000000000000000063ffffffff16565b905090565b4390565b4290565b60606000826001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015611d56573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d7e9190810190613e31565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031603611dbf5792915050565b8051600090815b81811015611ea9576000848281518110611de257611de2613a4c565b60200260200101516001600160a01b03166322abdbf56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e4b9190613a33565b1115611ea157838181518110611e6357611e63613a4c565b6020026020010151848481518110611e7d57611e7d613a4c565b6001600160a01b0390921660209283029190910190910152611e9e83613ebf565b92505b600101611dc6565b5050815292915050565b6060600083516001600160401b03811115611ed057611ed0612f39565b604051908082528060200260200182016040528015611f1557816020015b6040805180820190915260008082526020820152815260200190600190039081611eee5790505b50905060005b84518110156106e557611f51604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b611f7e604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b7f00000000000000000000000000000000000000000000000000000000000000001561210157856001600160a01b0316638f693ec7888581518110611fc557611fc5613a4c565b60200260200101516040518263ffffffff1660e01b8152600401611ff891906001600160a01b0391909116815260200190565b606060405180830381865afa158015612015573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120399190613eef565b604085015260208401526001600160e01b0316825286516001600160a01b0387169063818149459089908690811061207357612073613a4c565b60200260200101516040518263ffffffff1660e01b81526004016120a691906001600160a01b0391909116815260200190565b606060405180830381865afa1580156120c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e79190613eef565b604084015260208301526001600160e01b0316815261226c565b856001600160a01b0316632c427b5788858151811061212257612122613a4c565b60200260200101516040518263ffffffff1660e01b815260040161215591906001600160a01b0391909116815260200190565b606060405180830381865afa158015612172573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121969190613f38565b63ffffffff90811660408601521660208401526001600160e01b0316825286516001600160a01b038716906392a18235908990869081106121d9576121d9613a4c565b60200260200101516040518263ffffffff1660e01b815260040161220c91906001600160a01b0391909116815260200190565b606060405180830381865afa158015612229573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061224d9190613f38565b63ffffffff90811660408501521660208301526001600160e01b031681525b6000604051806020016040528089868151811061228b5761228b613a4c565b60200260200101516001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122f49190613a33565b815250905061231e88858151811061230e5761230e613a4c565b6020026020010151888584612413565b61234288858151811061233357612333613a4c565b60200260200101518884612614565b600061236a89868151811061235957612359613a4c565b6020026020010151898c878661280b565b905060006123938a878151811061238357612383613a4c565b60200260200101518a8d87612a3b565b60408051808201909152600080825260208201529091508a87815181106123bc576123bc613a4c565b60209081029190910101516001600160a01b031681526123dc8284613be4565b6020820152875181908990899081106123f7576123f7613a4c565b6020026020010181905250505050505050806001019050611f1b565b604051637c05a7c560e01b81526001600160a01b03858116600483015260009190851690637c05a7c590602401602060405180830381865afa15801561245d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124819190613a33565b9050600061248d611cd9565b9050600084604001511180156124a65750836040015181115b156124b2575060408301515b60006124c2828660200151612c5f565b90506000811180156124d45750600083115b156125fd576000612546886001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561251c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125409190613a33565b86612c72565b905060006125548386612c90565b90506000808311612574576040518060200160405280600081525061257e565b61257e8284612c9c565b905060006125a760405180602001604052808b600001516001600160e01b031681525083612ce1565b90506125e28160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612d0d565b6001600160e01b03168952505050506020850182905261260b565b801561260b57602085018290525b50505050505050565b604051631d31307360e21b81526001600160a01b038481166004830152600091908416906374c4c1cc90602401602060405180830381865afa15801561265e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126829190613a33565b9050600061268e611cd9565b9050600083604001511180156126a75750826040015181115b156126b3575060408201515b60006126c3828560200151612c5f565b90506000811180156126d55750600083115b156127f5576000866001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561271a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061273e9190613a33565b9050600061274c8386612c90565b9050600080831161276c5760405180602001604052806000815250612776565b6127768284612c9c565b9050600061279f60405180602001604052808a600001516001600160e01b031681525083612ce1565b90506127da8160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612d0d565b6001600160e01b031688525050505060208401829052612803565b801561280357602084018290525b505050505050565b604080516020808201835284516001600160e01b031682528251908101928390526336fe846560e11b9092526001600160a01b0387811660248401528581166044840152600092839181908916636dfd08ca60648301602060405180830381865afa15801561287e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a29190613a33565b905280519091501580156129245750866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129139190613f7b565b6001600160e01b0316826000015110155b1561299757866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061298b9190613f7b565b6001600160e01b031681525b60006129a38383612d49565b6040516395dd919360e01b81526001600160a01b038981166004830152919250600091612a1e91908c16906395dd919390602401602060405180830381865afa1580156129f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a189190613a33565b87612c72565b90506000612a2c8284612d75565b9b9a5050505050505050505050565b604080516020808201835283516001600160e01b0316825282519081019283905263552c097160e01b9092526001600160a01b038681166024840152848116604484015260009283918190881663552c097160648301602060405180830381865afa158015612aae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ad29190613a33565b90528051909150158015612b545750856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b439190613f7b565b6001600160e01b0316826000015110155b15612bc757856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bbb9190613f7b565b6001600160e01b031681525b6000612bd38383612d49565b6040516370a0823160e01b81526001600160a01b0388811660048301529192506000918a16906370a0823190602401602060405180830381865afa158015612c1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c439190613a33565b90506000612c518284612d75565b9a9950505050505050505050565b6000612c6b8284613f96565b9392505050565b6000612c6b612c8984670de0b6b3a7640000612c90565b8351612d9f565b6000612c6b8284613bab565b6040805160208101909152600081526040518060200160405280612cd8612cd2866ec097ce7bc90715b34b9f1000000000612c90565b85612d9f565b90529392505050565b6040805160208101909152600081526040518060200160405280612cd885600001518560000151612dab565b6000816001600160e01b03841115612d415760405162461bcd60e51b8152600401612d389190613fa9565b60405180910390fd5b509192915050565b6040805160208101909152600081526040518060200160405280612cd885600001518560000151612c5f565b60006ec097ce7bc90715b34b9f1000000000612d95848460000151612c90565b612c6b9190613bc2565b6000612c6b8284613bc2565b6000612c6b8284613be4565b604051806101a001604052806060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160608152602001606081526020016060815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001606081525090565b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180610220016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b6001600160a01b0381168114612f2657600080fd5b50565b8035612f3481612f11565b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715612f7157612f71612f39565b60405290565b604051606081016001600160401b0381118282101715612f7157612f71612f39565b604051601f8201601f191681016001600160401b0381118282101715612fc157612fc1612f39565b604052919050565b60006001600160401b03821115612fe257612fe2612f39565b50601f01601f191660200190565b6000806040838503121561300357600080fd5b823561300e81612f11565b91506020838101356001600160401b038082111561302b57600080fd5b9085019060a0828803121561303f57600080fd5b613047612f4f565b82358281111561305657600080fd5b83019150601f8201881361306957600080fd5b813561307c61307782612fc9565b612f99565b818152898683860101111561309057600080fd5b8186850187830137600086838301015280835250506130b0848401612f29565b848201526130c060408401612f29565b60408201526060830135606082015260808301356080820152809450505050509250929050565b60005b838110156131025781810151838201526020016130ea565b50506000910152565b600081518084526131238160208601602086016130e7565b601f01601f19169290920160200192915050565b80516001600160a01b031682526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e0830152610100808201518184015250610120808201518184015250610140808201518184015250610160808201516131c28285018215159052565b505061018081810151908301526101a0808201516001600160a01b0316908301526101c080820151908301526101e0808201519083015261020090810151910152565b60008151808452602080850194506020840160005b838110156132415761322d878351613137565b61022096909601959082019060010161321a565b509495945050505050565b60006101a082518185526132628286018261310b565b915050602083015161327f60208601826001600160a01b03169052565b50604083015161329a60408601826001600160a01b03169052565b50606083015160608501526080830151608085015260a083015184820360a08601526132c6828261310b565b91505060c083015184820360c08601526132e0828261310b565b91505060e083015184820360e08601526132fa828261310b565b91505061010080840151613318828701826001600160a01b03169052565b505061012083810151908501526101408084015190850152610160808401519085015261018080840151858303828701526133538382613205565b9695505050505050565b602081526000612c6b602083018461324c565b60008083601f84011261338257600080fd5b5081356001600160401b0381111561339957600080fd5b6020830191508360208260051b85010111156133b457600080fd5b9250929050565b600080602083850312156133ce57600080fd5b82356001600160401b038111156133e457600080fd5b6133f085828601613370565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b8281101561344f5761343f84835180516001600160a01b03168252602090810151910152565b9284019290850190600101613419565b5091979650505050505050565b60006020828403121561346e57600080fd5b8135612c6b81612f11565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156134d057603f198886030184526134be85835161324c565b945092850192908501906001016134a2565b5092979650505050505050565b602080825282516001600160a01b03168282015282810151604080840191909152808401516060808501528051608085018190526000939291830191849160a08701905b8084101561355b5761354782865180516001600160a01b03168252602090810151910152565b938501936001939093019290820190613521565b50979650505050505050565b6000806040838503121561357a57600080fd5b823561358581612f11565b9150602083013561359581612f11565b809150509250929050565b6000806000606084860312156135b557600080fd5b83356135c081612f11565b925060208401356135d081612f11565b915060408401356135e081612f11565b809150509250925092565b600060208083018184528085518083526040925060408601915060408160051b8701018488016000805b848110156136b857898403603f19018652825180516001600160a01b03908116865289820151168986015287810151888601526060908101516080918601829052805191860182905289019060a086019084905b808210156136a35761368f83855180516001600160a01b03168252602090810151910152565b928b0192918a019160019190910190613669565b50509689019694505091870191600101613615565b50919998505050505050505050565b6000806000604084860312156136dc57600080fd5b83356001600160401b038111156136f257600080fd5b6136fe86828701613370565b90945092505060208401356135e081612f11565b80516001600160a01b031682526020808201519083015260408082015190830152606080820151908301526080808201519083015260a090810151910152565b6020808252825182820181905260009190848201906040850190845b8181101561379457613781838551613712565b9284019260c0929092019160010161376e565b50909695505050505050565b81516001600160a01b031681526020808301519082015260408101610620565b61022081016106208284613137565b60c081016106208284613712565b6020808252825182820181905260009190848201906040850190845b818110156137945783516001600160a01b0316835292840192918401916001016137f9565b60006001600160401b0382111561383757613837612f39565b5060051b60200190565b6000602080838503121561385457600080fd5b82356001600160401b0381111561386a57600080fd5b8301601f8101851361387b57600080fd5b80356138896130778261381e565b81815260059190911b820183019083810190878311156138a857600080fd5b928401925b828410156138cf5783356138c081612f11565b825292840192908401906138ad565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561379457613909838551613137565b9284019261022092909201916001016138f6565b600082601f83011261392e57600080fd5b815161393c61307782612fc9565b81815284602083860101111561395157600080fd5b610baf8260208301602087016130e7565b60006020828403121561397457600080fd5b81516001600160401b038082111561398b57600080fd5b908301906060828603121561399f57600080fd5b6139a7612f77565b8251828111156139b657600080fd5b6139c28782860161391d565b8252506020830151828111156139d757600080fd5b6139e38782860161391d565b6020830152506040830151828111156139fb57600080fd5b613a078782860161391d565b60408301525095945050505050565b600060208284031215613a2857600080fd5b8151612c6b81612f11565b600060208284031215613a4557600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600060a08284031215613a7457600080fd5b613a7c612f4f565b905081516001600160401b03811115613a9457600080fd5b613aa08482850161391d565b8252506020820151613ab181612f11565b60208201526040820151613ac481612f11565b80604083015250606082015160608201526080820151608082015292915050565b60006020808385031215613af857600080fd5b82516001600160401b0380821115613b0f57600080fd5b818501915085601f830112613b2357600080fd5b8151613b316130778261381e565b81815260059190911b83018401908481019088831115613b5057600080fd5b8585015b83811015613b8857805185811115613b6c5760008081fd5b613b7a8b89838a0101613a62565b845250918601918601613b54565b5098975050505050505050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761062057610620613b95565b600082613bdf57634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561062057610620613b95565b600060208284031215613c0957600080fd5b81516001600160401b03811115613c1f57600080fd5b610baf84828501613a62565b60006020808385031215613c3e57600080fd5b82516001600160401b03811115613c5457600080fd5b8301601f81018513613c6557600080fd5b8051613c736130778261381e565b81815260059190911b82018301908381019087831115613c9257600080fd5b928401925b828410156138cf578351613caa81612f11565b82529284019290840190613c97565b80518015158114612f3457600080fd5b60008060408385031215613cdc57600080fd5b613ce583613cb9565b9150602083015190509250929050565b600060208284031215613d0757600080fd5b815160ff81168114612c6b57600080fd5b634e487b7160e01b600052602160045260246000fd5b6001600160a01b03831681526040810160098310613d5c57634e487b7160e01b600052602160045260246000fd5b8260208301529392505050565b600060208284031215613d7b57600080fd5b612c6b82613cb9565b600060ff821660ff8103613d9a57613d9a613b95565b60010192915050565b60006020808385031215613db657600080fd5b82516001600160401b03811115613dcc57600080fd5b8301601f81018513613ddd57600080fd5b8051613deb6130778261381e565b81815260059190911b82018301908381019087831115613e0a57600080fd5b928401925b828410156138cf578351613e2281612f11565b82529284019290840190613e0f565b60006020808385031215613e4457600080fd5b82516001600160401b03811115613e5a57600080fd5b8301601f81018513613e6b57600080fd5b8051613e796130778261381e565b81815260059190911b82018301908381019087831115613e9857600080fd5b928401925b828410156138cf578351613eb081612f11565b82529284019290840190613e9d565b600060018201613ed157613ed1613b95565b5060010190565b80516001600160e01b0381168114612f3457600080fd5b600080600060608486031215613f0457600080fd5b613f0d84613ed8565b925060208401519150604084015190509250925092565b805163ffffffff81168114612f3457600080fd5b600080600060608486031215613f4d57600080fd5b613f5684613ed8565b9250613f6460208501613f24565b9150613f7260408501613f24565b90509250925092565b600060208284031215613f8d57600080fd5b612c6b82613ed8565b8181038181111561062057610620613b95565b602081526000612c6b602083018461310b56fea264697066735822122096dca9ef030f65331631c7305d4d9405c1d0b56d48eb3787508d19369d85297764736f6c63430008190033", "devdoc": { "author": "Venus", "kind": "dev", @@ -1198,6 +1216,7 @@ "custom:oz-upgrades-unsafe-allow": "constructor", "params": { "blocksPerYear_": "The number of blocks per year", + "corePoolComptroller_": "The address of the core pool comptroller", "timeBased_": "A boolean indicating whether the contract is based on time or block." } }, @@ -1342,6 +1361,9 @@ "blocksOrSecondsPerYear()": { "notice": "Stores blocksPerYear if isTimeBased is true else secondsPerYear is stored" }, + "corePoolComptroller()": { + "notice": "Address of the core pool comptroller (all markets are returned for this pool, including paused ones)" + }, "getAllPools(address)": { "notice": "Queries all pools with addtional details for each of them" }, @@ -1391,7 +1413,7 @@ "storageLayout": { "storage": [ { - "astId": 1745, + "astId": 1737, "contract": "contracts/Lens/PoolLens.sol:PoolLens", "label": "__gap", "offset": 0, diff --git a/deployments/arbitrumone/solcInputs/09f8b2889a382752688c03578bc27f8d.json b/deployments/arbitrumone/solcInputs/09f8b2889a382752688c03578bc27f8d.json new file mode 100644 index 000000000..b2e4f0f5c --- /dev/null +++ b/deployments/arbitrumone/solcInputs/09f8b2889a382752688c03578bc27f8d.json @@ -0,0 +1,139 @@ +{ + "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/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/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/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/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" + }, + "@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/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/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\ninterface IProtocolShareReserve {\n /// @notice it represents the type of vToken income\n enum IncomeType {\n SPREAD,\n LIQUIDATION,\n ERC4626_WRAPPER_REWARDS,\n FLASHLOAN\n }\n\n function updateAssetsState(\n address comptroller,\n address asset,\n IncomeType incomeType\n ) external;\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/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/venus-protocol/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" + }, + "@venusprotocol/venus-protocol/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/Comptroller.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { IPrime } from \"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\";\n\nimport { ComptrollerInterface, Action } from \"./ComptrollerInterface.sol\";\nimport { ComptrollerStorage } from \"./ComptrollerStorage.sol\";\nimport { ExponentialNoError } from \"./ExponentialNoError.sol\";\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.sol\";\nimport { MaxLoopsLimitHelper } from \"./MaxLoopsLimitHelper.sol\";\nimport { ensureNonzeroAddress } from \"./lib/validators.sol\";\n\n/**\n * @title Comptroller\n * @author Venus\n * @notice The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating,\n * and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts\n * with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows\n * or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing\n * liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow,\n * as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the\n * markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market’s corresponding liquidation threshold,\n * the borrow is eligible for liquidation.\n *\n * The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed\n * the `minLiquidatableCollateral` for the `Comptroller`:\n *\n * - `healAccount()`: This function is called to seize all of a given user’s collateral, requiring the `msg.sender` repay a certain percentage\n * of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed\n * 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt\n * and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool.\n * - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation\n * incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic\n * verifying that the repay amount does not exceed the close factor.\n */\ncontract Comptroller is\n Ownable2StepUpgradeable,\n AccessControlledV8,\n ComptrollerStorage,\n ComptrollerInterface,\n ExponentialNoError,\n MaxLoopsLimitHelper\n{\n // PoolRegistry, immutable to save on gas\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable poolRegistry;\n\n /// @notice Emitted when an account enters a market\n event MarketEntered(VToken indexed vToken, address indexed account);\n\n /// @notice Emitted when an account exits a market\n event MarketExited(VToken indexed vToken, address indexed account);\n\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(VToken vToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa);\n\n /// @notice Emitted when liquidation threshold is changed by admin\n event NewLiquidationThreshold(\n VToken vToken,\n uint256 oldLiquidationThresholdMantissa,\n uint256 newLiquidationThresholdMantissa\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 an action is paused on a market\n event ActionPausedMarket(VToken vToken, Action action, bool pauseState);\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 the collateral threshold (in USD) for non-batch liquidations is changed\n event NewMinLiquidatableCollateral(uint256 oldMinLiquidatableCollateral, uint256 newMinLiquidatableCollateral);\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 a rewards distributor is added\n event NewRewardsDistributor(address indexed rewardsDistributor, address indexed rewardToken);\n\n /// @notice Emitted when a market is supported\n event MarketSupported(VToken vToken);\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 a market\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\n\n /// @notice Emitted when a market is unlisted\n event MarketUnlisted(address indexed vToken);\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 Thrown when collateral factor exceeds the upper bound\n error InvalidCollateralFactor();\n\n /// @notice Thrown when liquidation threshold exceeds the collateral factor\n error InvalidLiquidationThreshold();\n\n /// @notice Thrown when the action is only available to specific sender, but the real sender was different\n error UnexpectedSender(address expectedSender, address actualSender);\n\n /// @notice Thrown when the oracle returns an invalid price for some asset\n error PriceError(address vToken);\n\n /// @notice Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\n error SnapshotError(address vToken, address user);\n\n /// @notice Thrown when the market is not listed\n error MarketNotListed(address market);\n\n /// @notice Thrown when a market has an unexpected comptroller\n error ComptrollerMismatch();\n\n /// @notice Thrown when user is not member of market\n error MarketNotCollateral(address vToken, address user);\n\n /// @notice Thrown when borrow action is not paused\n error BorrowActionNotPaused();\n\n /// @notice Thrown when mint action is not paused\n error MintActionNotPaused();\n\n /// @notice Thrown when redeem action is not paused\n error RedeemActionNotPaused();\n\n /// @notice Thrown when repay action is not paused\n error RepayActionNotPaused();\n\n /// @notice Thrown when seize action is not paused\n error SeizeActionNotPaused();\n\n /// @notice Thrown when exit market action is not paused\n error ExitMarketActionNotPaused();\n\n /// @notice Thrown when transfer action is not paused\n error TransferActionNotPaused();\n\n /// @notice Thrown when enter market action is not paused\n error EnterMarketActionNotPaused();\n\n /// @notice Thrown when liquidate action is not paused\n error LiquidateActionNotPaused();\n\n /// @notice Thrown when borrow cap is not zero\n error BorrowCapIsNotZero();\n\n /// @notice Thrown when supply cap is not zero\n error SupplyCapIsNotZero();\n\n /// @notice Thrown when collateral factor is not zero\n error CollateralFactorIsNotZero();\n\n /**\n * @notice Thrown during the liquidation if user's total collateral amount is lower than\n * a predefined threshold. In this case only batch liquidations (either liquidateAccount\n * or healAccount) are available.\n */\n error MinimalCollateralViolated(uint256 expectedGreaterThan, uint256 actual);\n error CollateralExceedsThreshold(uint256 expectedLessThanOrEqualTo, uint256 actual);\n error InsufficientCollateral(uint256 collateralToSeize, uint256 availableCollateral);\n\n /// @notice Thrown when the account doesn't have enough liquidity to redeem or borrow\n error InsufficientLiquidity();\n\n /// @notice Thrown when trying to liquidate a healthy account\n error InsufficientShortfall();\n\n /// @notice Thrown when trying to repay more than allowed by close factor\n error TooMuchRepay();\n\n /// @notice Thrown if the user is trying to exit a market in which they have an outstanding debt\n error NonzeroBorrowBalance();\n\n /// @notice Thrown when trying to perform an action that is paused\n error ActionPaused(address market, Action action);\n\n /// @notice Thrown when trying to add a market that is already listed\n error MarketAlreadyListed(address market);\n\n /// @notice Thrown if the supply cap is exceeded\n error SupplyCapExceeded(address market, uint256 cap);\n\n /// @notice Thrown if the borrow cap is exceeded\n error BorrowCapExceeded(address market, uint256 cap);\n\n /// @notice Thrown if delegate approval status is already set to the requested value\n error DelegationStatusUnchanged();\n\n /// @param poolRegistry_ Pool registry address\n /// @custom:oz-upgrades-unsafe-allow constructor\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n constructor(address poolRegistry_) {\n ensureNonzeroAddress(poolRegistry_);\n\n poolRegistry = poolRegistry_;\n _disableInitializers();\n }\n\n /**\n * @param loopLimit Limit for the loops can iterate to avoid the DOS\n * @param accessControlManager Access control manager contract address\n */\n function initialize(uint256 loopLimit, address accessControlManager) external initializer {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager);\n\n _setMaxLoopsLimit(loopLimit);\n }\n\n /**\n * @notice Add assets to be included in account liquidity calculation; enabling them to be used as collateral\n * @param vTokens The list of addresses of the vToken markets to be enabled\n * @return errors An array of NO_ERROR for compatibility with Venus core tooling\n * @custom:event MarketEntered is emitted for each market on success\n * @custom:error ActionPaused error is thrown if entering any of the markets is paused\n * @custom:error MarketNotListed error is thrown if any of the markets is not listed\n * @custom:access Not restricted\n */\n function enterMarkets(address[] memory vTokens) external override returns (uint256[] memory) {\n uint256 len = vTokens.length;\n\n uint256[] memory results = new uint256[](len);\n for (uint256 i; i < len; ++i) {\n VToken vToken = VToken(vTokens[i]);\n\n _addToMarket(vToken, msg.sender);\n results[i] = NO_ERROR;\n }\n\n return results;\n }\n\n /**\n * @notice Unlist a market by setting isListed to false\n * @dev Checks if all actions are paused, borrow/supply caps is set to 0 and collateral factor is to 0.\n * @param market The address of the market (token) to unlist\n * @return uint256 Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event MarketUnlisted is emitted on success\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error BorrowActionNotPaused error is thrown if borrow action is not paused\n * @custom:error MintActionNotPaused error is thrown if mint action is not paused\n * @custom:error RedeemActionNotPaused error is thrown if redeem action is not paused\n * @custom:error RepayActionNotPaused error is thrown if repay action is not paused\n * @custom:error EnterMarketActionNotPaused error is thrown if enter market action is not paused\n * @custom:error LiquidateActionNotPaused error is thrown if liquidate action is not paused\n * @custom:error BorrowCapIsNotZero error is thrown if borrow cap is not zero\n * @custom:error SupplyCapIsNotZero error is thrown if supply cap is not zero\n * @custom:error CollateralFactorIsNotZero error is thrown if collateral factor is not zero\n */\n function unlistMarket(address market) external returns (uint256) {\n _checkAccessAllowed(\"unlistMarket(address)\");\n\n Market storage _market = markets[market];\n\n if (!_market.isListed) {\n revert MarketNotListed(market);\n }\n\n if (!actionPaused(market, Action.BORROW)) {\n revert BorrowActionNotPaused();\n }\n\n if (!actionPaused(market, Action.MINT)) {\n revert MintActionNotPaused();\n }\n\n if (!actionPaused(market, Action.REDEEM)) {\n revert RedeemActionNotPaused();\n }\n\n if (!actionPaused(market, Action.REPAY)) {\n revert RepayActionNotPaused();\n }\n\n if (!actionPaused(market, Action.SEIZE)) {\n revert SeizeActionNotPaused();\n }\n\n if (!actionPaused(market, Action.ENTER_MARKET)) {\n revert EnterMarketActionNotPaused();\n }\n\n if (!actionPaused(market, Action.LIQUIDATE)) {\n revert LiquidateActionNotPaused();\n }\n\n if (!actionPaused(market, Action.TRANSFER)) {\n revert TransferActionNotPaused();\n }\n\n if (!actionPaused(market, Action.EXIT_MARKET)) {\n revert ExitMarketActionNotPaused();\n }\n\n if (borrowCaps[market] != 0) {\n revert BorrowCapIsNotZero();\n }\n\n if (supplyCaps[market] != 0) {\n revert SupplyCapIsNotZero();\n }\n\n if (_market.collateralFactorMantissa != 0) {\n revert CollateralFactorIsNotZero();\n }\n\n _market.isListed = false;\n emit MarketUnlisted(market);\n\n return NO_ERROR;\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 * @custom:event DelegateUpdated emits on success\n * @custom:error ZeroAddressNotAllowed is thrown when delegate address is zero\n * @custom:error DelegationStatusUnchanged is thrown if approval status is already set to the requested value\n * @custom:access Not restricted\n */\n function updateDelegate(address delegate, bool approved) external {\n ensureNonzeroAddress(delegate);\n if (approvedDelegates[msg.sender][delegate] == approved) {\n revert DelegationStatusUnchanged();\n }\n\n approvedDelegates[msg.sender][delegate] = approved;\n emit DelegateUpdated(msg.sender, delegate, approved);\n }\n\n /**\n * @notice Removes asset from sender's account liquidity calculation; disabling them as collateral\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event MarketExited is emitted on success\n * @custom:error ActionPaused error is thrown if exiting the market is paused\n * @custom:error NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function exitMarket(address vTokenAddress) external override returns (uint256) {\n _checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\n VToken vToken = VToken(vTokenAddress);\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\n (uint256 tokensHeld, uint256 amountOwed, ) = _safeGetAccountSnapshot(vToken, msg.sender);\n\n /* Fail if the sender has a borrow balance */\n if (amountOwed != 0) {\n revert NonzeroBorrowBalance();\n }\n\n /* Fail if the sender is not permitted to redeem all of their tokens */\n _checkRedeemAllowed(vTokenAddress, msg.sender, tokensHeld);\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 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 // load into memory for faster iteration\n VToken[] memory userAssetList = accountAssets[msg.sender];\n uint256 len = userAssetList.length;\n\n uint256 assetIndex = len;\n for (uint256 i; i < len; ++i) {\n if (userAssetList[i] == vToken) {\n assetIndex = i;\n break;\n }\n }\n\n // We *must* have found the asset in the list or our redundant data structure is broken\n assert(assetIndex < len);\n\n // copy last item in list to location of item to be removed, reduce length by 1\n VToken[] storage storedList = accountAssets[msg.sender];\n storedList[assetIndex] = storedList[storedList.length - 1];\n storedList.pop();\n\n emit MarketExited(vToken, msg.sender);\n\n return NO_ERROR;\n }\n\n /*** Policy Hooks ***/\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 * @custom:error ActionPaused error is thrown if supplying to this market is paused\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\n * @custom:access Not restricted\n */\n function preMintHook(address vToken, address minter, uint256 mintAmount) external override {\n _checkActionPauseState(vToken, Action.MINT);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n uint256 supplyCap = supplyCaps[vToken];\n // Skipping the cap check for uncapped coins to save some gas\n if (supplyCap != type(uint256).max) {\n uint256 vTokenSupply = VToken(vToken).totalSupply();\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\n if (nextTotalSupply > supplyCap) {\n revert SupplyCapExceeded(vToken, supplyCap);\n }\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, minter);\n }\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external override {\n _checkActionPauseState(vToken, Action.REDEEM);\n\n _checkRedeemAllowed(vToken, redeemer, redeemTokens);\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, redeemer);\n }\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 if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(redeemer, vToken);\n }\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 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 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 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 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 * @custom:error ActionPaused error is thrown if borrowing is paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if there is not enough collateral to borrow\n * @custom:error BorrowCapExceeded is thrown if the borrow cap will be exceeded should this borrow succeed\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted if vToken is enabled as collateral, otherwise only vToken\n */\n /// disable-eslint\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external override {\n _checkActionPauseState(vToken, Action.BORROW);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n if (!markets[vToken].accountMembership[borrower]) {\n // only vTokens may call borrowAllowed if borrower not in market\n _checkSenderIs(vToken);\n\n // attempt to add borrower to the market or revert\n _addToMarket(VToken(msg.sender), borrower);\n }\n\n // Update the prices of tokens\n updatePrices(borrower);\n\n if (oracle.getUnderlyingPrice(vToken) == 0) {\n revert PriceError(address(vToken));\n }\n\n uint256 borrowCap = borrowCaps[vToken];\n // Skipping the cap check for uncapped coins to save some gas\n if (borrowCap != type(uint256).max) {\n uint256 totalBorrows = VToken(vToken).totalBorrows();\n uint256 badDebt = VToken(vToken).badDebt();\n uint256 nextTotalBorrows = totalBorrows + borrowAmount + badDebt;\n if (nextTotalBorrows > borrowCap) {\n revert BorrowCapExceeded(vToken, borrowCap);\n }\n }\n\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n borrower,\n VToken(vToken),\n 0,\n borrowAmount,\n _getCollateralFactor\n );\n\n if (snapshot.shortfall > 0) {\n revert InsufficientLiquidity();\n }\n\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\n }\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 borrower The account which would borrowed the asset\n * @custom:error ActionPaused error is thrown if repayments are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:access Not restricted\n */\n function preRepayHook(address vToken, address borrower) external override {\n _checkActionPauseState(vToken, Action.REPAY);\n\n oracle.updatePrice(vToken);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\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 borrower The address of the borrower\n * @param repayAmount The amount of underlying being repaid\n * @param skipLiquidityCheck Allows the borrow to be liquidated regardless of the account liquidity\n * @custom:error ActionPaused error is thrown if liquidations are paused in this market\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\n * @custom:error TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor\n * @custom:error MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations\n * @custom:error InsufficientShortfall is thrown when trying to liquidate a healthy account\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n */\n function preLiquidateHook(\n address vTokenBorrowed,\n address vTokenCollateral,\n address borrower,\n uint256 repayAmount,\n bool skipLiquidityCheck\n ) external override {\n // Pause Action.LIQUIDATE on BORROWED TOKEN to prevent liquidating it.\n // If we want to pause liquidating to vTokenCollateral, we should pause\n // Action.SEIZE on it\n _checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\n\n // Update the prices of tokens\n updatePrices(borrower);\n\n if (!markets[vTokenBorrowed].isListed) {\n revert MarketNotListed(address(vTokenBorrowed));\n }\n if (!markets[vTokenCollateral].isListed) {\n revert MarketNotListed(address(vTokenCollateral));\n }\n\n uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\n\n /* Allow accounts to be liquidated if it is a forced liquidation */\n if (skipLiquidityCheck || isForcedLiquidationEnabled[vTokenBorrowed]) {\n if (repayAmount > borrowBalance) {\n revert TooMuchRepay();\n }\n return;\n }\n\n /* The borrower must have shortfall and collateral > threshold in order to be liquidatable */\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral <= minLiquidatableCollateral) {\n /* The liquidator should use either liquidateAccount or healAccount */\n revert MinimalCollateralViolated(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n /* The liquidator may not repay more than what is allowed by the closeFactor */\n uint256 maxClose = mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance);\n if (repayAmount > maxClose) {\n revert TooMuchRepay();\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 seizerContract Contract that tries to seize the asset (either borrowed vToken or Comptroller)\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @custom:error ActionPaused error is thrown if seizing this type of collateral is paused\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\n * @custom:error ComptrollerMismatch error is when seizer contract or seized asset belong to different pools\n * @custom:access Not restricted\n */\n function preSeizeHook(\n address vTokenCollateral,\n address seizerContract,\n address liquidator,\n address borrower\n ) external override {\n // Pause Action.SEIZE on COLLATERAL to prevent seizing it.\n // If we want to pause liquidating vTokenBorrowed, we should pause\n // Action.LIQUIDATE on it\n _checkActionPauseState(vTokenCollateral, Action.SEIZE);\n\n Market storage market = markets[vTokenCollateral];\n\n if (!market.isListed) {\n revert MarketNotListed(vTokenCollateral);\n }\n\n if (seizerContract == address(this)) {\n // If Comptroller is the seizer, just check if collateral's comptroller\n // is equal to the current address\n if (address(VToken(vTokenCollateral).comptroller()) != address(this)) {\n revert ComptrollerMismatch();\n }\n } else {\n // If the seizer is not the Comptroller, check that the seizer is a\n // listed market, and that the markets' comptrollers match\n if (!markets[seizerContract].isListed) {\n revert MarketNotListed(seizerContract);\n }\n if (VToken(vTokenCollateral).comptroller() != VToken(seizerContract).comptroller()) {\n revert ComptrollerMismatch();\n }\n }\n\n if (!market.accountMembership[borrower]) {\n revert MarketNotCollateral(vTokenCollateral, borrower);\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vTokenCollateral);\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, borrower);\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, liquidator);\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external override {\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 _checkRedeemAllowed(vToken, src, transferTokens);\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, src);\n rewardsDistributor.distributeSupplierRewardToken(vToken, dst);\n }\n }\n\n /*** Pool-level operations ***/\n\n /**\n * @notice Seizes all the remaining collateral, makes msg.sender repay the existing\n * borrows, and treats the rest of the debt as bad debt (for each market).\n * The sender has to repay a certain percentage of the debt, computed as\n * collateral / (borrows * liquidationIncentive).\n * @param user account to heal\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for healing\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function healAccount(address user) external {\n VToken[] memory userAssets = getAssetsIn(user);\n uint256 userAssetsCount = userAssets.length;\n\n address liquidator = msg.sender;\n {\n ResilientOracleInterface oracle_ = oracle;\n // We need all user's markets to be fresh for the computations to be correct\n for (uint256 i; i < userAssetsCount; ++i) {\n userAssets[i].accrueInterest();\n oracle_.updatePrice(address(userAssets[i]));\n }\n }\n\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(user, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n // percentage = collateral / (borrows * liquidation incentive)\n Exp memory collateral = Exp({ mantissa: snapshot.totalCollateral });\n Exp memory scaledBorrows = mul_(\n Exp({ mantissa: snapshot.borrows }),\n Exp({ mantissa: liquidationIncentiveMantissa })\n );\n\n Exp memory percentage = div_(collateral, scaledBorrows);\n if (lessThanExp(Exp({ mantissa: MANTISSA_ONE }), percentage)) {\n revert CollateralExceedsThreshold(scaledBorrows.mantissa, collateral.mantissa);\n }\n\n for (uint256 i; i < userAssetsCount; ++i) {\n VToken market = userAssets[i];\n\n (uint256 tokens, uint256 borrowBalance, ) = _safeGetAccountSnapshot(market, user);\n uint256 repaymentAmount = mul_ScalarTruncate(percentage, borrowBalance);\n\n // Seize the entire collateral\n if (tokens != 0) {\n market.seize(liquidator, user, tokens);\n }\n // Repay a certain percentage of the borrow, forgive the rest\n if (borrowBalance != 0) {\n market.healBorrow(liquidator, user, repaymentAmount);\n }\n }\n }\n\n /**\n * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than\n * a predefined threshold, and the account collateral can be seized to cover all borrows. If\n * the collateral is higher than the threshold, use regular liquidations. If the collateral is\n * below the threshold, and the account is insolvent, use healAccount.\n * @param borrower the borrower address\n * @param orders an array of liquidation orders\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation\n * @custom:error InsufficientCollateral error is thrown when there is not enough collateral to cover the debt\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function liquidateAccount(address borrower, LiquidationOrder[] calldata orders) external {\n // We will accrue interest and update the oracle prices later during the liquidation\n\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\n // You should use the regular vToken.liquidateBorrow(...) call\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n uint256 collateralToSeize = mul_ScalarTruncate(\n Exp({ mantissa: liquidationIncentiveMantissa }),\n snapshot.borrows\n );\n if (collateralToSeize >= snapshot.totalCollateral) {\n // There is not enough collateral to seize. Use healBorrow to repay some part of the borrow\n // and record bad debt.\n revert InsufficientCollateral(collateralToSeize, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n uint256 ordersCount = orders.length;\n\n _ensureMaxLoops(ordersCount / 2);\n\n for (uint256 i; i < ordersCount; ++i) {\n if (!markets[address(orders[i].vTokenBorrowed)].isListed) {\n revert MarketNotListed(address(orders[i].vTokenBorrowed));\n }\n if (!markets[address(orders[i].vTokenCollateral)].isListed) {\n revert MarketNotListed(address(orders[i].vTokenCollateral));\n }\n\n LiquidationOrder calldata order = orders[i];\n order.vTokenBorrowed.forceLiquidateBorrow(\n msg.sender,\n borrower,\n order.repayAmount,\n order.vTokenCollateral,\n true\n );\n }\n\n VToken[] memory borrowMarkets = getAssetsIn(borrower);\n uint256 marketsCount = borrowMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower);\n require(borrowBalance == 0, \"Nonzero borrow balance after liquidation\");\n }\n }\n\n /**\n * @notice Sets the closeFactor to use when liquidating borrows\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\n * @custom:event Emits NewCloseFactor on success\n * @custom:access Controlled by AccessControlManager\n */\n function setCloseFactor(uint256 newCloseFactorMantissa) external {\n _checkAccessAllowed(\"setCloseFactor(uint256)\");\n require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, \"Close factor greater than maximum close factor\");\n require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, \"Close factor smaller than minimum close factor\");\n\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\n closeFactorMantissa = newCloseFactorMantissa;\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\n }\n\n /**\n * @notice Sets the collateralFactor for a market\n * @dev This function is restricted by the AccessControlManager\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 * @custom:event Emits NewCollateralFactor when collateral factor is updated\n * and NewLiquidationThreshold when liquidation threshold is updated\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InvalidCollateralFactor error is thrown when collateral factor is too high\n * @custom:error InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor\n * @custom:error PriceError is thrown when the oracle returns an invalid price for the asset\n * @custom:access Controlled by AccessControlManager\n */\n function setCollateralFactor(\n VToken vToken,\n uint256 newCollateralFactorMantissa,\n uint256 newLiquidationThresholdMantissa\n ) external {\n _checkAccessAllowed(\"setCollateralFactor(address,uint256,uint256)\");\n\n // Verify market is listed\n Market storage market = markets[address(vToken)];\n if (!market.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n // Check collateral factor <= 0.9\n if (newCollateralFactorMantissa > MAX_COLLATERAL_FACTOR_MANTISSA) {\n revert InvalidCollateralFactor();\n }\n\n // Ensure that liquidation threshold <= 1\n if (newLiquidationThresholdMantissa > MANTISSA_ONE) {\n revert InvalidLiquidationThreshold();\n }\n\n // Ensure that liquidation threshold >= CF\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\n revert InvalidLiquidationThreshold();\n }\n\n // If collateral factor != 0, fail if price == 0\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\n revert PriceError(address(vToken));\n }\n\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\n market.collateralFactorMantissa = newCollateralFactorMantissa;\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\n }\n\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\n emit NewLiquidationThreshold(vToken, oldLiquidationThresholdMantissa, newLiquidationThresholdMantissa);\n }\n }\n\n /**\n * @notice Sets liquidationIncentive\n * @dev This function is restricted by the AccessControlManager\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\n * @custom:event Emits NewLiquidationIncentive on success\n * @custom:access Controlled by AccessControlManager\n */\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external {\n require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, \"liquidation incentive should be greater than 1e18\");\n\n _checkAccessAllowed(\"setLiquidationIncentive(uint256)\");\n\n // Save current value for use in log\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\n\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\n /**\n * @notice Add the market to the markets mapping and set it as listed\n * @dev Only callable by the PoolRegistry\n * @param vToken The address of the market (token) to list\n * @custom:error MarketAlreadyListed is thrown if the market is already listed in this pool\n * @custom:access Only PoolRegistry\n */\n function supportMarket(VToken vToken) external {\n _checkSenderIs(poolRegistry);\n\n if (markets[address(vToken)].isListed) {\n revert MarketAlreadyListed(address(vToken));\n }\n\n require(vToken.isVToken(), \"Comptroller: Invalid vToken\"); // Sanity check to make sure its really a VToken\n\n Market storage newMarket = markets[address(vToken)];\n newMarket.isListed = true;\n newMarket.collateralFactorMantissa = 0;\n newMarket.liquidationThresholdMantissa = 0;\n\n _addMarket(address(vToken));\n\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n rewardsDistributors[i].initializeMarket(address(vToken));\n }\n\n emit MarketSupported(vToken);\n }\n\n /**\n * @notice Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\n * @dev This function is restricted by the AccessControlManager\n * @dev A borrow cap of type(uint256).max corresponds to unlimited borrowing.\n * @dev Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed\n until the total borrows amount goes below the new borrow cap\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 type(uint256).max corresponds to unlimited borrowing.\n * @custom:access Controlled by AccessControlManager\n */\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\n _checkAccessAllowed(\"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 _ensureMaxLoops(numMarkets);\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 * @notice Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\n * @dev This function is restricted by the AccessControlManager\n * @dev A supply cap of type(uint256).max corresponds to unlimited supply.\n * @dev Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed\n until the total supplies amount goes below the new supply cap\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 type(uint256).max corresponds to unlimited supply.\n * @custom:access Controlled by AccessControlManager\n */\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\n _checkAccessAllowed(\"setMarketSupplyCaps(address[],uint256[])\");\n uint256 vTokensCount = vTokens.length;\n\n require(vTokensCount != 0, \"invalid number of markets\");\n require(vTokensCount == newSupplyCaps.length, \"invalid number of markets\");\n\n _ensureMaxLoops(vTokensCount);\n\n for (uint256 i; i < vTokensCount; ++i) {\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\n }\n }\n\n /**\n * @notice Pause/unpause specified actions\n * @dev This function is restricted by the AccessControlManager\n * @param marketsList Markets to pause/unpause the actions on\n * @param actionsList List of action ids to pause/unpause\n * @param paused The new paused state (true=paused, false=unpaused)\n * @custom:access Controlled by AccessControlManager\n */\n function setActionsPaused(VToken[] calldata marketsList, Action[] calldata actionsList, bool paused) external {\n _checkAccessAllowed(\"setActionsPaused(address[],uint256[],bool)\");\n\n uint256 marketsCount = marketsList.length;\n uint256 actionsCount = actionsList.length;\n\n _ensureMaxLoops(marketsCount * actionsCount);\n\n for (uint256 marketIdx; marketIdx < marketsCount; ++marketIdx) {\n for (uint256 actionIdx; actionIdx < actionsCount; ++actionIdx) {\n _setActionPaused(address(marketsList[marketIdx]), actionsList[actionIdx], paused);\n }\n }\n }\n\n /**\n * @notice Set the given collateral threshold for non-batch liquidations. Regular liquidations\n * will fail if the collateral amount is less than this threshold. Liquidators should use batch\n * operations like liquidateAccount or healAccount.\n * @dev This function is restricted by the AccessControlManager\n * @param newMinLiquidatableCollateral The new min liquidatable collateral (in USD).\n * @custom:access Controlled by AccessControlManager\n */\n function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external {\n _checkAccessAllowed(\"setMinLiquidatableCollateral(uint256)\");\n\n uint256 oldMinLiquidatableCollateral = minLiquidatableCollateral;\n minLiquidatableCollateral = newMinLiquidatableCollateral;\n emit NewMinLiquidatableCollateral(oldMinLiquidatableCollateral, newMinLiquidatableCollateral);\n }\n\n /**\n * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor\n * contracts with the same rewardToken, and there could be overlaping among them considering the last reward slot (block or second)\n * @dev Only callable by the admin\n * @param _rewardsDistributor Address of the RewardDistributor contract to add\n * @custom:access Only Governance\n * @custom:event Emits NewRewardsDistributor with distributor address\n */\n function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner {\n require(!rewardsDistributorExists[address(_rewardsDistributor)], \"already exists\");\n\n uint256 rewardsDistributorsLen = rewardsDistributors.length;\n _ensureMaxLoops(rewardsDistributorsLen + 1);\n\n rewardsDistributors.push(_rewardsDistributor);\n rewardsDistributorExists[address(_rewardsDistributor)] = true;\n\n uint256 marketsCount = allMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n _rewardsDistributor.initializeMarket(address(allMarkets[i]));\n }\n\n emit NewRewardsDistributor(address(_rewardsDistributor), address(_rewardsDistributor.rewardToken()));\n }\n\n /**\n * @notice Sets a new price oracle for the Comptroller\n * @dev Only callable by the admin\n * @param newOracle Address of the new price oracle to set\n * @custom:event Emits NewPriceOracle on success\n * @custom:error ZeroAddressNotAllowed is thrown when the new oracle address is zero\n */\n function setPriceOracle(ResilientOracleInterface newOracle) external onlyOwner {\n ensureNonzeroAddress(address(newOracle));\n\n ResilientOracleInterface oldOracle = oracle;\n oracle = newOracle;\n emit NewPriceOracle(oldOracle, newOracle);\n }\n\n /**\n * @notice Set the for loop iteration limit to avoid DOS\n * @param limit Limit for the max loops can execute at a time\n */\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\n _setMaxLoopsLimit(limit);\n }\n\n /**\n * @notice Sets the prime token contract for the comptroller\n * @param _prime Address of the Prime contract\n */\n function setPrimeToken(IPrime _prime) external onlyOwner {\n ensureNonzeroAddress(address(_prime));\n\n emit NewPrimeToken(prime, _prime);\n prime = _prime;\n }\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 * @param vTokenBorrowed Borrowed vToken\n * @param enable Whether to enable forced liquidations\n */\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\n _checkAccessAllowed(\"setForcedLiquidation(address,bool)\");\n ensureNonzeroAddress(vTokenBorrowed);\n\n if (!markets[vTokenBorrowed].isListed) {\n revert MarketNotListed(vTokenBorrowed);\n }\n\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\n }\n\n /**\n * @notice Determine the current account liquidity with respect to liquidation threshold requirements\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\n * @param account The account get liquidity for\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Account liquidity in excess of liquidation threshold requirements,\n * @return shortfall Account shortfall below liquidation threshold requirements\n */\n function getAccountLiquidity(\n address account\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getLiquidationThreshold);\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\n }\n\n /**\n * @notice Determine the current account liquidity with respect to collateral requirements\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\n * @param account The account get liquidity for\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Account liquidity in excess of collateral requirements,\n * @return shortfall Account shortfall below collateral requirements\n */\n function getBorrowingPower(\n address account\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getCollateralFactor);\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\n }\n\n /**\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Hypothetical account liquidity in excess of collateral requirements,\n * @return shortfall 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 error, uint256 liquidity, uint256 shortfall) {\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n account,\n VToken(vTokenModify),\n redeemTokens,\n borrowAmount,\n _getCollateralFactor\n );\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\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 markets The list of market addresses\n */\n function getAllMarkets() external view override returns (VToken[] memory) {\n return allMarkets;\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 /*** Assets You Are In ***/\n\n /**\n * @notice Returns whether the given account is entered in a given market\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 market specified, 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 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 error Always NO_ERROR for compatibility with Venus core tooling\n * @return tokensToSeize Number of vTokenCollateral tokens to be seized in a liquidation\n * @custom:error PriceError if the oracle returns an invalid price\n */\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view override returns (uint256 error, uint256 tokensToSeize) {\n /* Read oracle prices for borrowed and collateral markets */\n uint256 priceBorrowedMantissa = _safeGetUnderlyingPrice(VToken(vTokenBorrowed));\n uint256 priceCollateralMantissa = _safeGetUnderlyingPrice(VToken(vTokenCollateral));\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 uint256 exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\n uint256 seizeTokens;\n Exp memory numerator;\n Exp memory denominator;\n Exp memory ratio;\n\n numerator = mul_(Exp({ mantissa: liquidationIncentiveMantissa }), Exp({ mantissa: priceBorrowedMantissa }));\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\n ratio = div_(numerator, denominator);\n\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\n\n return (NO_ERROR, seizeTokens);\n }\n\n /**\n * @notice Returns reward speed given a vToken\n * @param vToken The vToken to get the reward speeds for\n * @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors\n */\n function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {\n uint256 rewardsDistributorsLength = rewardsDistributors.length;\n rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);\n for (uint256 i; i < rewardsDistributorsLength; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n address rewardToken = address(rewardsDistributor.rewardToken());\n rewardSpeeds[i] = RewardSpeeds({\n rewardToken: rewardToken,\n supplySpeed: rewardsDistributor.rewardTokenSupplySpeeds(vToken),\n borrowSpeed: rewardsDistributor.rewardTokenBorrowSpeeds(vToken)\n });\n }\n return rewardSpeeds;\n }\n\n /**\n * @notice Return all reward distributors for this pool\n * @return Array of RewardDistributor addresses\n */\n function getRewardDistributors() external view returns (RewardsDistributor[] memory) {\n return rewardsDistributors;\n }\n\n /**\n * @notice A marker method that returns true for a valid Comptroller contract\n * @return Always true\n */\n function isComptroller() external pure override returns (bool) {\n return true;\n }\n\n /**\n * @notice Update the prices of all the tokens associated with the provided account\n * @param account Address of the account to get associated tokens with\n */\n function updatePrices(address account) public {\n VToken[] memory vTokens = getAssetsIn(account);\n uint256 vTokensCount = vTokens.length;\n\n ResilientOracleInterface oracle_ = oracle;\n\n for (uint256 i; i < vTokensCount; ++i) {\n oracle_.updatePrice(address(vTokens[i]));\n }\n }\n\n /**\n * @notice Checks if a certain action is paused on a market\n * @param market vToken address\n * @param action Action to check\n * @return paused True if the action is paused otherwise false\n */\n function actionPaused(address market, Action action) public view returns (bool) {\n return _actionPaused[market][action];\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 list with the assets the account has entered\n */\n function getAssetsIn(address account) public 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 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 */\n function _addToMarket(VToken vToken, address borrower) internal {\n _checkActionPauseState(address(vToken), Action.ENTER_MARKET);\n Market storage marketToJoin = markets[address(vToken)];\n\n if (!marketToJoin.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n if (marketToJoin.accountMembership[borrower]) {\n // already joined\n return;\n }\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\n /**\n * @notice Internal function to validate that a market hasn't already been added\n * and if it hasn't adds it\n * @param vToken The market to support\n */\n function _addMarket(address vToken) internal {\n uint256 marketsCount = allMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n if (allMarkets[i] == VToken(vToken)) {\n revert MarketAlreadyListed(vToken);\n }\n }\n allMarkets.push(VToken(vToken));\n marketsCount = allMarkets.length;\n _ensureMaxLoops(marketsCount);\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 _setActionPaused(address market, Action action, bool paused) internal {\n require(markets[market].isListed, \"cannot pause a market that is not listed\");\n _actionPaused[market][action] = paused;\n emit ActionPausedMarket(VToken(market), action, paused);\n }\n\n /**\n * @dev Internal function to check that vTokens can be safely redeemed for the underlying asset.\n * @param vToken Address of the vTokens to redeem\n * @param redeemer Account redeeming the tokens\n * @param redeemTokens The number of tokens to redeem\n */\n function _checkRedeemAllowed(address vToken, address redeemer, uint256 redeemTokens) internal {\n Market storage market = markets[vToken];\n\n if (!market.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\n if (!market.accountMembership[redeemer]) {\n return;\n }\n\n // Update the prices of tokens\n updatePrices(redeemer);\n\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n redeemer,\n VToken(vToken),\n redeemTokens,\n 0,\n _getCollateralFactor\n );\n if (snapshot.shortfall > 0) {\n revert InsufficientLiquidity();\n }\n }\n\n /**\n * @notice Get the total collateral, weighted collateral, borrow balance, liquidity, shortfall\n * @param account The account to get the snapshot for\n * @param weight The function to compute the weight of the collateral – either collateral factor or\n * liquidation threshold. Accepts the address of the vToken and returns the weight as Exp.\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\n * without calculating accumulated interest.\n * @return snapshot Account liquidity snapshot\n */\n function _getCurrentLiquiditySnapshot(\n address account,\n function(VToken) internal view returns (Exp memory) weight\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\n return _getHypotheticalLiquiditySnapshot(account, VToken(address(0)), 0, 0, weight);\n }\n\n /**\n * @notice Determine what the supply/borrow balances 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 weight The function to compute the weight of the collateral – either collateral factor or\n liquidation threshold. Accepts the address of the VToken and returns the weight\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\n * without calculating accumulated interest.\n * @return snapshot Account liquidity snapshot\n */\n function _getHypotheticalLiquiditySnapshot(\n address account,\n VToken vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount,\n function(VToken) internal view returns (Exp memory) weight\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\n // For each asset the account is in\n VToken[] memory assets = getAssetsIn(account);\n uint256 assetsCount = assets.length;\n\n for (uint256 i; i < assetsCount; ++i) {\n VToken asset = assets[i];\n\n // Read the balances and exchange rate from the vToken\n (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) = _safeGetAccountSnapshot(\n asset,\n account\n );\n\n // Get the normalized price of the asset\n Exp memory oraclePrice = Exp({ mantissa: _safeGetUnderlyingPrice(asset) });\n\n // Pre-compute conversion factors from vTokens -> usd\n Exp memory vTokenPrice = mul_(Exp({ mantissa: exchangeRateMantissa }), oraclePrice);\n Exp memory weightedVTokenPrice = mul_(weight(asset), vTokenPrice);\n\n // weightedCollateral += weightedVTokenPrice * vTokenBalance\n snapshot.weightedCollateral = mul_ScalarTruncateAddUInt(\n weightedVTokenPrice,\n vTokenBalance,\n snapshot.weightedCollateral\n );\n\n // totalCollateral += vTokenPrice * vTokenBalance\n snapshot.totalCollateral = mul_ScalarTruncateAddUInt(vTokenPrice, vTokenBalance, snapshot.totalCollateral);\n\n // borrows += oraclePrice * borrowBalance\n snapshot.borrows = mul_ScalarTruncateAddUInt(oraclePrice, borrowBalance, snapshot.borrows);\n\n // Calculate effects of interacting with vTokenModify\n if (asset == vTokenModify) {\n // redeem effect\n // effects += tokensToDenom * redeemTokens\n snapshot.effects = mul_ScalarTruncateAddUInt(weightedVTokenPrice, redeemTokens, snapshot.effects);\n\n // borrow effect\n // effects += oraclePrice * borrowAmount\n snapshot.effects = mul_ScalarTruncateAddUInt(oraclePrice, borrowAmount, snapshot.effects);\n }\n }\n\n uint256 borrowPlusEffects = snapshot.borrows + snapshot.effects;\n // These are safe, as the underflow condition is checked first\n unchecked {\n if (snapshot.weightedCollateral > borrowPlusEffects) {\n snapshot.liquidity = snapshot.weightedCollateral - borrowPlusEffects;\n snapshot.shortfall = 0;\n } else {\n snapshot.liquidity = 0;\n snapshot.shortfall = borrowPlusEffects - snapshot.weightedCollateral;\n }\n }\n\n return snapshot;\n }\n\n /**\n * @dev Retrieves price from oracle for an asset and checks it is nonzero\n * @param asset Address for asset to query price\n * @return Underlying price\n */\n function _safeGetUnderlyingPrice(VToken asset) internal view returns (uint256) {\n uint256 oraclePriceMantissa = oracle.getUnderlyingPrice(address(asset));\n if (oraclePriceMantissa == 0) {\n revert PriceError(address(asset));\n }\n return oraclePriceMantissa;\n }\n\n /**\n * @dev Return collateral factor for a market\n * @param asset Address for asset\n * @return Collateral factor as exponential\n */\n function _getCollateralFactor(VToken asset) internal view returns (Exp memory) {\n return Exp({ mantissa: markets[address(asset)].collateralFactorMantissa });\n }\n\n /**\n * @dev Retrieves liquidation threshold for a market as an exponential\n * @param asset Address for asset to liquidation threshold\n * @return Liquidation threshold as exponential\n */\n function _getLiquidationThreshold(VToken asset) internal view returns (Exp memory) {\n return Exp({ mantissa: markets[address(asset)].liquidationThresholdMantissa });\n }\n\n /**\n * @dev Returns supply and borrow balances of user in vToken, reverts on failure\n * @param vToken Market to query\n * @param user Account address\n * @return vTokenBalance Balance of vTokens, the same as vToken.balanceOf(user)\n * @return borrowBalance Borrowed amount, including the interest\n * @return exchangeRateMantissa Stored exchange rate\n */\n function _safeGetAccountSnapshot(\n VToken vToken,\n address user\n ) internal view returns (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) {\n uint256 err;\n (err, vTokenBalance, borrowBalance, exchangeRateMantissa) = vToken.getAccountSnapshot(user);\n if (err != 0) {\n revert SnapshotError(address(vToken), user);\n }\n return (vTokenBalance, borrowBalance, exchangeRateMantissa);\n }\n\n /// @notice Reverts if the call is not from expectedSender\n /// @param expectedSender Expected transaction sender\n function _checkSenderIs(address expectedSender) internal view {\n if (msg.sender != expectedSender) {\n revert UnexpectedSender(expectedSender, msg.sender);\n }\n }\n\n /// @notice Reverts if a certain action is paused on a market\n /// @param market Market to check\n /// @param action Action to check\n function _checkActionPauseState(address market, Action action) private view {\n if (actionPaused(market, action)) {\n revert ActionPaused(market, action);\n }\n }\n}\n" + }, + "contracts/ComptrollerInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.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\n/**\n * @title ComptrollerInterface\n * @author Venus\n * @notice Interface implemented by the `Comptroller` contract.\n */\ninterface ComptrollerInterface {\n /*** Assets You Are In ***/\n\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\n\n function exitMarket(address vToken) external returns (uint256);\n\n /*** Policy Hooks ***/\n\n function preMintHook(address vToken, address minter, uint256 mintAmount) external;\n\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external;\n\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external;\n\n function preRepayHook(address vToken, address borrower) external;\n\n function preLiquidateHook(\n address vTokenBorrowed,\n address vTokenCollateral,\n address borrower,\n uint256 repayAmount,\n bool skipLiquidityCheck\n ) external;\n\n function preSeizeHook(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower\n ) external;\n\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\n\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\n\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\n\n function repayBorrowVerify(\n address vToken,\n address payer,\n address borrower,\n uint repayAmount,\n uint borrowerIndex\n ) external;\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 seizeVerify(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint seizeTokens\n ) external;\n\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\n\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external;\n\n function isComptroller() external view returns (bool);\n\n /*** Liquidity/Liquidation Calculations ***/\n\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 repayAmount\n ) external view returns (uint256, uint256);\n\n function getAllMarkets() external view returns (VToken[] memory);\n\n function actionPaused(address market, Action action) external view returns (bool);\n}\n\n/**\n * @title ComptrollerViewInterface\n * @author Venus\n * @notice Interface implemented by the `Comptroller` contract, including only some util view functions.\n */\ninterface ComptrollerViewInterface {\n function markets(address) external view returns (bool, uint256);\n\n function oracle() external view returns (ResilientOracleInterface);\n\n function getAssetsIn(address) external view returns (VToken[] memory);\n\n function closeFactorMantissa() external view returns (uint256);\n\n function liquidationIncentiveMantissa() external view returns (uint256);\n\n function minLiquidatableCollateral() external view returns (uint256);\n\n function getRewardDistributors() external view returns (RewardsDistributor[] memory);\n\n function getAllMarkets() external view returns (VToken[] memory);\n\n function borrowCaps(address) external view returns (uint256);\n\n function supplyCaps(address) external view returns (uint256);\n\n function approvedDelegates(address user, address delegate) external view returns (bool);\n}\n" + }, + "contracts/ComptrollerStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.sol\";\nimport { IPrime } from \"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\";\nimport { Action } from \"./ComptrollerInterface.sol\";\n\n/**\n * @title ComptrollerStorage\n * @author Venus\n * @notice Storage layout for the `Comptroller` contract.\n */\ncontract ComptrollerStorage {\n struct LiquidationOrder {\n VToken vTokenCollateral;\n VToken vTokenBorrowed;\n uint256 repayAmount;\n }\n\n struct AccountLiquiditySnapshot {\n uint256 totalCollateral;\n uint256 weightedCollateral;\n uint256 borrows;\n uint256 effects;\n uint256 liquidity;\n uint256 shortfall;\n }\n\n struct RewardSpeeds {\n address rewardToken;\n uint256 supplySpeed;\n uint256 borrowSpeed;\n }\n\n struct Market {\n // Whether or not this market is listed\n bool isListed;\n // 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 uint256 collateralFactorMantissa;\n // 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 uint256 liquidationThresholdMantissa;\n // Per-market mapping of \"accounts in this asset\"\n mapping(address => bool) accountMembership;\n }\n\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 Per-account mapping of \"assets you are in\"\n */\n mapping(address => VToken[]) public accountAssets;\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 /// @notice A list of all markets\n VToken[] public allMarkets;\n\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\n mapping(address => uint256) public borrowCaps;\n\n /// @notice Minimal collateral required for regular (non-batch) liquidations\n uint256 public minLiquidatableCollateral;\n\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\n mapping(address => uint256) public supplyCaps;\n\n /// @notice True if a certain action is paused on a certain market\n mapping(address => mapping(Action => bool)) internal _actionPaused;\n\n // List of Reward Distributors added\n RewardsDistributor[] internal rewardsDistributors;\n\n // Used to check if rewards distributor is added\n mapping(address => bool) internal rewardsDistributorExists;\n\n /// @notice Flag indicating whether forced liquidation enabled for a market\n mapping(address => bool) public isForcedLiquidationEnabled;\n\n uint256 internal constant NO_ERROR = 0;\n\n // closeFactorMantissa must be strictly greater than this value\n uint256 internal constant MIN_CLOSE_FACTOR_MANTISSA = 0.05e18; // 0.05\n\n // closeFactorMantissa must not exceed this value\n uint256 internal constant MAX_CLOSE_FACTOR_MANTISSA = 0.9e18; // 0.9\n\n // No collateralFactorMantissa may exceed this value\n uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.95e18; // 0.95\n\n /// Prime token address\n IPrime public prime;\n\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 /**\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[47] private __gap;\n}\n" + }, + "contracts/ErrorReporter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n/**\n * @title TokenErrorReporter\n * @author Venus\n * @notice Errors that can be thrown by the `VToken` contract.\n */\ncontract TokenErrorReporter {\n uint256 public constant NO_ERROR = 0; // support legacy return codes\n\n error TransferNotAllowed();\n\n error MintFreshnessCheck();\n\n error RedeemFreshnessCheck();\n error RedeemTransferOutNotPossible();\n\n error BorrowFreshnessCheck();\n error BorrowCashNotAvailable();\n error DelegateNotApproved();\n\n error RepayBorrowFreshnessCheck();\n\n error HealBorrowUnauthorized();\n error ForceLiquidateBorrowUnauthorized();\n\n error LiquidateFreshnessCheck();\n error LiquidateCollateralFreshnessCheck();\n error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\n error LiquidateLiquidatorIsBorrower();\n error LiquidateCloseAmountIsZero();\n error LiquidateCloseAmountIsUintMax();\n\n error LiquidateSeizeLiquidatorIsBorrower();\n\n error ProtocolSeizeShareTooBig();\n\n error SetReserveFactorFreshCheck();\n error SetReserveFactorBoundsCheck();\n\n error AddReservesFactorFreshCheck(uint256 actualAddAmount);\n\n error ReduceReservesFreshCheck();\n error ReduceReservesCashNotAvailable();\n error ReduceReservesCashValidation();\n\n error SetInterestRateModelFreshCheck();\n}\n" + }, + "contracts/ExponentialNoError.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from \"./lib/constants.sol\";\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 struct Exp {\n uint256 mantissa;\n }\n\n struct Double {\n uint256 mantissa;\n }\n\n uint256 internal constant EXP_SCALE = EXP_SCALE_;\n uint256 internal constant DOUBLE_SCALE = 1e36;\n uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;\n uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;\n\n /**\n * @dev Truncates the given exp to a whole number value.\n * For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15\n */\n function truncate(Exp memory exp) internal pure returns (uint256) {\n // Note: We are not using careful math here as we're performing a division that cannot fail\n return exp.mantissa / EXP_SCALE;\n }\n\n /**\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\n */\n // solhint-disable-next-line func-name-mixedcase\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\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 // solhint-disable-next-line func-name-mixedcase\n function mul_ScalarTruncateAddUInt(Exp memory a, uint256 scalar, uint256 addend) internal pure returns (uint256) {\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 function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\n require(n <= type(uint224).max, errorMessage);\n return uint224(n);\n }\n\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\n require(n <= type(uint32).max, 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_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a + b;\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_(uint256 a, uint256 b) internal pure returns (uint256) {\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) / EXP_SCALE });\n }\n\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\n return Exp({ mantissa: mul_(a.mantissa, b) });\n }\n\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\n return mul_(a, b.mantissa) / EXP_SCALE;\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) / DOUBLE_SCALE });\n }\n\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: mul_(a.mantissa, b) });\n }\n\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\n return mul_(a, b.mantissa) / DOUBLE_SCALE;\n }\n\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a * b;\n }\n\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });\n }\n\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\n return Exp({ mantissa: div_(a.mantissa, b) });\n }\n\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\n return div_(mul_(a, EXP_SCALE), 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, DOUBLE_SCALE), b.mantissa) });\n }\n\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(a.mantissa, b) });\n }\n\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\n return div_(mul_(a, DOUBLE_SCALE), b.mantissa);\n }\n\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a / b;\n }\n\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });\n }\n}\n" + }, + "contracts/InterestRateModel.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n/**\n * @title Compound's InterestRateModel Interface\n * @author Compound\n */\nabstract contract InterestRateModel {\n /**\n * @notice Calculates the current borrow interest rate per slot (block or second)\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 amount of reserves the market has\n * @param badDebt The amount of badDebt in the market\n * @return The borrow rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\n */\n function getBorrowRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) external view virtual returns (uint256);\n\n /**\n * @notice Calculates the current supply interest rate per slot (block or second)\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 amount of reserves the market has\n * @param reserveFactorMantissa The current reserve factor the market has\n * @param badDebt The amount of badDebt in the market\n * @return The supply rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\n */\n function getSupplyRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 reserveFactorMantissa,\n uint256 badDebt\n ) external view virtual returns (uint256);\n\n /**\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\n * @return Always true\n */\n function isInterestRateModel() external pure virtual returns (bool) {\n return true;\n }\n}\n" + }, + "contracts/Lens/PoolLens.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IERC20Metadata } from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { ExponentialNoError } from \"../ExponentialNoError.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { Action, ComptrollerInterface, ComptrollerViewInterface } from \"../ComptrollerInterface.sol\";\nimport { PoolRegistryInterface } from \"../Pool/PoolRegistryInterface.sol\";\nimport { PoolRegistry } from \"../Pool/PoolRegistry.sol\";\nimport { RewardsDistributor } from \"../Rewards/RewardsDistributor.sol\";\nimport { TimeManagerV8 } from \"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\";\n\n/**\n * @title PoolLens\n * @author Venus\n * @notice The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information\n * for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be\n * looked up for specific pools and markets:\n- the vToken balance of a given user;\n- the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address;\n- the vToken address in a pool for a given asset;\n- a list of all pools that support an asset;\n- the underlying asset price of a vToken;\n- the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\n */\ncontract PoolLens is ExponentialNoError, TimeManagerV8 {\n /**\n * @dev Struct for PoolDetails.\n */\n struct PoolData {\n string name;\n address creator;\n address comptroller;\n uint256 blockPosted;\n uint256 timestampPosted;\n string category;\n string logoURL;\n string description;\n address priceOracle;\n uint256 closeFactor;\n uint256 liquidationIncentive;\n uint256 minLiquidatableCollateral;\n VTokenMetadata[] vTokens;\n }\n\n /**\n * @dev Struct for VToken.\n */\n struct VTokenMetadata {\n address vToken;\n uint256 exchangeRateCurrent;\n uint256 supplyRatePerBlockOrTimestamp;\n uint256 borrowRatePerBlockOrTimestamp;\n uint256 reserveFactorMantissa;\n uint256 supplyCaps;\n uint256 borrowCaps;\n uint256 totalBorrows;\n uint256 totalReserves;\n uint256 totalSupply;\n uint256 totalCash;\n bool isListed;\n uint256 collateralFactorMantissa;\n address underlyingAssetAddress;\n uint256 vTokenDecimals;\n uint256 underlyingDecimals;\n uint256 pausedActions;\n }\n\n /**\n * @dev Struct for VTokenBalance.\n */\n struct VTokenBalances {\n address vToken;\n uint256 balanceOf;\n uint256 borrowBalanceCurrent;\n uint256 balanceOfUnderlying;\n uint256 tokenBalance;\n uint256 tokenAllowance;\n }\n\n /**\n * @dev Struct for underlyingPrice of VToken.\n */\n struct VTokenUnderlyingPrice {\n address vToken;\n uint256 underlyingPrice;\n }\n\n /**\n * @dev Struct with pending reward info for a market.\n */\n struct PendingReward {\n address vTokenAddress;\n uint256 amount;\n }\n\n /**\n * @dev Struct with reward distribution totals for a single reward token and distributor.\n */\n struct RewardSummary {\n address distributorAddress;\n address rewardTokenAddress;\n uint256 totalRewards;\n PendingReward[] pendingRewards;\n }\n\n /**\n * @dev Struct used in RewardDistributor to save last updated market state.\n */\n struct RewardTokenState {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block number or timestamp the index was last updated at\n uint256 blockOrTimestamp;\n // The block number or timestamp at which to stop rewards\n uint256 lastRewardingBlockOrTimestamp;\n }\n\n /**\n * @dev Struct with bad debt of a market denominated\n */\n struct BadDebt {\n address vTokenAddress;\n uint256 badDebtUsd;\n }\n\n /**\n * @dev Struct with bad debt total denominated in usd for a pool and an array of BadDebt structs for each market\n */\n struct BadDebtSummary {\n address comptroller;\n uint256 totalBadDebtUsd;\n BadDebt[] badDebts;\n }\n\n /// @notice Address of the core pool comptroller (all markets are returned for this pool, including paused ones)\n address public immutable corePoolComptroller;\n\n /**\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\n * @param blocksPerYear_ The number of blocks per year\n * @param corePoolComptroller_ The address of the core pool comptroller\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor(\n bool timeBased_,\n uint256 blocksPerYear_,\n address corePoolComptroller_\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\n corePoolComptroller = corePoolComptroller_;\n }\n\n /**\n * @notice Queries the user's supply/borrow balances in vTokens\n * @param vTokens The list of vToken addresses\n * @param account The user Account\n * @return A list of structs containing balances data\n */\n function vTokenBalancesAll(VToken[] calldata vTokens, address account) external returns (VTokenBalances[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenBalances[] memory res = new VTokenBalances[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenBalances(vTokens[i], account);\n }\n return res;\n }\n\n /**\n * @notice Queries all pools with addtional details for each of them\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @return Arrays of all Venus pools' data\n */\n function getAllPools(address poolRegistryAddress) external view returns (PoolData[] memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n PoolRegistry.VenusPool[] memory venusPools = poolRegistryInterface.getAllPools();\n uint256 poolLength = venusPools.length;\n\n PoolData[] memory poolDataItems = new PoolData[](poolLength);\n\n for (uint256 i; i < poolLength; ++i) {\n PoolRegistry.VenusPool memory venusPool = venusPools[i];\n PoolData memory poolData = getPoolDataFromVenusPool(poolRegistryAddress, venusPool);\n poolDataItems[i] = poolData;\n }\n\n return poolDataItems;\n }\n\n /**\n * @notice Queries the details of a pool identified by Comptroller address\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param comptroller The Comptroller implementation address\n * @return PoolData structure containing the details of the pool\n */\n function getPoolByComptroller(\n address poolRegistryAddress,\n address comptroller\n ) external view returns (PoolData memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return getPoolDataFromVenusPool(poolRegistryAddress, poolRegistryInterface.getPoolByComptroller(comptroller));\n }\n\n /**\n * @notice Returns vToken holding the specified underlying asset in the specified pool\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param comptroller The pool comptroller\n * @param asset The underlyingAsset of VToken\n * @return Address of the vToken\n */\n function getVTokenForAsset(\n address poolRegistryAddress,\n address comptroller,\n address asset\n ) external view returns (address) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return poolRegistryInterface.getVTokenForAsset(comptroller, asset);\n }\n\n /**\n * @notice Returns all pools that support the specified underlying asset\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param asset The underlying asset of vToken\n * @return A list of Comptroller contracts\n */\n function getPoolsSupportedByAsset(\n address poolRegistryAddress,\n address asset\n ) external view returns (address[] memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return poolRegistryInterface.getPoolsSupportedByAsset(asset);\n }\n\n /**\n * @notice Returns the price data for the underlying assets of the specified vTokens\n * @param vTokens The list of vToken addresses\n * @return An array containing the price data for each asset\n */\n function vTokenUnderlyingPriceAll(\n VToken[] calldata vTokens\n ) external view returns (VTokenUnderlyingPrice[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenUnderlyingPrice[] memory res = new VTokenUnderlyingPrice[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenUnderlyingPrice(vTokens[i]);\n }\n return res;\n }\n\n /**\n * @notice Returns the pending rewards for a user for a given pool.\n * @param account The user account.\n * @param comptrollerAddress address\n * @return Pending rewards array\n */\n function getPendingRewards(\n address account,\n address comptrollerAddress\n ) external view returns (RewardSummary[] memory) {\n VToken[] memory markets = _getMarkets(ComptrollerInterface(comptrollerAddress));\n RewardsDistributor[] memory rewardsDistributors = ComptrollerViewInterface(comptrollerAddress)\n .getRewardDistributors();\n RewardSummary[] memory rewardSummary = new RewardSummary[](rewardsDistributors.length);\n for (uint256 i; i < rewardsDistributors.length; ++i) {\n RewardSummary memory reward;\n reward.distributorAddress = address(rewardsDistributors[i]);\n reward.rewardTokenAddress = address(rewardsDistributors[i].rewardToken());\n reward.totalRewards = rewardsDistributors[i].rewardTokenAccrued(account);\n reward.pendingRewards = _calculateNotDistributedAwards(account, markets, rewardsDistributors[i]);\n rewardSummary[i] = reward;\n }\n return rewardSummary;\n }\n\n /**\n * @notice Returns a summary of a pool's bad debt broken down by market\n *\n * @param comptrollerAddress Address of the comptroller\n *\n * @return badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and\n * a break down of bad debt by market\n */\n function getPoolBadDebt(address comptrollerAddress) external view returns (BadDebtSummary memory) {\n uint256 totalBadDebtUsd;\n\n // Get every listed market in the pool\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\n VToken[] memory markets = _getMarkets(ComptrollerInterface(comptrollerAddress));\n ResilientOracleInterface priceOracle = comptroller.oracle();\n\n BadDebt[] memory badDebts = new BadDebt[](markets.length);\n\n BadDebtSummary memory badDebtSummary;\n badDebtSummary.comptroller = comptrollerAddress;\n badDebtSummary.badDebts = badDebts;\n\n // // Calculate the bad debt is USD per market\n for (uint256 i; i < markets.length; ++i) {\n BadDebt memory badDebt;\n badDebt.vTokenAddress = address(markets[i]);\n badDebt.badDebtUsd =\n (VToken(address(markets[i])).badDebt() * priceOracle.getUnderlyingPrice(address(markets[i]))) /\n EXP_SCALE;\n badDebtSummary.badDebts[i] = badDebt;\n totalBadDebtUsd = totalBadDebtUsd + badDebt.badDebtUsd;\n }\n\n badDebtSummary.totalBadDebtUsd = totalBadDebtUsd;\n\n return badDebtSummary;\n }\n\n /**\n * @notice Queries the user's supply/borrow balances in the specified vToken\n * @param vToken vToken address\n * @param account The user Account\n * @return A struct containing the balances data\n */\n function vTokenBalances(VToken vToken, address account) public returns (VTokenBalances memory) {\n uint256 balanceOf = vToken.balanceOf(account);\n uint256 borrowBalanceCurrent = vToken.borrowBalanceCurrent(account);\n uint256 balanceOfUnderlying = vToken.balanceOfUnderlying(account);\n uint256 tokenBalance;\n uint256 tokenAllowance;\n\n IERC20 underlying = IERC20(vToken.underlying());\n tokenBalance = underlying.balanceOf(account);\n tokenAllowance = underlying.allowance(account, address(vToken));\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 Queries additional information for the pool\n * @param poolRegistryAddress Address of the PoolRegistry\n * @param venusPool The VenusPool Object from PoolRegistry\n * @return Enriched PoolData\n */\n function getPoolDataFromVenusPool(\n address poolRegistryAddress,\n PoolRegistry.VenusPool memory venusPool\n ) public view returns (PoolData memory) {\n // Get tokens in the Pool\n ComptrollerInterface comptrollerInstance = ComptrollerInterface(venusPool.comptroller);\n\n VToken[] memory vTokens = _getMarkets(comptrollerInstance);\n\n VTokenMetadata[] memory vTokenMetadataItems = vTokenMetadataAll(vTokens);\n\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n\n PoolRegistry.VenusPoolMetaData memory venusPoolMetaData = poolRegistryInterface.getVenusPoolMetadata(\n venusPool.comptroller\n );\n\n ComptrollerViewInterface comptrollerViewInstance = ComptrollerViewInterface(venusPool.comptroller);\n\n PoolData memory poolData = PoolData({\n name: venusPool.name,\n creator: venusPool.creator,\n comptroller: venusPool.comptroller,\n blockPosted: venusPool.blockPosted,\n timestampPosted: venusPool.timestampPosted,\n category: venusPoolMetaData.category,\n logoURL: venusPoolMetaData.logoURL,\n description: venusPoolMetaData.description,\n vTokens: vTokenMetadataItems,\n priceOracle: address(comptrollerViewInstance.oracle()),\n closeFactor: comptrollerViewInstance.closeFactorMantissa(),\n liquidationIncentive: comptrollerViewInstance.liquidationIncentiveMantissa(),\n minLiquidatableCollateral: comptrollerViewInstance.minLiquidatableCollateral()\n });\n\n return poolData;\n }\n\n /**\n * @notice Returns the metadata of VToken\n * @param vToken The address of vToken\n * @return VTokenMetadata struct\n */\n function vTokenMetadata(VToken vToken) public view returns (VTokenMetadata memory) {\n uint256 exchangeRateCurrent = vToken.exchangeRateStored();\n address comptrollerAddress = address(vToken.comptroller());\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\n (bool isListed, uint256 collateralFactorMantissa) = comptroller.markets(address(vToken));\n\n address underlyingAssetAddress = vToken.underlying();\n uint256 underlyingDecimals = IERC20Metadata(underlyingAssetAddress).decimals();\n\n uint256 pausedActions;\n for (uint8 i; i <= uint8(type(Action).max); ++i) {\n uint256 paused = ComptrollerInterface(comptrollerAddress).actionPaused(address(vToken), Action(i)) ? 1 : 0;\n pausedActions |= paused << i;\n }\n\n uint256 supplyRatePerBlock;\n\n if (vToken.totalSupply() > 0) {\n supplyRatePerBlock = vToken.supplyRatePerBlock();\n }\n\n return\n VTokenMetadata({\n vToken: address(vToken),\n exchangeRateCurrent: exchangeRateCurrent,\n supplyRatePerBlockOrTimestamp: supplyRatePerBlock,\n borrowRatePerBlockOrTimestamp: vToken.borrowRatePerBlock(),\n reserveFactorMantissa: vToken.reserveFactorMantissa(),\n supplyCaps: comptroller.supplyCaps(address(vToken)),\n borrowCaps: comptroller.borrowCaps(address(vToken)),\n totalBorrows: vToken.totalBorrows(),\n totalReserves: vToken.totalReserves(),\n totalSupply: vToken.totalSupply(),\n totalCash: vToken.getCash(),\n isListed: isListed,\n collateralFactorMantissa: collateralFactorMantissa,\n underlyingAssetAddress: underlyingAssetAddress,\n vTokenDecimals: vToken.decimals(),\n underlyingDecimals: underlyingDecimals,\n pausedActions: pausedActions\n });\n }\n\n /**\n * @notice Returns the metadata of all VTokens\n * @param vTokens The list of vToken addresses\n * @return An array of VTokenMetadata structs\n */\n function vTokenMetadataAll(VToken[] memory vTokens) public view returns (VTokenMetadata[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenMetadata[] memory res = new VTokenMetadata[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenMetadata(vTokens[i]);\n }\n return res;\n }\n\n /**\n * @notice Returns the price data for the underlying asset of the specified vToken\n * @param vToken vToken address\n * @return The price data for each asset\n */\n function vTokenUnderlyingPrice(VToken vToken) public view returns (VTokenUnderlyingPrice memory) {\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(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 Returns markets from a comptroller. For the core pool, all markets are returned.\n * For other pools, markets with zero internalCash are filtered.\n * @param comptroller The comptroller to query\n * @return An array of VToken addresses\n */\n function _getMarkets(ComptrollerInterface comptroller) internal view returns (VToken[] memory) {\n VToken[] memory allMarkets = comptroller.getAllMarkets();\n\n if (address(comptroller) == corePoolComptroller) {\n return allMarkets;\n }\n\n // Single-loop filter: pack active markets to the front of allMarkets\n uint256 count;\n uint256 len = allMarkets.length;\n for (uint256 i; i < len; ++i) {\n if (allMarkets[i].internalCash() > 0) {\n allMarkets[count] = allMarkets[i];\n ++count;\n }\n }\n\n // Trim the array to the active count\n assembly {\n mstore(allMarkets, count)\n }\n\n return allMarkets;\n }\n\n function _calculateNotDistributedAwards(\n address account,\n VToken[] memory markets,\n RewardsDistributor rewardsDistributor\n ) internal view returns (PendingReward[] memory) {\n PendingReward[] memory pendingRewards = new PendingReward[](markets.length);\n\n for (uint256 i; i < markets.length; ++i) {\n // Market borrow and supply state we will modify update in-memory, in order to not modify storage\n RewardTokenState memory borrowState;\n RewardTokenState memory supplyState;\n\n if (isTimeBased) {\n (\n borrowState.index,\n borrowState.blockOrTimestamp,\n borrowState.lastRewardingBlockOrTimestamp\n ) = rewardsDistributor.rewardTokenBorrowStateTimeBased(address(markets[i]));\n (\n supplyState.index,\n supplyState.blockOrTimestamp,\n supplyState.lastRewardingBlockOrTimestamp\n ) = rewardsDistributor.rewardTokenSupplyStateTimeBased(address(markets[i]));\n } else {\n (\n borrowState.index,\n borrowState.blockOrTimestamp,\n borrowState.lastRewardingBlockOrTimestamp\n ) = rewardsDistributor.rewardTokenBorrowState(address(markets[i]));\n (\n supplyState.index,\n supplyState.blockOrTimestamp,\n supplyState.lastRewardingBlockOrTimestamp\n ) = rewardsDistributor.rewardTokenSupplyState(address(markets[i]));\n }\n\n Exp memory marketBorrowIndex = Exp({ mantissa: markets[i].borrowIndex() });\n\n // Update market supply and borrow index in-memory\n updateMarketBorrowIndex(address(markets[i]), rewardsDistributor, borrowState, marketBorrowIndex);\n updateMarketSupplyIndex(address(markets[i]), rewardsDistributor, supplyState);\n\n // Calculate pending rewards\n uint256 borrowReward = calculateBorrowerReward(\n address(markets[i]),\n rewardsDistributor,\n account,\n borrowState,\n marketBorrowIndex\n );\n uint256 supplyReward = calculateSupplierReward(\n address(markets[i]),\n rewardsDistributor,\n account,\n supplyState\n );\n\n PendingReward memory pendingReward;\n pendingReward.vTokenAddress = address(markets[i]);\n pendingReward.amount = borrowReward + supplyReward;\n pendingRewards[i] = pendingReward;\n }\n return pendingRewards;\n }\n\n function updateMarketBorrowIndex(\n address vToken,\n RewardsDistributor rewardsDistributor,\n RewardTokenState memory borrowState,\n Exp memory marketBorrowIndex\n ) internal view {\n uint256 borrowSpeed = rewardsDistributor.rewardTokenBorrowSpeeds(vToken);\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n if (\n borrowState.lastRewardingBlockOrTimestamp > 0 &&\n blockNumberOrTimestamp > borrowState.lastRewardingBlockOrTimestamp\n ) {\n blockNumberOrTimestamp = borrowState.lastRewardingBlockOrTimestamp;\n }\n\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, borrowState.blockOrTimestamp);\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\n // Remove the total earned interest rate since the opening of the market from total borrows\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, borrowSpeed);\n Double memory ratio = borrowAmount > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\n } else if (deltaBlocksOrTimestamp > 0) {\n borrowState.blockOrTimestamp = blockNumberOrTimestamp;\n }\n }\n\n function updateMarketSupplyIndex(\n address vToken,\n RewardsDistributor rewardsDistributor,\n RewardTokenState memory supplyState\n ) internal view {\n uint256 supplySpeed = rewardsDistributor.rewardTokenSupplySpeeds(vToken);\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n if (\n supplyState.lastRewardingBlockOrTimestamp > 0 &&\n blockNumberOrTimestamp > supplyState.lastRewardingBlockOrTimestamp\n ) {\n blockNumberOrTimestamp = supplyState.lastRewardingBlockOrTimestamp;\n }\n\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, supplyState.blockOrTimestamp);\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\n uint256 supplyTokens = VToken(vToken).totalSupply();\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, supplySpeed);\n Double memory ratio = supplyTokens > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\n } else if (deltaBlocksOrTimestamp > 0) {\n supplyState.blockOrTimestamp = blockNumberOrTimestamp;\n }\n }\n\n function calculateBorrowerReward(\n address vToken,\n RewardsDistributor rewardsDistributor,\n address borrower,\n RewardTokenState memory borrowState,\n Exp memory marketBorrowIndex\n ) internal view returns (uint256) {\n Double memory borrowIndex = Double({ mantissa: borrowState.index });\n Double memory borrowerIndex = Double({\n mantissa: rewardsDistributor.rewardTokenBorrowerIndex(vToken, borrower)\n });\n if (borrowerIndex.mantissa == 0 && borrowIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\n // Covers the case where users borrowed tokens before the market's borrow state index was set\n borrowerIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\n }\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\n return borrowerDelta;\n }\n\n function calculateSupplierReward(\n address vToken,\n RewardsDistributor rewardsDistributor,\n address supplier,\n RewardTokenState memory supplyState\n ) internal view returns (uint256) {\n Double memory supplyIndex = Double({ mantissa: supplyState.index });\n Double memory supplierIndex = Double({\n mantissa: rewardsDistributor.rewardTokenSupplierIndex(vToken, supplier)\n });\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\n // Covers the case where users supplied tokens before the market's supply state index was set\n supplierIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\n }\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\n return supplierDelta;\n }\n}\n" + }, + "contracts/lib/constants.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\n/// @dev The approximate number of seconds per year\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\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" + }, + "contracts/lib/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 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" + }, + "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" + }, + "contracts/Pool/PoolRegistry.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\n\nimport { PoolRegistryInterface } from \"./PoolRegistryInterface.sol\";\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { ensureNonzeroAddress } from \"../lib/validators.sol\";\n\n/**\n * @title PoolRegistry\n * @author Venus\n * @notice The Isolated Pools architecture centers around the `PoolRegistry` contract. The `PoolRegistry` maintains a directory of isolated lending\n * pools and can perform actions like creating and registering new pools, adding new markets to existing pools, setting and updating the pool's required\n * metadata, and providing the getter methods to get information on the pools.\n *\n * Isolated lending has three main components: PoolRegistry, pools, and markets. The PoolRegistry is responsible for managing pools.\n * It can create new pools, update pool metadata and manage markets within pools. PoolRegistry contains getter methods to get the details of\n * any existing pool like `getVTokenForAsset` and `getPoolsSupportedByAsset`. It also contains methods for updating pool metadata (`updatePoolMetadata`)\n * and setting pool name (`setPoolName`).\n *\n * The directory of pools is managed through two mappings: `_poolByComptroller` which is a hashmap with the comptroller address as the key and `VenusPool` as\n * the value and `_poolsByID` which is an array of comptroller addresses. Individual pools can be accessed by calling `getPoolByComptroller` with the pool's\n * comptroller address. `_poolsByID` is used to iterate through all of the pools.\n *\n * PoolRegistry also contains a map of asset addresses called `_supportedPools` that maps to an array of assets suppored by each pool. This array of pools by\n * asset is retrieved by calling `getPoolsSupportedByAsset`.\n *\n * PoolRegistry registers new isolated pools in the directory with the `createRegistryPool` method. Isolated pools are composed of independent markets with\n * specific assets and custom risk management configurations according to their markets.\n */\ncontract PoolRegistry is Ownable2StepUpgradeable, AccessControlledV8, PoolRegistryInterface {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n struct AddMarketInput {\n VToken vToken;\n uint256 collateralFactor;\n uint256 liquidationThreshold;\n uint256 initialSupply;\n address vTokenReceiver;\n uint256 supplyCap;\n uint256 borrowCap;\n }\n\n uint256 internal constant MAX_POOL_NAME_LENGTH = 100;\n\n /**\n * @notice Maps pool's comptroller address to metadata.\n */\n mapping(address => VenusPoolMetaData) public metadata;\n\n /**\n * @dev Maps pool ID to pool's comptroller address\n */\n mapping(uint256 => address) private _poolsByID;\n\n /**\n * @dev Total number of pools created.\n */\n uint256 private _numberOfPools;\n\n /**\n * @dev Maps comptroller address to Venus pool Index.\n */\n mapping(address => VenusPool) private _poolByComptroller;\n\n /**\n * @dev Maps pool's comptroller address to asset to vToken.\n */\n mapping(address => mapping(address => address)) private _vTokens;\n\n /**\n * @dev Maps asset to list of supported pools.\n */\n mapping(address => address[]) private _supportedPools;\n\n /**\n * @notice Emitted when a new Venus pool is added to the directory.\n */\n event PoolRegistered(address indexed comptroller, VenusPool pool);\n\n /**\n * @notice Emitted when a pool name is set.\n */\n event PoolNameSet(address indexed comptroller, string oldName, string newName);\n\n /**\n * @notice Emitted when a pool metadata is updated.\n */\n event PoolMetadataUpdated(\n address indexed comptroller,\n VenusPoolMetaData oldMetadata,\n VenusPoolMetaData newMetadata\n );\n\n /**\n * @notice Emitted when a Market is added to the pool.\n */\n event MarketAdded(address indexed comptroller, address indexed vTokenAddress);\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the deployer to owner\n * @param accessControlManager_ AccessControlManager contract address\n */\n function initialize(address accessControlManager_) external initializer {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n }\n\n /**\n * @notice Adds a new Venus pool to the directory\n * @dev Price oracle must be configured before adding a pool\n * @param name The name of the pool\n * @param comptroller Pool's Comptroller contract\n * @param closeFactor The pool's close factor (scaled by 1e18)\n * @param liquidationIncentive The pool's liquidation incentive (scaled by 1e18)\n * @param minLiquidatableCollateral Minimal collateral for regular (non-batch) liquidations flow\n * @return index The index of the registered Venus pool\n * @custom:error ZeroAddressNotAllowed is thrown when Comptroller address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\n */\n function addPool(\n string calldata name,\n Comptroller comptroller,\n uint256 closeFactor,\n uint256 liquidationIncentive,\n uint256 minLiquidatableCollateral\n ) external virtual returns (uint256 index) {\n _checkAccessAllowed(\"addPool(string,address,uint256,uint256,uint256)\");\n // Input validation\n ensureNonzeroAddress(address(comptroller));\n ensureNonzeroAddress(address(comptroller.oracle()));\n\n uint256 poolId = _registerPool(name, address(comptroller));\n\n // Set Venus pool parameters\n comptroller.setCloseFactor(closeFactor);\n comptroller.setLiquidationIncentive(liquidationIncentive);\n comptroller.setMinLiquidatableCollateral(minLiquidatableCollateral);\n\n return poolId;\n }\n\n /**\n * @notice Add a market to an existing pool and then mint to provide initial supply\n * @param input The structure describing the parameters for adding a market to a pool\n * @custom:error ZeroAddressNotAllowed is thrown when vToken address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when vTokenReceiver address is zero\n */\n function addMarket(AddMarketInput memory input) external {\n _checkAccessAllowed(\"addMarket(AddMarketInput)\");\n ensureNonzeroAddress(address(input.vToken));\n ensureNonzeroAddress(input.vTokenReceiver);\n require(input.initialSupply > 0, \"PoolRegistry: initialSupply is zero\");\n\n VToken vToken = input.vToken;\n address vTokenAddress = address(vToken);\n address comptrollerAddress = address(vToken.comptroller());\n Comptroller comptroller = Comptroller(comptrollerAddress);\n address underlyingAddress = vToken.underlying();\n IERC20Upgradeable underlying = IERC20Upgradeable(underlyingAddress);\n\n require(_poolByComptroller[comptrollerAddress].creator != address(0), \"PoolRegistry: Pool not registered\");\n // solhint-disable-next-line reason-string\n require(\n _vTokens[comptrollerAddress][underlyingAddress] == address(0),\n \"PoolRegistry: Market already added for asset comptroller combination\"\n );\n\n comptroller.supportMarket(vToken);\n comptroller.setCollateralFactor(vToken, input.collateralFactor, input.liquidationThreshold);\n\n uint256[] memory newSupplyCaps = new uint256[](1);\n uint256[] memory newBorrowCaps = new uint256[](1);\n VToken[] memory vTokens = new VToken[](1);\n\n newSupplyCaps[0] = input.supplyCap;\n newBorrowCaps[0] = input.borrowCap;\n vTokens[0] = vToken;\n\n comptroller.setMarketSupplyCaps(vTokens, newSupplyCaps);\n comptroller.setMarketBorrowCaps(vTokens, newBorrowCaps);\n\n _vTokens[comptrollerAddress][underlyingAddress] = vTokenAddress;\n _supportedPools[underlyingAddress].push(comptrollerAddress);\n\n uint256 amountToSupply = _transferIn(underlying, msg.sender, input.initialSupply);\n underlying.forceApprove(vTokenAddress, 0);\n underlying.forceApprove(vTokenAddress, amountToSupply);\n vToken.mintBehalf(input.vTokenReceiver, amountToSupply);\n\n emit MarketAdded(comptrollerAddress, vTokenAddress);\n }\n\n /**\n * @notice Modify existing Venus pool name\n * @param comptroller Pool's Comptroller\n * @param name New pool name\n */\n function setPoolName(address comptroller, string calldata name) external {\n _checkAccessAllowed(\"setPoolName(address,string)\");\n _ensureValidName(name);\n VenusPool storage pool = _poolByComptroller[comptroller];\n string memory oldName = pool.name;\n pool.name = name;\n emit PoolNameSet(comptroller, oldName, name);\n }\n\n /**\n * @notice Update metadata of an existing pool\n * @param comptroller Pool's Comptroller\n * @param metadata_ New pool metadata\n */\n function updatePoolMetadata(address comptroller, VenusPoolMetaData calldata metadata_) external {\n _checkAccessAllowed(\"updatePoolMetadata(address,VenusPoolMetaData)\");\n VenusPoolMetaData memory oldMetadata = metadata[comptroller];\n metadata[comptroller] = metadata_;\n emit PoolMetadataUpdated(comptroller, oldMetadata, metadata_);\n }\n\n /**\n * @notice Returns arrays of all Venus pools' data\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\n * @return A list of all pools within PoolRegistry, with details for each pool\n */\n function getAllPools() external view override returns (VenusPool[] memory) {\n uint256 numberOfPools_ = _numberOfPools; // storage load to save gas\n VenusPool[] memory _pools = new VenusPool[](numberOfPools_);\n for (uint256 i = 1; i <= numberOfPools_; ++i) {\n address comptroller = _poolsByID[i];\n _pools[i - 1] = (_poolByComptroller[comptroller]);\n }\n return _pools;\n }\n\n /**\n * @param comptroller The comptroller proxy address associated to the pool\n * @return Returns Venus pool\n */\n function getPoolByComptroller(address comptroller) external view override returns (VenusPool memory) {\n return _poolByComptroller[comptroller];\n }\n\n /**\n * @param comptroller comptroller of Venus pool\n * @return Returns Metadata of Venus pool\n */\n function getVenusPoolMetadata(address comptroller) external view override returns (VenusPoolMetaData memory) {\n return metadata[comptroller];\n }\n\n function getVTokenForAsset(address comptroller, address asset) external view override returns (address) {\n return _vTokens[comptroller][asset];\n }\n\n function getPoolsSupportedByAsset(address asset) external view override returns (address[] memory) {\n return _supportedPools[asset];\n }\n\n /**\n * @dev Adds a new Venus pool to the directory (without checking msg.sender).\n * @param name The name of the pool\n * @param comptroller The pool's Comptroller proxy contract address\n * @return The index of the registered Venus pool\n */\n function _registerPool(string calldata name, address comptroller) internal returns (uint256) {\n VenusPool storage storedPool = _poolByComptroller[comptroller];\n\n require(storedPool.creator == address(0), \"PoolRegistry: Pool already exists in the directory.\");\n _ensureValidName(name);\n\n ++_numberOfPools;\n uint256 numberOfPools_ = _numberOfPools; // cache on stack to save storage read gas\n\n VenusPool memory pool = VenusPool(name, msg.sender, comptroller, block.number, block.timestamp);\n\n _poolsByID[numberOfPools_] = comptroller;\n _poolByComptroller[comptroller] = pool;\n\n emit PoolRegistered(comptroller, pool);\n return numberOfPools_;\n }\n\n function _transferIn(IERC20Upgradeable token, address from, uint256 amount) internal returns (uint256) {\n uint256 balanceBefore = token.balanceOf(address(this));\n token.safeTransferFrom(from, address(this), amount);\n uint256 balanceAfter = token.balanceOf(address(this));\n return balanceAfter - balanceBefore;\n }\n\n function _ensureValidName(string calldata name) internal pure {\n require(bytes(name).length <= MAX_POOL_NAME_LENGTH, \"Pool's name is too large\");\n }\n}\n" + }, + "contracts/Pool/PoolRegistryInterface.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 /**\n * @notice Struct for a Venus interest rate pool metadata.\n */\n struct VenusPoolMetaData {\n string category;\n string logoURL;\n string description;\n }\n\n /// @notice Get all pools in PoolRegistry\n function getAllPools() external view returns (VenusPool[] memory);\n\n /// @notice Get a pool by comptroller address\n function getPoolByComptroller(address comptroller) external view returns (VenusPool memory);\n\n /// @notice Get the address of the VToken contract in the Pool where the underlying token is the provided 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 /// @notice Get the metadata of a Pool by comptroller address\n function getVenusPoolMetadata(address comptroller) external view returns (VenusPoolMetaData memory);\n}\n" + }, + "contracts/Rewards/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\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 { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { TimeManagerV8 } from \"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\";\n\nimport { ExponentialNoError } from \"../ExponentialNoError.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { MaxLoopsLimitHelper } from \"../MaxLoopsLimitHelper.sol\";\nimport { RewardsDistributorStorage } from \"./RewardsDistributorStorage.sol\";\n\n/**\n * @title `RewardsDistributor`\n * @author Venus\n * @notice Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol.\n * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward\n * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool.\n * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward\n * token to be released each slot (block or second) for borrowers and suppliers, which is distributed based on a user’s percentage of the borrows or supplies\n * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting\n * their contributor reward token speed, which similarly allocates a fixed amount of reward token per slot (block or second).\n *\n * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed\n * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized\n * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\n */\ncontract RewardsDistributor is\n ExponentialNoError,\n Ownable2StepUpgradeable,\n AccessControlledV8,\n MaxLoopsLimitHelper,\n RewardsDistributorStorage,\n TimeManagerV8\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice The initial REWARD TOKEN index for a market\n uint224 public constant INITIAL_INDEX = 1e36;\n\n /// @notice Emitted when REWARD TOKEN is distributed to a supplier\n event DistributedSupplierRewardToken(\n VToken indexed vToken,\n address indexed supplier,\n uint256 rewardTokenDelta,\n uint256 rewardTokenTotal,\n uint256 rewardTokenSupplyIndex\n );\n\n /// @notice Emitted when REWARD TOKEN is distributed to a borrower\n event DistributedBorrowerRewardToken(\n VToken indexed vToken,\n address indexed borrower,\n uint256 rewardTokenDelta,\n uint256 rewardTokenTotal,\n uint256 rewardTokenBorrowIndex\n );\n\n /// @notice Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\n event RewardTokenSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /// @notice Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\n event RewardTokenBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /// @notice Emitted when REWARD TOKEN is granted by admin\n event RewardTokenGranted(address indexed recipient, uint256 amount);\n\n /// @notice Emitted when a new REWARD TOKEN speed is set for a contributor\n event ContributorRewardTokenSpeedUpdated(address indexed contributor, uint256 newSpeed);\n\n /// @notice Emitted when a market is initialized\n event MarketInitialized(address indexed vToken);\n\n /// @notice Emitted when a reward token supply index is updated\n event RewardTokenSupplyIndexUpdated(address indexed vToken);\n\n /// @notice Emitted when a reward token borrow index is updated\n event RewardTokenBorrowIndexUpdated(address indexed vToken, Exp marketBorrowIndex);\n\n /// @notice Emitted when a reward for contributor is updated\n event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued);\n\n /// @notice Emitted when a reward token last rewarding block for supply is updated\n event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\n\n /// @notice Emitted when a reward token last rewarding block for borrow is updated\n event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\n\n /// @notice Emitted when a reward token last rewarding timestamp for supply is updated\n event SupplyLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\n\n /// @notice Emitted when a reward token last rewarding timestamp for borrow is updated\n event BorrowLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\n\n modifier onlyComptroller() {\n require(address(comptroller) == msg.sender, \"Only comptroller can call this function\");\n _;\n }\n\n /**\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\n * @param blocksPerYear_ The number of blocks per year\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /**\n * @notice RewardsDistributor initializer\n * @dev Initializes the deployer to owner\n * @param comptroller_ Comptroller to attach the reward distributor to\n * @param rewardToken_ Reward token to distribute\n * @param loopsLimit_ Maximum number of iterations for the loops in this contract\n * @param accessControlManager_ AccessControlManager contract address\n */\n function initialize(\n Comptroller comptroller_,\n IERC20Upgradeable rewardToken_,\n uint256 loopsLimit_,\n address accessControlManager_\n ) external initializer {\n comptroller = comptroller_;\n rewardToken = rewardToken_;\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n\n _setMaxLoopsLimit(loopsLimit_);\n }\n\n /**\n * @notice Initializes the market state for a specific vToken\n * @param vToken The address of the vToken to be initialized\n * @custom:event MarketInitialized emits on success\n * @custom:access Only Comptroller\n */\n function initializeMarket(address vToken) external onlyComptroller {\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n isTimeBased\n ? _initializeMarketTimestampBased(vToken, blockNumberOrTimestamp)\n : _initializeMarketBlockBased(vToken, safe32(blockNumberOrTimestamp, \"block number exceeds 32 bits\"));\n\n emit MarketInitialized(vToken);\n }\n\n /*** Reward Token Distribution ***/\n\n /**\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them\n * Borrowers will begin to accrue after the first interaction with the protocol.\n * @dev This function should only be called when the user has a borrow position in the market\n * (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook)\n * We avoid an external call to check if they are in the market to save gas because this function is called in many places\n * @param vToken The market in which the borrower is interacting\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\n * @param marketBorrowIndex The current global borrow index of vToken\n */\n function distributeBorrowerRewardToken(\n address vToken,\n address borrower,\n Exp memory marketBorrowIndex\n ) external onlyComptroller {\n _distributeBorrowerRewardToken(vToken, borrower, marketBorrowIndex);\n }\n\n function updateRewardTokenSupplyIndex(address vToken) external onlyComptroller {\n _updateRewardTokenSupplyIndex(vToken);\n }\n\n /**\n * @notice Transfer REWARD TOKEN to the recipient\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\n * @param recipient The address of the recipient to transfer REWARD TOKEN to\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\n */\n function grantRewardToken(address recipient, uint256 amount) external onlyOwner {\n uint256 amountLeft = _grantRewardToken(recipient, amount);\n require(amountLeft == 0, \"insufficient rewardToken for grant\");\n emit RewardTokenGranted(recipient, amount);\n }\n\n function updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) external onlyComptroller {\n _updateRewardTokenBorrowIndex(vToken, marketBorrowIndex);\n }\n\n /**\n * @notice Set REWARD TOKEN borrow and supply speeds for the specified markets\n * @param vTokens The markets whose REWARD TOKEN speed to update\n * @param supplySpeeds New supply-side REWARD TOKEN speed for the corresponding market\n * @param borrowSpeeds New borrow-side REWARD TOKEN speed for the corresponding market\n */\n function setRewardTokenSpeeds(\n VToken[] memory vTokens,\n uint256[] memory supplySpeeds,\n uint256[] memory borrowSpeeds\n ) external {\n _checkAccessAllowed(\"setRewardTokenSpeeds(address[],uint256[],uint256[])\");\n uint256 numTokens = vTokens.length;\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \"invalid setRewardTokenSpeeds\");\n\n for (uint256 i; i < numTokens; ++i) {\n _setRewardTokenSpeed(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\n }\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding block for the specified markets, used when contract is block based\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\n * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market\n * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market\n */\n function setLastRewardingBlocks(\n VToken[] calldata vTokens,\n uint32[] calldata supplyLastRewardingBlocks,\n uint32[] calldata borrowLastRewardingBlocks\n ) external {\n _checkAccessAllowed(\"setLastRewardingBlocks(address[],uint32[],uint32[])\");\n require(!isTimeBased, \"Block-based operation only\");\n\n uint256 numTokens = vTokens.length;\n require(\n numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length,\n \"RewardsDistributor::setLastRewardingBlocks invalid input\"\n );\n\n for (uint256 i; i < numTokens; ) {\n _setLastRewardingBlock(vTokens[i], supplyLastRewardingBlocks[i], borrowLastRewardingBlocks[i]);\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding block timestamp for the specified markets, used when contract is time based\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\n * @param supplyLastRewardingBlockTimestamps New supply-side REWARD TOKEN last rewarding block timestamp for the corresponding market\n * @param borrowLastRewardingBlockTimestamps New borrow-side REWARD TOKEN last rewarding block timestamp for the corresponding market\n */\n function setLastRewardingBlockTimestamps(\n VToken[] calldata vTokens,\n uint256[] calldata supplyLastRewardingBlockTimestamps,\n uint256[] calldata borrowLastRewardingBlockTimestamps\n ) external {\n _checkAccessAllowed(\"setLastRewardingBlockTimestamps(address[],uint256[],uint256[])\");\n require(isTimeBased, \"Time-based operation only\");\n\n uint256 numTokens = vTokens.length;\n require(\n numTokens == supplyLastRewardingBlockTimestamps.length &&\n numTokens == borrowLastRewardingBlockTimestamps.length,\n \"RewardsDistributor::setLastRewardingBlockTimestamps invalid input\"\n );\n\n for (uint256 i; i < numTokens; ) {\n _setLastRewardingBlockTimestamp(\n vTokens[i],\n supplyLastRewardingBlockTimestamps[i],\n borrowLastRewardingBlockTimestamps[i]\n );\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Set REWARD TOKEN speed for a single contributor\n * @param contributor The contributor whose REWARD TOKEN speed to update\n * @param rewardTokenSpeed New REWARD TOKEN speed for contributor\n */\n function setContributorRewardTokenSpeed(address contributor, uint256 rewardTokenSpeed) external onlyOwner {\n // note that REWARD TOKEN speed could be set to 0 to halt liquidity rewards for a contributor\n updateContributorRewards(contributor);\n if (rewardTokenSpeed == 0) {\n // release storage\n delete lastContributorBlock[contributor];\n } else {\n lastContributorBlock[contributor] = getBlockNumberOrTimestamp();\n }\n rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed;\n\n emit ContributorRewardTokenSpeedUpdated(contributor, rewardTokenSpeed);\n }\n\n function distributeSupplierRewardToken(address vToken, address supplier) external onlyComptroller {\n _distributeSupplierRewardToken(vToken, supplier);\n }\n\n /**\n * @notice Claim all the rewardToken accrued by holder in all markets\n * @param holder The address to claim REWARD TOKEN for\n */\n function claimRewardToken(address holder) external {\n return claimRewardToken(holder, comptroller.getAllMarkets());\n }\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) external onlyOwner {\n _setMaxLoopsLimit(limit);\n }\n\n /**\n * @notice Calculate additional accrued REWARD TOKEN for a contributor since last accrual\n * @param contributor The address to calculate contributor rewards for\n */\n function updateContributorRewards(address contributor) public {\n uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor];\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, lastContributorBlock[contributor]);\n if (deltaBlocksOrTimestamp > 0 && rewardTokenSpeed > 0) {\n uint256 newAccrued = mul_(deltaBlocksOrTimestamp, rewardTokenSpeed);\n uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued);\n\n rewardTokenAccrued[contributor] = contributorAccrued;\n lastContributorBlock[contributor] = blockNumberOrTimestamp;\n\n emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]);\n }\n }\n\n /**\n * @notice Claim all the rewardToken accrued by holder in the specified markets\n * @param holder The address to claim REWARD TOKEN for\n * @param vTokens The list of markets to claim REWARD TOKEN in\n */\n function claimRewardToken(address holder, VToken[] memory vTokens) public {\n uint256 vTokensCount = vTokens.length;\n\n _ensureMaxLoops(vTokensCount);\n\n for (uint256 i; i < vTokensCount; ++i) {\n VToken vToken = vTokens[i];\n require(comptroller.isMarketListed(vToken), \"market must be listed\");\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\n _distributeBorrowerRewardToken(address(vToken), holder, borrowIndex);\n _updateRewardTokenSupplyIndex(address(vToken));\n _distributeSupplierRewardToken(address(vToken), holder);\n }\n rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]);\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding block for a single market.\n * @param vToken market's whose reward token last rewarding block to be updated\n * @param supplyLastRewardingBlock New supply-side REWARD TOKEN last rewarding block for market\n * @param borrowLastRewardingBlock New borrow-side REWARD TOKEN last rewarding block for market\n */\n function _setLastRewardingBlock(\n VToken vToken,\n uint32 supplyLastRewardingBlock,\n uint32 borrowLastRewardingBlock\n ) internal {\n require(comptroller.isMarketListed(vToken), \"rewardToken market is not listed\");\n\n uint256 blockNumber = getBlockNumberOrTimestamp();\n\n require(supplyLastRewardingBlock > blockNumber, \"setting last rewarding block in the past is not allowed\");\n require(borrowLastRewardingBlock > blockNumber, \"setting last rewarding block in the past is not allowed\");\n\n uint32 currentSupplyLastRewardingBlock = rewardTokenSupplyState[address(vToken)].lastRewardingBlock;\n uint32 currentBorrowLastRewardingBlock = rewardTokenBorrowState[address(vToken)].lastRewardingBlock;\n\n require(\n currentSupplyLastRewardingBlock == 0 || currentSupplyLastRewardingBlock > blockNumber,\n \"this RewardsDistributor is already locked\"\n );\n require(\n currentBorrowLastRewardingBlock == 0 || currentBorrowLastRewardingBlock > blockNumber,\n \"this RewardsDistributor is already locked\"\n );\n\n if (currentSupplyLastRewardingBlock != supplyLastRewardingBlock) {\n rewardTokenSupplyState[address(vToken)].lastRewardingBlock = supplyLastRewardingBlock;\n emit SupplyLastRewardingBlockUpdated(address(vToken), supplyLastRewardingBlock);\n }\n\n if (currentBorrowLastRewardingBlock != borrowLastRewardingBlock) {\n rewardTokenBorrowState[address(vToken)].lastRewardingBlock = borrowLastRewardingBlock;\n emit BorrowLastRewardingBlockUpdated(address(vToken), borrowLastRewardingBlock);\n }\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding timestamp for a single market.\n * @param vToken market's whose reward token last rewarding timestamp to be updated\n * @param supplyLastRewardingBlockTimestamp New supply-side REWARD TOKEN last rewarding timestamp for market\n * @param borrowLastRewardingBlockTimestamp New borrow-side REWARD TOKEN last rewarding timestamp for market\n */\n function _setLastRewardingBlockTimestamp(\n VToken vToken,\n uint256 supplyLastRewardingBlockTimestamp,\n uint256 borrowLastRewardingBlockTimestamp\n ) internal {\n require(comptroller.isMarketListed(vToken), \"rewardToken market is not listed\");\n\n uint256 blockTimestamp = getBlockNumberOrTimestamp();\n\n require(\n supplyLastRewardingBlockTimestamp > blockTimestamp,\n \"setting last rewarding timestamp in the past is not allowed\"\n );\n require(\n borrowLastRewardingBlockTimestamp > blockTimestamp,\n \"setting last rewarding timestamp in the past is not allowed\"\n );\n\n uint256 currentSupplyLastRewardingBlockTimestamp = rewardTokenSupplyStateTimeBased[address(vToken)]\n .lastRewardingTimestamp;\n uint256 currentBorrowLastRewardingBlockTimestamp = rewardTokenBorrowStateTimeBased[address(vToken)]\n .lastRewardingTimestamp;\n\n require(\n currentSupplyLastRewardingBlockTimestamp == 0 || currentSupplyLastRewardingBlockTimestamp > blockTimestamp,\n \"this RewardsDistributor is already locked\"\n );\n require(\n currentBorrowLastRewardingBlockTimestamp == 0 || currentBorrowLastRewardingBlockTimestamp > blockTimestamp,\n \"this RewardsDistributor is already locked\"\n );\n\n if (currentSupplyLastRewardingBlockTimestamp != supplyLastRewardingBlockTimestamp) {\n rewardTokenSupplyStateTimeBased[address(vToken)].lastRewardingTimestamp = supplyLastRewardingBlockTimestamp;\n emit SupplyLastRewardingBlockTimestampUpdated(address(vToken), supplyLastRewardingBlockTimestamp);\n }\n\n if (currentBorrowLastRewardingBlockTimestamp != borrowLastRewardingBlockTimestamp) {\n rewardTokenBorrowStateTimeBased[address(vToken)].lastRewardingTimestamp = borrowLastRewardingBlockTimestamp;\n emit BorrowLastRewardingBlockTimestampUpdated(address(vToken), borrowLastRewardingBlockTimestamp);\n }\n }\n\n /**\n * @notice Set REWARD TOKEN speed for a single market.\n * @param vToken market's whose reward token rate to be updated\n * @param supplySpeed New supply-side REWARD TOKEN speed for market\n * @param borrowSpeed New borrow-side REWARD TOKEN speed for market\n */\n function _setRewardTokenSpeed(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\n require(comptroller.isMarketListed(vToken), \"rewardToken market is not listed\");\n\n if (rewardTokenSupplySpeeds[address(vToken)] != supplySpeed) {\n // Supply speed updated so let's update supply state to ensure that\n // 1. REWARD TOKEN accrued properly for the old speed, and\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\n _updateRewardTokenSupplyIndex(address(vToken));\n\n // Update speed and emit event\n rewardTokenSupplySpeeds[address(vToken)] = supplySpeed;\n emit RewardTokenSupplySpeedUpdated(vToken, supplySpeed);\n }\n\n if (rewardTokenBorrowSpeeds[address(vToken)] != borrowSpeed) {\n // Borrow speed updated so let's update borrow state to ensure that\n // 1. REWARD TOKEN accrued properly for the old speed, and\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\n\n // Update speed and emit event\n rewardTokenBorrowSpeeds[address(vToken)] = borrowSpeed;\n emit RewardTokenBorrowSpeedUpdated(vToken, borrowSpeed);\n }\n }\n\n /**\n * @notice Calculate REWARD TOKEN 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 REWARD TOKEN to\n */\n function _distributeSupplierRewardToken(address vToken, address supplier) internal {\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\n\n uint256 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\n uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier];\n\n // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN\n rewardTokenSupplierIndex[vToken][supplier] = supplyIndex;\n\n if (supplierIndex == 0 && supplyIndex >= INITIAL_INDEX) {\n // Covers the case where users supplied tokens before the market's supply state index was set.\n // Rewards the user with REWARD TOKEN accrued from the start of when supplier rewards were first\n // set for the market.\n supplierIndex = INITIAL_INDEX;\n }\n\n // Calculate change in the cumulative sum of the REWARD TOKEN per vToken accrued\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\n\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\n\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerVToken\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\n\n uint256 supplierAccrued = add_(rewardTokenAccrued[supplier], supplierDelta);\n rewardTokenAccrued[supplier] = supplierAccrued;\n\n emit DistributedSupplierRewardToken(VToken(vToken), supplier, supplierDelta, supplierAccrued, supplyIndex);\n }\n\n /**\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them.\n * @param vToken The market in which the borrower is interacting\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\n * @param marketBorrowIndex The current global borrow index of vToken\n */\n function _distributeBorrowerRewardToken(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\n\n uint256 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\n uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower];\n\n // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN\n rewardTokenBorrowerIndex[vToken][borrower] = borrowIndex;\n\n if (borrowerIndex == 0 && borrowIndex >= INITIAL_INDEX) {\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\n // Rewards the user with REWARD TOKEN accrued from the start of when borrower rewards were first\n // set for the market.\n borrowerIndex = INITIAL_INDEX;\n }\n\n // Calculate change in the cumulative sum of the REWARD TOKEN per borrowed unit accrued\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\n\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\n\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerBorrowedUnit\n if (borrowerAmount != 0) {\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\n\n uint256 borrowerAccrued = add_(rewardTokenAccrued[borrower], borrowerDelta);\n rewardTokenAccrued[borrower] = borrowerAccrued;\n\n emit DistributedBorrowerRewardToken(VToken(vToken), borrower, borrowerDelta, borrowerAccrued, borrowIndex);\n }\n }\n\n /**\n * @notice Transfer REWARD TOKEN to the user.\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all.\n * @param user The address of the user to transfer REWARD TOKEN to\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\n * @return The amount of REWARD TOKEN which was NOT transferred to the user\n */\n function _grantRewardToken(address user, uint256 amount) internal returns (uint256) {\n uint256 rewardTokenRemaining = rewardToken.balanceOf(address(this));\n if (amount > 0 && amount <= rewardTokenRemaining) {\n rewardToken.safeTransfer(user, amount);\n return 0;\n }\n return amount;\n }\n\n /**\n * @notice Accrue REWARD TOKEN to the market by updating the supply index\n * @param vToken The market whose supply index to update\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\n */\n function _updateRewardTokenSupplyIndex(address vToken) internal {\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\n\n uint256 supplySpeed = rewardTokenSupplySpeeds[vToken];\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n if (!isTimeBased) {\n safe32(blockNumberOrTimestamp, \"block number exceeds 32 bits\");\n }\n\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\n ? supplyStateTimeBased.lastRewardingTimestamp\n : uint256(supplyState.lastRewardingBlock);\n\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\n }\n\n uint256 deltaBlocksOrTimestamp = sub_(\n blockNumberOrTimestamp,\n (isTimeBased ? supplyStateTimeBased.timestamp : uint256(supplyState.block))\n );\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\n uint256 supplyTokens = VToken(vToken).totalSupply();\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, supplySpeed);\n Double memory ratio = supplyTokens > 0\n ? fraction(accruedSinceUpdate, supplyTokens)\n : Double({ mantissa: 0 });\n uint224 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\n uint224 index = safe224(\n add_(Double({ mantissa: supplyIndex }), ratio).mantissa,\n \"new index exceeds 224 bits\"\n );\n\n if (isTimeBased) {\n supplyStateTimeBased.index = index;\n supplyStateTimeBased.timestamp = blockNumberOrTimestamp;\n } else {\n supplyState.index = index;\n supplyState.block = uint32(blockNumberOrTimestamp);\n }\n } else if (deltaBlocksOrTimestamp > 0) {\n isTimeBased ? supplyStateTimeBased.timestamp = blockNumberOrTimestamp : supplyState.block = uint32(\n blockNumberOrTimestamp\n );\n }\n\n emit RewardTokenSupplyIndexUpdated(vToken);\n }\n\n /**\n * @notice Accrue REWARD TOKEN to the market by updating the borrow index\n * @param vToken The market whose borrow index to update\n * @param marketBorrowIndex The current global borrow index of vToken\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\n */\n function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\n\n uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken];\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n if (!isTimeBased) {\n safe32(blockNumberOrTimestamp, \"block number exceeds 32 bits\");\n }\n\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\n ? borrowStateTimeBased.lastRewardingTimestamp\n : uint256(borrowState.lastRewardingBlock);\n\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\n }\n\n uint256 deltaBlocksOrTimestamp = sub_(\n blockNumberOrTimestamp,\n (isTimeBased ? borrowStateTimeBased.timestamp : uint256(borrowState.block))\n );\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, borrowSpeed);\n Double memory ratio = borrowAmount > 0\n ? fraction(accruedSinceUpdate, borrowAmount)\n : Double({ mantissa: 0 });\n uint224 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\n uint224 index = safe224(\n add_(Double({ mantissa: borrowIndex }), ratio).mantissa,\n \"new index exceeds 224 bits\"\n );\n\n if (isTimeBased) {\n borrowStateTimeBased.index = index;\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\n } else {\n borrowState.index = index;\n borrowState.block = uint32(blockNumberOrTimestamp);\n }\n } else if (deltaBlocksOrTimestamp > 0) {\n if (isTimeBased) {\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\n } else {\n borrowState.block = uint32(blockNumberOrTimestamp);\n }\n }\n\n emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex);\n }\n\n /**\n * @notice Initializes the market state for a specific vToken called when contract is block-based\n * @param vToken The address of the vToken to be initialized\n * @param blockNumber current block number\n */\n function _initializeMarketBlockBased(address vToken, uint32 blockNumber) internal {\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n RewardToken storage borrowState = rewardTokenBorrowState[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 = INITIAL_INDEX;\n }\n\n if (borrowState.index == 0) {\n // Initialize borrow state index with default value\n borrowState.index = INITIAL_INDEX;\n }\n\n /*\n * Update market state block numbers\n */\n supplyState.block = borrowState.block = blockNumber;\n }\n\n /**\n * @notice Initializes the market state for a specific vToken called when contract is time-based\n * @param vToken The address of the vToken to be initialized\n * @param blockTimestamp current block timestamp\n */\n function _initializeMarketTimestampBased(address vToken, uint256 blockTimestamp) internal {\n TimeBasedRewardToken storage supplyState = rewardTokenSupplyStateTimeBased[vToken];\n TimeBasedRewardToken storage borrowState = rewardTokenBorrowStateTimeBased[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 = INITIAL_INDEX;\n }\n\n if (borrowState.index == 0) {\n // Initialize borrow state index with default value\n borrowState.index = INITIAL_INDEX;\n }\n\n /*\n * Update market state block timestamp\n */\n supplyState.timestamp = borrowState.timestamp = blockTimestamp;\n }\n}\n" + }, + "contracts/Rewards/RewardsDistributorStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\nimport { Comptroller } from \"../Comptroller.sol\";\n\n/**\n * @title RewardsDistributorStorage\n * @author Venus\n * @dev Storage for RewardsDistributor\n */\ncontract RewardsDistributorStorage {\n struct RewardToken {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block number the index was last updated at\n uint32 block;\n // The block number at which to stop rewards\n uint32 lastRewardingBlock;\n }\n\n struct TimeBasedRewardToken {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block timestamp the index was last updated at\n uint256 timestamp;\n // The block timestamp at which to stop rewards\n uint256 lastRewardingTimestamp;\n }\n\n /// @notice The REWARD TOKEN market supply state for each market\n mapping(address => RewardToken) public rewardTokenSupplyState;\n\n /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\n mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex;\n\n /// @notice The REWARD TOKEN accrued but not yet transferred to each user\n mapping(address => uint256) public rewardTokenAccrued;\n\n /// @notice The rate at which rewardToken is distributed to the corresponding borrow market per slot (block or second)\n mapping(address => uint256) public rewardTokenBorrowSpeeds;\n\n /// @notice The rate at which rewardToken is distributed to the corresponding supply market per slot (block or second)\n mapping(address => uint256) public rewardTokenSupplySpeeds;\n\n /// @notice The REWARD TOKEN market borrow state for each market\n mapping(address => RewardToken) public rewardTokenBorrowState;\n\n /// @notice The portion of REWARD TOKEN that each contributor receives per slot (block or second)\n mapping(address => uint256) public rewardTokenContributorSpeeds;\n\n /// @notice Last slot (block or second) at which a contributor's REWARD TOKEN rewards have been allocated\n mapping(address => uint256) public lastContributorBlock;\n\n /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\n mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex;\n\n Comptroller internal comptroller;\n\n IERC20Upgradeable public rewardToken;\n\n /// @notice The REWARD TOKEN market supply state for each market\n mapping(address => TimeBasedRewardToken) public rewardTokenSupplyStateTimeBased;\n\n /// @notice The REWARD TOKEN market borrow state for each market\n mapping(address => TimeBasedRewardToken) public rewardTokenBorrowStateTimeBased;\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[37] private __gap;\n}\n" + }, + "contracts/VToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\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 { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { IProtocolShareReserve } from \"@venusprotocol/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\";\n\nimport { VTokenInterface } from \"./VTokenInterfaces.sol\";\nimport { ComptrollerInterface, ComptrollerViewInterface } from \"./ComptrollerInterface.sol\";\nimport { TokenErrorReporter } from \"./ErrorReporter.sol\";\nimport { InterestRateModel } from \"./InterestRateModel.sol\";\nimport { ExponentialNoError } from \"./ExponentialNoError.sol\";\nimport { TimeManagerV8 } from \"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\";\nimport { ensureNonzeroAddress } from \"./lib/validators.sol\";\n\n/**\n * @title VToken\n * @author Venus\n * @notice Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview,\n * each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of\n * the pool. The main actions a user regularly interacts with in a market are:\n\n- mint/redeem of vTokens;\n- transfer of vTokens;\n- borrow/repay a loan on an underlying asset;\n- liquidate a borrow or liquidate/heal an account.\n\n * A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`.\n * The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted\n * `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken`\n * as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that\n * a user may borrow up to a portion of their collateral determined by the market’s collateral factor. However, if their borrowed amount exceeds an amount\n * calculated using the market’s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also\n * pay off interest accrued on the borrow.\n * \n * The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller`\n * and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a\n * total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`.\n * Both functions settle all of an account’s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of\n * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\n */\ncontract VToken is\n Ownable2StepUpgradeable,\n AccessControlledV8,\n VTokenInterface,\n ExponentialNoError,\n TokenErrorReporter,\n TimeManagerV8\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5%\n\n // Maximum fraction of interest that can be set aside for reserves\n uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18;\n\n // Maximum borrow rate that can ever be applied per slot(block or second)\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n uint256 internal immutable MAX_BORROW_RATE_MANTISSA;\n\n /**\n * Reentrancy Guard **\n */\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 * @param timeBased_ A boolean indicating whether the contract is based on time or block.\n * @param blocksPerYear_ The number of blocks per year\n * @param maxBorrowRateMantissa_ The maximum value of borrowing rate mantissa\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor(\n bool timeBased_,\n uint256 blocksPerYear_,\n uint256 maxBorrowRateMantissa_\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n require(maxBorrowRateMantissa_ <= 1e18, \"Max borrow rate must be <= 1e18\");\n\n MAX_BORROW_RATE_MANTISSA = maxBorrowRateMantissa_;\n _disableInitializers();\n }\n\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_ ERC-20 name of this token\n * @param symbol_ ERC-20 symbol of this token\n * @param decimals_ ERC-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param accessControlManager_ AccessControlManager contract address\n * @param riskManagement Addresses of risk & income related contracts\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\n * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\n */\n function initialize(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address admin_,\n address accessControlManager_,\n RiskManagementInit memory riskManagement,\n uint256 reserveFactorMantissa_\n ) external initializer {\n ensureNonzeroAddress(admin_);\n\n // Initialize the market\n _initialize(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_,\n accessControlManager_,\n riskManagement,\n reserveFactorMantissa_\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 * @return success True if the transfer succeeded, reverts otherwise\n * @custom:event Emits Transfer event on success\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\n * @custom:access Not restricted\n */\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\n _transferTokens(msg.sender, msg.sender, dst, amount);\n return true;\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 success True if the transfer succeeded, reverts otherwise\n * @custom:event Emits Transfer event on success\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\n * @custom:access Not restricted\n */\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\n _transferTokens(msg.sender, src, dst, amount);\n return true;\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 (uint256.max means infinite)\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function approve(address spender, uint256 amount) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n transferAllowances[src][spender] = amount;\n emit Approval(src, spender, amount);\n return true;\n }\n\n /**\n * @notice Increase approval for `spender`\n * @param spender The address of the account which may transfer tokens\n * @param addedValue The number of additional tokens spender can transfer\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function increaseAllowance(address spender, uint256 addedValue) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n uint256 newAllowance = transferAllowances[src][spender];\n newAllowance += addedValue;\n transferAllowances[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n return true;\n }\n\n /**\n * @notice Decreases approval for `spender`\n * @param spender The address of the account which may transfer tokens\n * @param subtractedValue The number of tokens to remove from total approval\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n uint256 currentAllowance = transferAllowances[src][spender];\n require(currentAllowance >= subtractedValue, \"decreased allowance below zero\");\n unchecked {\n currentAllowance -= subtractedValue;\n }\n\n transferAllowances[src][spender] = currentAllowance;\n\n emit Approval(src, spender, currentAllowance);\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 amount The amount of underlying owned by `owner`\n */\n function balanceOfUnderlying(address owner) external override returns (uint256) {\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\n return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\n }\n\n /**\n * @notice Returns the current total borrows plus accrued interest\n * @return totalBorrows The total borrows with interest\n */\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\n accrueInterest();\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 borrowBalance The calculated balance\n */\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\n accrueInterest();\n return _borrowBalanceStored(account);\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function mint(uint256 mintAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _mintFresh(msg.sender, msg.sender, mintAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param minter User whom the supply will be attributed to\n * @param mintAmount The amount of the underlying asset to supply\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when minter address is zero\n */\n function mintBehalf(address minter, uint256 mintAmount) external override nonReentrant returns (uint256) {\n ensureNonzeroAddress(minter);\n\n accrueInterest();\n\n _mintFresh(msg.sender, minter, mintAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\n * @custom:access Not restricted\n */\n function redeem(uint256 redeemTokens) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _redeemFresh(msg.sender, msg.sender, redeemTokens, 0);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function redeemBehalf(address redeemer, uint256 redeemTokens) external override nonReentrant returns (uint256) {\n _ensureSenderIsDelegateOf(redeemer);\n\n accrueInterest();\n\n _redeemFresh(redeemer, msg.sender, redeemTokens, 0);\n return NO_ERROR;\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 receive from redeeming vTokens\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n */\n function redeemUnderlying(uint256 redeemAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _redeemFresh(msg.sender, msg.sender, 0, redeemAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function redeemUnderlyingBehalf(\n address redeemer,\n uint256 redeemAmount\n ) external override nonReentrant returns (uint256) {\n _ensureSenderIsDelegateOf(redeemer);\n\n accrueInterest();\n\n _redeemFresh(redeemer, msg.sender, 0, redeemAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Borrow event; may emit AccrueInterest\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\n * @custom:access Not restricted\n */\n function borrow(uint256 borrowAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _borrowFresh(msg.sender, msg.sender, borrowAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:error DelegateNotApproved is thrown if caller is not approved delegate\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\n * @custom:event Emits Borrow event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function borrowBehalf(address borrower, uint256 borrowAmount) external override returns (uint256) {\n _ensureSenderIsDelegateOf(borrower);\n accrueInterest();\n\n _borrowFresh(borrower, msg.sender, borrowAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function repayBorrow(uint256 repayAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _repayBorrowFresh(msg.sender, msg.sender, repayAmount);\n return NO_ERROR;\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, or type(uint256).max for the full outstanding amount\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _repayBorrowFresh(msg.sender, borrower, repayAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\n * @custom:access Not restricted\n */\n function liquidateBorrow(\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) external override returns (uint256) {\n _liquidateBorrow(msg.sender, borrower, repayAmount, vTokenCollateral, false);\n return NO_ERROR;\n }\n\n /**\n * @notice sets protocol share accumulated from liquidations\n * @dev must be equal or less than liquidation incentive - 1\n * @param newProtocolSeizeShareMantissa_ new protocol share mantissa\n * @custom:event Emits NewProtocolSeizeShare event on success\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:error ProtocolSeizeShareTooBig is thrown when the new seize share is too high\n * @custom:access Controlled by AccessControlManager\n */\n function setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa_) external {\n _checkAccessAllowed(\"setProtocolSeizeShare(uint256)\");\n uint256 liquidationIncentive = ComptrollerViewInterface(address(comptroller)).liquidationIncentiveMantissa();\n if (newProtocolSeizeShareMantissa_ + MANTISSA_ONE > liquidationIncentive) {\n revert ProtocolSeizeShareTooBig();\n }\n\n uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\n protocolSeizeShareMantissa = newProtocolSeizeShareMantissa_;\n emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa_);\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 * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\n * @custom:event Emits NewReserveFactor event; may emit AccrueInterest\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:error SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\n * @custom:access Controlled by AccessControlManager\n */\n function setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant {\n _checkAccessAllowed(\"setReserveFactor(uint256)\");\n\n accrueInterest();\n _setReserveFactorFresh(newReserveFactorMantissa);\n }\n\n /**\n * @notice Accrues interest and reduces reserves by transferring to the protocol reserve contract\n * @dev Gracefully return if reserves already reduced in accrueInterest\n * @param reduceAmount Amount of reduction to reserves\n * @custom:event Emits ReservesReduced event; may emit AccrueInterest\n * @custom:error ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash\n * @custom:error ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\n * @custom:access Not restricted\n */\n function reduceReserves(uint256 reduceAmount) external override nonReentrant {\n accrueInterest();\n if (reduceReservesBlockNumber == getBlockNumberOrTimestamp()) return;\n _reduceReservesFresh(reduceAmount);\n }\n\n /**\n * @notice The sender adds to reserves.\n * @param addAmount The amount of underlying token to add as reserves\n * @custom:event Emits ReservesAdded event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function addReserves(uint256 addAmount) external override nonReentrant {\n accrueInterest();\n _addReservesFresh(addAmount);\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 * @custom:event Emits NewMarketInterestRateModel event; may emit AccrueInterest\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:access Controlled by AccessControlManager\n */\n function setInterestRateModel(InterestRateModel newInterestRateModel) external override {\n _checkAccessAllowed(\"setInterestRateModel(address)\");\n\n accrueInterest();\n _setInterestRateModelFresh(newInterestRateModel);\n }\n\n /**\n * @notice Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially\n * \"forgiving\" the borrower. Healing is a situation that should rarely happen. However, some pools\n * may list risky assets or be configured improperly – we want to still handle such cases gracefully.\n * We assume that Comptroller does the seizing, so this function is only available to Comptroller.\n * @dev This function does not call any Comptroller hooks (like \"healAllowed\"), because we assume\n * the Comptroller does all the necessary checks before calling this function.\n * @param payer account who repays the debt\n * @param borrower account to heal\n * @param repayAmount amount to repay\n * @custom:event Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\n * @custom:error HealBorrowUnauthorized is thrown when the request does not come from Comptroller\n * @custom:access Only Comptroller\n */\n function healBorrow(address payer, address borrower, uint256 repayAmount) external override nonReentrant {\n if (repayAmount != 0) {\n comptroller.preRepayHook(address(this), borrower);\n }\n\n if (msg.sender != address(comptroller)) {\n revert HealBorrowUnauthorized();\n }\n\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n uint256 totalBorrowsNew = totalBorrows;\n\n uint256 actualRepayAmount;\n if (repayAmount != 0) {\n // _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\n // We violate checks-effects-interactions here to account for tokens that take transfer fees\n actualRepayAmount = _doTransferIn(payer, repayAmount);\n totalBorrowsNew = totalBorrowsNew - actualRepayAmount;\n emit RepayBorrow(\n payer,\n borrower,\n actualRepayAmount,\n accountBorrowsPrev - actualRepayAmount,\n totalBorrowsNew\n );\n }\n\n // The transaction will fail if trying to repay too much\n uint256 badDebtDelta = accountBorrowsPrev - actualRepayAmount;\n if (badDebtDelta != 0) {\n uint256 badDebtOld = badDebt;\n uint256 badDebtNew = badDebtOld + badDebtDelta;\n totalBorrowsNew = totalBorrowsNew - badDebtDelta;\n badDebt = badDebtNew;\n\n // We treat healing as \"repayment\", where vToken is the payer\n emit RepayBorrow(address(this), borrower, badDebtDelta, 0, totalBorrowsNew);\n emit BadDebtIncreased(borrower, badDebtDelta, badDebtOld, badDebtNew);\n }\n\n accountBorrows[borrower].principal = 0;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n emit HealBorrow(payer, borrower, repayAmount);\n }\n\n /**\n * @notice The extended version of liquidations, callable only by Comptroller. May skip\n * the close factor check. The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\n * @custom:error ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\n * @custom:access Only Comptroller\n */\n function forceLiquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) external override {\n if (msg.sender != address(comptroller)) {\n revert ForceLiquidateBorrowUnauthorized();\n }\n _liquidateBorrow(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\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 * @custom:event Emits Transfer, ReservesAdded events\n * @custom:error LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:access Not restricted\n */\n function seize(address liquidator, address borrower, uint256 seizeTokens) external override nonReentrant {\n _seize(msg.sender, liquidator, borrower, seizeTokens);\n }\n\n /**\n * @notice Updates bad debt\n * @dev Called only when bad debt is recovered from auction. Updates internal cash balance.\n * @param recoveredAmount_ The amount of bad debt recovered\n * @custom:event Emits BadDebtRecovered event\n * @custom:access Only Shortfall contract\n */\n function badDebtRecovered(uint256 recoveredAmount_) external {\n require(msg.sender == shortfall, \"only shortfall contract can update bad debt\");\n require(recoveredAmount_ <= badDebt, \"more than bad debt recovered from auction\");\n\n uint256 badDebtOld = badDebt;\n uint256 badDebtNew = badDebtOld - recoveredAmount_;\n badDebt = badDebtNew;\n internalCash += recoveredAmount_;\n\n emit BadDebtRecovered(badDebtOld, badDebtNew);\n }\n\n /**\n * @notice Sets protocol share reserve contract address\n * @param protocolShareReserve_ The address of the protocol share reserve contract\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\n * @custom:access Only Governance\n */\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\n _setProtocolShareReserve(protocolShareReserve_);\n }\n\n /**\n * @notice Sets shortfall contract address\n * @param shortfall_ The address of the shortfall contract\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\n * @custom:access Only Governance\n */\n function setShortfallContract(address shortfall_) external onlyOwner {\n _setShortfallContract(shortfall_);\n }\n\n /**\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\n * @param token The address of the ERC-20 token to sweep\n * @custom:access Only Governance\n */\n function sweepToken(IERC20Upgradeable token) external override {\n require(msg.sender == owner(), \"VToken::sweepToken: only admin can sweep tokens\");\n require(address(token) != underlying, \"VToken::sweepToken: can not sweep underlying token\");\n uint256 balance = token.balanceOf(address(this));\n token.safeTransfer(owner(), balance);\n\n emit SweepToken(address(token));\n }\n\n /**\n * @notice Sync internalCash with the actual underlying token balance\n * @dev Used for one-time migration after upgrade to initialize internalCash\n * @custom:event Emits CashSynced\n * @custom:access Controlled by AccessControlManager\n */\n function syncCash() external override nonReentrant {\n _checkAccessAllowed(\"syncCash()\");\n uint256 oldInternalCash = internalCash;\n uint256 actualCash = IERC20Upgradeable(underlying).balanceOf(address(this));\n internalCash = actualCash;\n emit CashSynced(oldInternalCash, actualCash);\n }\n\n /**\n * @notice A public function to set new threshold of slot(block or second) difference after which funds will be sent to the protocol share reserve\n * @param _newReduceReservesBlockOrTimestampDelta slot(block or second) difference value\n * @custom:access Only Governance\n */\n function setReduceReservesBlockDelta(uint256 _newReduceReservesBlockOrTimestampDelta) external {\n _checkAccessAllowed(\"setReduceReservesBlockDelta(uint256)\");\n require(_newReduceReservesBlockOrTimestampDelta > 0, \"Invalid Input\");\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, _newReduceReservesBlockOrTimestampDelta);\n reduceReservesBlockDelta = _newReduceReservesBlockOrTimestampDelta;\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 amount 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 amount 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 error Always NO_ERROR for compatibility with Venus core tooling\n * @return vTokenBalance User's balance of vTokens\n * @return borrowBalance Amount owed in terms of underlying\n * @return exchangeRate Stored exchange rate\n */\n function getAccountSnapshot(\n address account\n )\n external\n view\n override\n returns (uint256 error, uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRate)\n {\n return (NO_ERROR, accountTokens[account], _borrowBalanceStored(account), _exchangeRateStored());\n }\n\n /**\n * @notice Get the internally tracked cash balance of this vToken in the underlying asset\n * @return cash The quantity of underlying asset tracked internally by this contract\n */\n function getCash() external view override returns (uint256) {\n return _getCashPrior();\n }\n\n /**\n * @notice Returns the current per slot(block or second) borrow interest rate for this vToken\n * @return rate The borrow interest rate per slot(block or second), scaled by 1e18\n */\n function borrowRatePerBlock() external view override returns (uint256) {\n return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt);\n }\n\n /**\n * @notice Returns the current per-slot(block or second) supply interest rate for this v\n * @return rate The supply interest rate per slot(block or second), scaled by 1e18\n */\n function supplyRatePerBlock() external view override returns (uint256) {\n return\n interestRateModel.getSupplyRate(\n _getCashPrior(),\n totalBorrows,\n totalReserves,\n reserveFactorMantissa,\n badDebt\n );\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 borrowBalance The calculated balance\n */\n function borrowBalanceStored(address account) external view override returns (uint256) {\n return _borrowBalanceStored(account);\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 exchangeRate Calculated exchange rate scaled by 1e18\n */\n function exchangeRateStored() external view override returns (uint256) {\n return _exchangeRateStored();\n }\n\n /**\n * @notice Accrue interest then return the up-to-date exchange rate\n * @return exchangeRate Calculated exchange rate scaled by 1e18\n */\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\n accrueInterest();\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 slot(block or second)\n * up to the current slot(block or second) and writes new checkpoint to storage and\n * reduce spread reserves to protocol share reserve\n * if currentSlot - reduceReservesBlockNumber >= slotDelta\n * @return Always NO_ERROR\n * @custom:event Emits AccrueInterest event on success\n * @custom:access Not restricted\n */\n function accrueInterest() public virtual override returns (uint256) {\n /* Remember the initial block number or timestamp */\n uint256 currentSlotNumber = getBlockNumberOrTimestamp();\n uint256 accrualSlotNumberPrior = accrualBlockNumber;\n\n /* Short-circuit accumulating 0 interest */\n if (accrualSlotNumberPrior == currentSlotNumber) {\n return NO_ERROR;\n }\n\n /* Read the previous values out of storage */\n uint256 cashPrior = _getCashPrior();\n uint256 borrowsPrior = totalBorrows;\n uint256 reservesPrior = totalReserves;\n uint256 borrowIndexPrior = borrowIndex;\n\n /* Calculate the current borrow interest rate */\n uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt);\n require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, \"borrow rate is absurdly high\");\n\n /* Calculate the number of slots elapsed since the last accrual */\n uint256 slotDelta = currentSlotNumber - accrualSlotNumberPrior;\n\n /*\n * Calculate the interest accumulated into borrows and reserves and the new index:\n * simpleInterestFactor = borrowRate * slotDelta\n * interestAccumulated = simpleInterestFactor * totalBorrows\n * totalBorrowsNew = interestAccumulated + totalBorrows\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\n */\n\n Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), slotDelta);\n uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\n uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;\n uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\n Exp({ mantissa: reserveFactorMantissa }),\n interestAccumulated,\n reservesPrior\n );\n uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the previously calculated values into storage */\n accrualBlockNumber = currentSlotNumber;\n borrowIndex = borrowIndexNew;\n totalBorrows = totalBorrowsNew;\n totalReserves = totalReservesNew;\n\n if (currentSlotNumber - reduceReservesBlockNumber >= reduceReservesBlockDelta) {\n reduceReservesBlockNumber = currentSlotNumber;\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 NO_ERROR;\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 or timestamp\n * @param payer The address of the account which is sending the assets for supply\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 */\n function _mintFresh(address payer, address minter, uint256 mintAmount) internal {\n /* Fail if mint not allowed */\n comptroller.preMintHook(address(this), minter, mintAmount);\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert MintFreshnessCheck();\n }\n\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\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 * `_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 uint256 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 uint256 mintTokens = div_(actualMintAmount, exchangeRate);\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 * And write them into storage\n */\n totalSupply = totalSupply + mintTokens;\n uint256 balanceAfter = accountTokens[minter] + mintTokens;\n accountTokens[minter] = balanceAfter;\n\n /* We emit a Mint event, and a Transfer event */\n emit Mint(minter, actualMintAmount, mintTokens, balanceAfter);\n emit Transfer(address(0), minter, mintTokens);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.mintVerify(address(this), minter, actualMintAmount, mintTokens);\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 Comptroller.updateDelegate)\n * @dev Assumes interest has already been accrued up to the current slot(block or second)\n * @param redeemer The address of the account which is redeeming the tokens\n * @param receiver The receiver of the underlying 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 */\n function _redeemFresh(address redeemer, address receiver, uint256 redeemTokensIn, uint256 redeemAmountIn) internal {\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \"one of redeemTokensIn or redeemAmountIn must be zero\");\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert RedeemFreshnessCheck();\n }\n\n /* exchangeRate = invoke Exchange Rate Stored() */\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\n\n uint256 redeemTokens;\n uint256 redeemAmount;\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 */\n redeemTokens = redeemTokensIn;\n } else {\n /*\n * We get the current exchange rate and calculate the amount to be redeemed:\n * redeemTokens = redeemAmountIn / exchangeRate\n */\n redeemTokens = div_(redeemAmountIn, exchangeRate);\n\n uint256 _redeemAmount = mul_(redeemTokens, exchangeRate);\n if (_redeemAmount != 0 && _redeemAmount != redeemAmountIn) redeemTokens++; // round up\n }\n\n // redeemAmount = exchangeRate * redeemTokens\n redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokens);\n\n // Revert if amount is zero\n if (redeemAmount == 0) {\n revert(\"redeemAmount is zero\");\n }\n\n /* Fail if redeem not allowed */\n comptroller.preRedeemHook(address(this), redeemer, redeemTokens);\n\n /* Fail gracefully if protocol has insufficient cash */\n if (_getCashPrior() - totalReserves < redeemAmount) {\n revert RedeemTransferOutNotPossible();\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We write the previously calculated values into storage.\n * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\n */\n totalSupply = totalSupply - redeemTokens;\n uint256 balanceAfter = accountTokens[redeemer] - redeemTokens;\n accountTokens[redeemer] = balanceAfter;\n\n /*\n * We invoke _doTransferOut for the receiver and the redeemAmount.\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 _doTransferOut(receiver, redeemAmount);\n\n /* We emit a Transfer event, and a Redeem event */\n emit Transfer(redeemer, address(this), redeemTokens);\n emit Redeem(redeemer, redeemAmount, redeemTokens, balanceAfter);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.redeemVerify(address(this), redeemer, redeemAmount, redeemTokens);\n }\n\n /**\n * @notice Users or their delegates borrow assets from the protocol\n * @param borrower User who borrows the assets\n * @param receiver The receiver of the tokens, if called by a delegate\n * @param borrowAmount The amount of the underlying asset to borrow\n */\n function _borrowFresh(address borrower, address receiver, uint256 borrowAmount) internal {\n /* Fail if borrow not allowed */\n comptroller.preBorrowHook(address(this), borrower, borrowAmount);\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert BorrowFreshnessCheck();\n }\n\n /* Fail gracefully if protocol has insufficient underlying cash */\n if (_getCashPrior() - totalReserves < borrowAmount) {\n revert BorrowCashNotAvailable();\n }\n\n /*\n * We calculate the new borrower and total borrow balances, failing on overflow:\n * accountBorrowNew = accountBorrow + borrowAmount\n * totalBorrowsNew = totalBorrows + borrowAmount\n */\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;\n uint256 totalBorrowsNew = totalBorrows + borrowAmount;\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We write the previously calculated values into storage.\n * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\n `*/\n accountBorrows[borrower].principal = accountBorrowsNew;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n /*\n * We invoke _doTransferOut for the receiver and the borrowAmount.\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, accountBorrowsNew, totalBorrowsNew);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\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 underlying tokens being returned, or type(uint256).max for the full outstanding amount\n * @return (uint) the actual repayment amount.\n */\n function _repayBorrowFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256) {\n /* Fail if repayBorrow not allowed */\n comptroller.preRepayHook(address(this), borrower);\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert RepayBorrowFreshnessCheck();\n }\n\n /* We fetch the amount the borrower owes, with accumulated interest */\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n\n uint256 repayAmountFinal = repayAmount >= accountBorrowsPrev ? accountBorrowsPrev : 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 * 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 uint256 actualRepayAmount = _doTransferIn(payer, repayAmountFinal);\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 uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\n uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;\n\n /* We write the previously calculated values into storage */\n accountBorrows[borrower].principal = accountBorrowsNew;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n /* We emit a RepayBorrow event */\n emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.repayBorrowVerify(address(this), payer, borrower, actualRepayAmount, borrowIndex);\n\n return actualRepayAmount;\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n */\n function _liquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) internal nonReentrant {\n accrueInterest();\n\n uint256 error = vTokenCollateral.accrueInterest();\n if (error != NO_ERROR) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\n revert LiquidateAccrueCollateralInterestFailed(error);\n }\n\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\n }\n\n /**\n * @notice The liquidator liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n */\n function _liquidateBorrowFresh(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) internal {\n /* Fail if liquidate not allowed */\n comptroller.preLiquidateHook(\n address(this),\n address(vTokenCollateral),\n borrower,\n repayAmount,\n skipLiquidityCheck\n );\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert LiquidateFreshnessCheck();\n }\n\n /* Verify vTokenCollateral market's slot(block or second) number equals current slot(block or second) number */\n if (vTokenCollateral.accrualBlockNumber() != getBlockNumberOrTimestamp()) {\n revert LiquidateCollateralFreshnessCheck();\n }\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n revert LiquidateLiquidatorIsBorrower();\n }\n\n /* Fail if repayAmount = 0 */\n if (repayAmount == 0) {\n revert LiquidateCloseAmountIsZero();\n }\n\n /* Fail if repayAmount = type(uint256).max */\n if (repayAmount == type(uint256).max) {\n revert LiquidateCloseAmountIsUintMax();\n }\n\n /* Fail if repayBorrow fails */\n uint256 actualRepayAmount = _repayBorrowFresh(liquidator, borrower, repayAmount);\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.liquidateCalculateSeizeTokens(\n address(this),\n address(vTokenCollateral),\n actualRepayAmount\n );\n require(amountSeizeError == 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, call _seize internally to avoid re-entrancy, otherwise make an external call\n if (address(vTokenCollateral) == address(this)) {\n _seize(address(this), liquidator, borrower, seizeTokens);\n } else {\n vTokenCollateral.seize(liquidator, borrower, seizeTokens);\n }\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\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 * It's absolutely critical to use msg.sender as the seizer vToken and not a parameter.\n * @param seizerContract The contract seizing the collateral (either borrowed vToken or Comptroller)\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 */\n function _seize(address seizerContract, address liquidator, address borrower, uint256 seizeTokens) internal {\n /* Fail if seize not allowed */\n comptroller.preSeizeHook(address(this), seizerContract, liquidator, borrower);\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n revert LiquidateSeizeLiquidatorIsBorrower();\n }\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 uint256 liquidationIncentiveMantissa = ComptrollerViewInterface(address(comptroller))\n .liquidationIncentiveMantissa();\n uint256 numerator = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));\n uint256 protocolSeizeTokens = div_(numerator, Exp({ mantissa: liquidationIncentiveMantissa }));\n uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\n uint256 protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the calculated values into storage */\n totalSupply = totalSupply - protocolSeizeTokens;\n accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\n accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\n\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\n _doTransferOut(protocolShareReserve, protocolSeizeAmount);\n\n // Update the pool asset's state in the protocol share reserve for the above transfer.\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\n address(comptroller),\n underlying,\n IProtocolShareReserve.IncomeType.LIQUIDATION\n );\n\n /* Emit a Transfer event */\n emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\n emit ProtocolSeize(borrower, protocolShareReserve, protocolSeizeAmount);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.seizeVerify(address(this), seizerContract, liquidator, borrower, seizeTokens);\n }\n\n function _setComptroller(ComptrollerInterface newComptroller) internal {\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\n /**\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\n * @dev Admin function to set a new reserve factor\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\n */\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal {\n // Verify market's slot(block or second) number equals current slot(block or second) number\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert SetReserveFactorFreshCheck();\n }\n\n // Check newReserveFactor ≤ maxReserveFactor\n if (newReserveFactorMantissa > MAX_RESERVE_FACTOR_MANTISSA) {\n revert SetReserveFactorBoundsCheck();\n }\n\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\n reserveFactorMantissa = newReserveFactorMantissa;\n\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\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 actualAddAmount The actual amount added, excluding the potential token fees\n */\n function _addReservesFresh(uint256 addAmount) internal returns (uint256) {\n // totalReserves + actualAddAmount\n uint256 totalReservesNew;\n uint256 actualAddAmount;\n\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert AddReservesFactorFreshCheck(actualAddAmount);\n }\n\n actualAddAmount = _doTransferIn(msg.sender, addAmount);\n totalReservesNew = totalReserves + actualAddAmount;\n totalReserves = totalReservesNew;\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\n\n return actualAddAmount;\n }\n\n /**\n * @notice Reduces reserves by transferring to the protocol reserve contract\n * @dev Requires fresh interest accrual\n * @param reduceAmount Amount of reduction to reserves\n */\n function _reduceReservesFresh(uint256 reduceAmount) internal {\n if (reduceAmount == 0) {\n return;\n }\n // totalReserves - reduceAmount\n uint256 totalReservesNew;\n\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert ReduceReservesFreshCheck();\n }\n\n // Fail gracefully if protocol has insufficient underlying cash\n if (_getCashPrior() < reduceAmount) {\n revert ReduceReservesCashNotAvailable();\n }\n\n // Check reduceAmount ≤ reserves[n] (totalReserves)\n if (reduceAmount > totalReserves) {\n revert ReduceReservesCashValidation();\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 // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\n _doTransferOut(protocolShareReserve, reduceAmount);\n\n // Update the pool asset's state in the protocol share reserve for the above transfer.\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\n address(comptroller),\n underlying,\n IProtocolShareReserve.IncomeType.SPREAD\n );\n\n emit SpreadReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\n }\n\n /**\n * @notice updates the interest rate model (*requires fresh interest accrual)\n * @dev Admin function to update the interest rate model\n * @param newInterestRateModel the new interest rate model to use\n */\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal {\n // Used to store old model for use in the event that is emitted on success\n InterestRateModel oldInterestRateModel;\n\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert SetInterestRateModelFreshCheck();\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\n /**\n * Safe Token **\n */\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 returns (uint256) {\n IERC20Upgradeable token = IERC20Upgradeable(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 * @param to Receiver of the underlying tokens\n * @param amount Amount of underlying to transfer\n */\n function _doTransferOut(address to, uint256 amount) internal virtual {\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\n internalCash -= amount;\n token.safeTransfer(to, amount);\n }\n\n /**\n * @notice Transfer `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 */\n function _transferTokens(address spender, address src, address dst, uint256 tokens) internal {\n /* Fail if transfer not allowed */\n comptroller.preTransferHook(address(this), src, dst, tokens);\n\n /* Do not allow self-transfers */\n if (src == dst) {\n revert TransferNotAllowed();\n }\n\n /* Get the allowance, infinite for the account owner */\n uint256 startingAllowance;\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 uint256 allowanceNew = startingAllowance - tokens;\n uint256 srcTokensNew = accountTokens[src] - tokens;\n uint256 dstTokensNew = accountTokens[dst] + tokens;\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n\n accountTokens[src] = srcTokensNew;\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\n /**\n * @notice Initialize the 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_ ERC-20 name of this token\n * @param symbol_ ERC-20 symbol of this token\n * @param decimals_ ERC-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param accessControlManager_ AccessControlManager contract address\n * @param riskManagement Addresses of risk & income related contracts\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\n */\n function _initialize(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address admin_,\n address accessControlManager_,\n RiskManagementInit memory riskManagement,\n uint256 reserveFactorMantissa_\n ) internal onlyInitializing {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\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 _setComptroller(comptroller_);\n\n // Initialize slot(block or second) number and borrow index (slot(block or second) number mocks depend on comptroller being set)\n accrualBlockNumber = getBlockNumberOrTimestamp();\n borrowIndex = MANTISSA_ONE;\n\n // Set the interest rate model (depends on slot(block or second) number / borrow index)\n _setInterestRateModelFresh(interestRateModel_);\n\n _setReserveFactorFresh(reserveFactorMantissa_);\n\n name = name_;\n symbol = symbol_;\n decimals = decimals_;\n _setShortfallContract(riskManagement.shortfall);\n _setProtocolShareReserve(riskManagement.protocolShareReserve);\n protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA;\n\n // Set underlying and sanity check it\n underlying = underlying_;\n IERC20Upgradeable(underlying).totalSupply();\n\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\n _notEntered = true;\n _transferOwnership(admin_);\n }\n\n function _setShortfallContract(address shortfall_) internal {\n ensureNonzeroAddress(shortfall_);\n address oldShortfall = shortfall;\n shortfall = shortfall_;\n emit NewShortfallContract(oldShortfall, shortfall_);\n }\n\n function _setProtocolShareReserve(address payable protocolShareReserve_) internal {\n ensureNonzeroAddress(protocolShareReserve_);\n address oldProtocolShareReserve = address(protocolShareReserve);\n protocolShareReserve = protocolShareReserve_;\n emit NewProtocolShareReserve(oldProtocolShareReserve, address(protocolShareReserve_));\n }\n\n function _ensureSenderIsDelegateOf(address user) internal view {\n if (!ComptrollerViewInterface(address(comptroller)).approvedDelegates(user, msg.sender)) {\n revert DelegateNotApproved();\n }\n }\n\n /**\n * @notice Gets the internally tracked cash balance of this market\n * @dev Returns the internalCash state variable, which is updated on transfers in/out\n * @return The quantity of underlying tokens tracked internally by this contract\n */\n function _getCashPrior() internal view virtual returns (uint256) {\n return internalCash;\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 borrowBalance the calculated balance\n */\n function _borrowBalanceStored(address account) internal view returns (uint256) {\n /* Get borrowBalance and borrowIndex */\n BorrowSnapshot memory 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 0;\n }\n\n /* Calculate new borrow balance using the interest index:\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\n */\n uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;\n\n return principalTimesIndex / borrowSnapshot.interestIndex;\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 exchangeRate Calculated exchange rate scaled by 1e18\n */\n function _exchangeRateStored() internal view virtual returns (uint256) {\n uint256 _totalSupply = totalSupply;\n if (_totalSupply == 0) {\n /*\n * If there are no tokens minted:\n * exchangeRate = initialExchangeRate\n */\n return initialExchangeRateMantissa;\n }\n /*\n * Otherwise:\n * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply\n */\n uint256 totalCash = _getCashPrior();\n uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;\n uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply;\n\n return exchangeRate;\n }\n}\n" + }, + "contracts/VTokenInterfaces.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\nimport { ComptrollerInterface } from \"./ComptrollerInterface.sol\";\nimport { InterestRateModel } from \"./InterestRateModel.sol\";\n\n/**\n * @title VTokenStorage\n * @author Venus\n * @notice Storage layout used by the `VToken` contract\n */\n// solhint-disable-next-line max-states-count\ncontract VTokenStorage {\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 uint256 principal;\n uint256 interestIndex;\n }\n\n /**\n * @dev Guard variable for re-entrancy checks\n */\n bool internal _notEntered;\n\n /**\n * @notice Underlying asset for this VToken\n */\n address public underlying;\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 Protocol share Reserve contract address\n */\n address payable public protocolShareReserve;\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 InterestRateModel public interestRateModel;\n\n // Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\n uint256 internal initialExchangeRateMantissa;\n\n /**\n * @notice Fraction of interest currently set aside for reserves\n */\n uint256 public reserveFactorMantissa;\n\n /**\n * @notice Slot(block or second) number that interest was last accrued at\n */\n uint256 public accrualBlockNumber;\n\n /**\n * @notice Accumulator of the total earned interest rate since the opening of the market\n */\n uint256 public borrowIndex;\n\n /**\n * @notice Total amount of outstanding borrows of the underlying in this market\n */\n uint256 public totalBorrows;\n\n /**\n * @notice Total amount of reserves of the underlying held in this market\n */\n uint256 public totalReserves;\n\n /**\n * @notice Total number of tokens in circulation\n */\n uint256 public totalSupply;\n\n /**\n * @notice Total bad debt of the market\n */\n uint256 public badDebt;\n\n // Official record of token balances for each account\n mapping(address => uint256) internal accountTokens;\n\n // Approved token transfer amounts on behalf of others\n mapping(address => mapping(address => uint256)) internal transferAllowances;\n\n // Mapping of account addresses to outstanding borrow balances\n mapping(address => BorrowSnapshot) internal accountBorrows;\n\n /**\n * @notice Share of seized collateral that is added to reserves\n */\n uint256 public protocolSeizeShareMantissa;\n\n /**\n * @notice Storage of Shortfall contract address\n */\n address public shortfall;\n\n /**\n * @notice delta slot (block or second) after which reserves will be reduced\n */\n uint256 public reduceReservesBlockDelta;\n\n /**\n * @notice last slot (block or second) number at which reserves were reduced\n */\n uint256 public reduceReservesBlockNumber;\n\n /**\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\n * @dev Updated via _doTransferIn(), _doTransferOut(), syncCash(), and badDebtRecovered(). Must be initialized via syncCash() 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[47] private __gap;\n}\n\n/**\n * @title VTokenInterface\n * @author Venus\n * @notice Interface implemented by the `VToken` contract\n */\nabstract contract VTokenInterface is VTokenStorage {\n struct RiskManagementInit {\n address shortfall;\n address payable protocolShareReserve;\n }\n\n /*** Market Events ***/\n\n /**\n * @notice Event emitted when interest is accrued\n */\n event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\n\n /**\n * @notice Event emitted when tokens are minted\n */\n event Mint(address indexed minter, uint256 mintAmount, uint256 mintTokens, uint256 accountBalance);\n\n /**\n * @notice Event emitted when tokens are redeemed\n */\n event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens, uint256 accountBalance);\n\n /**\n * @notice Event emitted when underlying is borrowed\n */\n event Borrow(address indexed borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\n\n /**\n * @notice Event emitted when a borrow is repaid\n */\n event RepayBorrow(\n address indexed payer,\n address indexed borrower,\n uint256 repayAmount,\n uint256 accountBorrows,\n uint256 totalBorrows\n );\n\n /**\n * @notice Event emitted when bad debt is accumulated on a market\n * @param borrower borrower to \"forgive\"\n * @param badDebtDelta amount of new bad debt recorded\n * @param badDebtOld previous bad debt value\n * @param badDebtNew new bad debt value\n */\n event BadDebtIncreased(address indexed borrower, uint256 badDebtDelta, uint256 badDebtOld, uint256 badDebtNew);\n\n /**\n * @notice Event emitted when bad debt is recovered via an auction\n * @param badDebtOld previous bad debt value\n * @param badDebtNew new bad debt value\n */\n event BadDebtRecovered(uint256 badDebtOld, uint256 badDebtNew);\n\n /**\n * @notice Event emitted when a borrow is liquidated\n */\n event LiquidateBorrow(\n address indexed liquidator,\n address indexed borrower,\n uint256 repayAmount,\n address indexed vTokenCollateral,\n uint256 seizeTokens\n );\n\n /*** Admin Events ***/\n\n /**\n * @notice Event emitted when comptroller is changed\n */\n event NewComptroller(ComptrollerInterface indexed oldComptroller, ComptrollerInterface indexed newComptroller);\n\n /**\n * @notice Event emitted when shortfall contract address is changed\n */\n event NewShortfallContract(address indexed oldShortfall, address indexed newShortfall);\n\n /**\n * @notice Event emitted when protocol share reserve contract address is changed\n */\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\n\n /**\n * @notice Event emitted when interestRateModel is changed\n */\n event NewMarketInterestRateModel(\n InterestRateModel indexed oldInterestRateModel,\n InterestRateModel indexed newInterestRateModel\n );\n\n /**\n * @notice Event emitted when protocol seize share is changed\n */\n event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\n\n /**\n * @notice Event emitted when the reserve factor is changed\n */\n event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\n\n /**\n * @notice Event emitted when the reserves are added\n */\n event ReservesAdded(address indexed benefactor, uint256 addAmount, uint256 newTotalReserves);\n\n /**\n * @notice Event emitted when the spread reserves are reduced\n */\n event SpreadReservesReduced(address indexed protocolShareReserve, uint256 reduceAmount, uint256 newTotalReserves);\n\n /**\n * @notice EIP20 Transfer event\n */\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n /**\n * @notice EIP20 Approval event\n */\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /**\n * @notice Event emitted when healing the borrow\n */\n event HealBorrow(address indexed payer, address indexed borrower, uint256 repayAmount);\n\n /**\n * @notice Event emitted when tokens are swept\n */\n event SweepToken(address indexed token);\n\n /**\n * @notice Event emitted when reduce reserves slot (block or second) delta is changed\n */\n event NewReduceReservesBlockDelta(\n uint256 oldReduceReservesBlockOrTimestampDelta,\n uint256 newReduceReservesBlockOrTimestampDelta\n );\n\n /**\n * @notice Event emitted when liquidation reserves are reduced\n */\n event ProtocolSeize(address indexed from, address indexed to, uint256 amount);\n\n /**\n * @notice Event emitted when internalCash is synced with actual token balance\n */\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\n\n /*** User Interface ***/\n\n function mint(uint256 mintAmount) external virtual returns (uint256);\n\n function mintBehalf(address minter, uint256 mintAllowed) external virtual returns (uint256);\n\n function redeem(uint256 redeemTokens) external virtual returns (uint256);\n\n function redeemBehalf(address redeemer, uint256 redeemTokens) external virtual returns (uint256);\n\n function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);\n\n function redeemUnderlyingBehalf(address redeemer, uint256 redeemAmount) external virtual returns (uint256);\n\n function borrow(uint256 borrowAmount) external virtual returns (uint256);\n\n function borrowBehalf(address borrwwer, uint256 borrowAmount) external virtual returns (uint256);\n\n function repayBorrow(uint256 repayAmount) external virtual returns (uint256);\n\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);\n\n function liquidateBorrow(\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) external virtual returns (uint256);\n\n function healBorrow(address payer, address borrower, uint256 repayAmount) external virtual;\n\n function forceLiquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipCloseFactorCheck\n ) external virtual;\n\n function seize(address liquidator, address borrower, uint256 seizeTokens) external virtual;\n\n function transfer(address dst, uint256 amount) external virtual returns (bool);\n\n function transferFrom(address src, address dst, uint256 amount) external virtual returns (bool);\n\n function accrueInterest() external virtual returns (uint256);\n\n function sweepToken(IERC20Upgradeable token) external virtual;\n\n /*** Admin Functions ***/\n\n function setReserveFactor(uint256 newReserveFactorMantissa) external virtual;\n\n function reduceReserves(uint256 reduceAmount) external virtual;\n\n function exchangeRateCurrent() external virtual returns (uint256);\n\n function borrowBalanceCurrent(address account) external virtual returns (uint256);\n\n function setInterestRateModel(InterestRateModel newInterestRateModel) external virtual;\n\n function addReserves(uint256 addAmount) external virtual;\n\n function syncCash() external virtual;\n\n function totalBorrowsCurrent() external virtual returns (uint256);\n\n function balanceOfUnderlying(address owner) external virtual returns (uint256);\n\n function approve(address spender, uint256 amount) external virtual returns (bool);\n\n function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool);\n\n function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool);\n\n function allowance(address owner, address spender) external view virtual returns (uint256);\n\n function balanceOf(address owner) external view virtual returns (uint256);\n\n function getAccountSnapshot(address account) external view virtual returns (uint256, uint256, uint256, uint256);\n\n function borrowRatePerBlock() external view virtual returns (uint256);\n\n function supplyRatePerBlock() external view virtual returns (uint256);\n\n function borrowBalanceStored(address account) external view virtual returns (uint256);\n\n function exchangeRateStored() external view virtual returns (uint256);\n\n function getCash() external view virtual returns (uint256);\n\n /**\n * @notice Indicator that this is a VToken contract (for inspection)\n * @return Always true\n */\n function isVToken() external pure virtual returns (bool) {\n return true;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200, + "details": { + "yul": true + } + }, + "evmVersion": "paris", + "outputSelection": { + "*": { + "*": [ + "storageLayout", + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} diff --git a/deployments/arbitrumone_addresses.json b/deployments/arbitrumone_addresses.json index de29290ac..6951ea3d8 100644 --- a/deployments/arbitrumone_addresses.json +++ b/deployments/arbitrumone_addresses.json @@ -16,7 +16,7 @@ "JumpRateModelV2_base0bps_slope900bps_jump30000bps_kink4500bps_timeBased": "0x88C409Bf5b604F70505C1eC594D8155489B1d8b2", "NativeTokenGateway_vWETH_Core": "0xc8e51418cadc001157506b306C6d0b878f1ff755", "NativeTokenGateway_vWETH_LiquidStakedETH": "0xD1e89806BAB8Cd7680DFc7425D1fA6d7D5F0C3FE", - "PoolLens": "0x53F34FF95367B2A4542461a6A63fD321F8da22AD", + "PoolLens": "0x7603e9aD2b5f758C8eb8480Ed9Cb1509BeDB126c", "PoolRegistry": "0x382238f07Bc4Fe4aA99e561adE8A4164b5f815DA", "PoolRegistry_Implementation": "0xc9A9594e774F9454e4665126C72Eb62643253aB0", "PoolRegistry_Proxy": "0x382238f07Bc4Fe4aA99e561adE8A4164b5f815DA", diff --git a/deployments/basemainnet.json b/deployments/basemainnet.json index 137f303ef..92fe1b4db 100644 --- a/deployments/basemainnet.json +++ b/deployments/basemainnet.json @@ -4292,7 +4292,7 @@ ] }, "PoolLens": { - "address": "0x89825677fb4845f5Fc0B227e387455ECa1200058", + "address": "0x70F86E84CfB7c5bd8E845aC643c2BDBFf811F335", "abi": [ { "inputs": [ @@ -4305,6 +4305,11 @@ "internalType": "uint256", "name": "blocksPerYear_", "type": "uint256" + }, + { + "internalType": "address", + "name": "corePoolComptroller_", + "type": "address" } ], "stateMutability": "nonpayable", @@ -4333,6 +4338,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "corePoolComptroller", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { diff --git a/deployments/basemainnet/PoolLens.json b/deployments/basemainnet/PoolLens.json index 38b545c57..3e73189fd 100644 --- a/deployments/basemainnet/PoolLens.json +++ b/deployments/basemainnet/PoolLens.json @@ -1,5 +1,5 @@ { - "address": "0x89825677fb4845f5Fc0B227e387455ECa1200058", + "address": "0x70F86E84CfB7c5bd8E845aC643c2BDBFf811F335", "abi": [ { "inputs": [ @@ -12,6 +12,11 @@ "internalType": "uint256", "name": "blocksPerYear_", "type": "uint256" + }, + { + "internalType": "address", + "name": "corePoolComptroller_", + "type": "address" } ], "stateMutability": "nonpayable", @@ -40,6 +45,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "corePoolComptroller", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -1168,28 +1186,28 @@ "type": "function" } ], - "transactionHash": "0x3e0a6b6322f47c37b63dac0a3036deff5e122bce43992f6f6f39c81592fb487f", + "transactionHash": "0x8c3f8926e1227825e5ccd655a57fccfd9f1e9f0704802d64f549c351b43777d3", "receipt": { "to": null, - "from": "0xdB7a865041d965f575CAB277783fF490508A21F3", - "contractAddress": "0x89825677fb4845f5Fc0B227e387455ECa1200058", - "transactionIndex": 83, - "gasUsed": "3524220", + "from": "0x1461d2EcE51c07E88A54dB77Dade74a5B364037D", + "contractAddress": "0x70F86E84CfB7c5bd8E845aC643c2BDBFf811F335", + "transactionIndex": 135, + "gasUsed": "3593126", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x46823c73edbfd9c64107fc76016e8c0f891de0cbcf101ad39098512fe55c9eb0", - "transactionHash": "0x3e0a6b6322f47c37b63dac0a3036deff5e122bce43992f6f6f39c81592fb487f", + "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "transactionHash": "0x8c3f8926e1227825e5ccd655a57fccfd9f1e9f0704802d64f549c351b43777d3", "logs": [], - "blockNumber": 23344414, - "cumulativeGasUsed": "18194395", + "blockNumber": 44085905, + "cumulativeGasUsed": "51376654", "status": 1, "byzantium": true }, - "args": [true, 0], - "numDeployments": 1, - "solcInputHash": "1cc1a300ca8c782ec718d1d686c359e7", - "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"timeBased_\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"blocksPerYear_\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidBlocksPerYear\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTimeBasedConfiguration\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"blocksOrSecondsPerYear\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"}],\"name\":\"getAllPools\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockNumberOrTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getPendingRewards\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"distributorAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"rewardTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalRewards\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.PendingReward[]\",\"name\":\"pendingRewards\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.RewardSummary[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getPoolBadDebt\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalBadDebtUsd\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"badDebtUsd\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.BadDebt[]\",\"name\":\"badDebts\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.BadDebtSummary\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolByComptroller\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolRegistryInterface.VenusPool\",\"name\":\"venusPool\",\"type\":\"tuple\"}],\"name\":\"getPoolDataFromVenusPool\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getPoolsSupportedByAsset\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getVTokenForAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isTimeBased\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"vTokenBalances\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalanceCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balanceOfUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenAllowance\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenBalances\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"vTokenBalancesAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalanceCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balanceOfUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenAllowance\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenBalances[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"vTokenMetadata\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"vTokenMetadataAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"vTokenUnderlyingPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"underlyingPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenUnderlyingPrice\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"vTokenUnderlyingPriceAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"underlyingPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenUnderlyingPrice[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"params\":{\"blocksPerYear_\":\"The number of blocks per year\",\"timeBased_\":\"A boolean indicating whether the contract is based on time or block.\"}},\"getAllPools(address)\":{\"details\":\"This function is not designed to be called in a transaction: it is too gas-intensive\",\"params\":{\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"Arrays of all Venus pools' data\"}},\"getBlockNumberOrTimestamp()\":{\"details\":\"Function to simply retrieve block number or block timestamp\",\"returns\":{\"_0\":\"Current block number or block timestamp\"}},\"getPendingRewards(address,address)\":{\"params\":{\"account\":\"The user account.\",\"comptrollerAddress\":\"address\"},\"returns\":{\"_0\":\"Pending rewards array\"}},\"getPoolBadDebt(address)\":{\"params\":{\"comptrollerAddress\":\"Address of the comptroller\"},\"returns\":{\"_0\":\"badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and a break down of bad debt by market\"}},\"getPoolByComptroller(address,address)\":{\"params\":{\"comptroller\":\"The Comptroller implementation address\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"PoolData structure containing the details of the pool\"}},\"getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))\":{\"params\":{\"poolRegistryAddress\":\"Address of the PoolRegistry\",\"venusPool\":\"The VenusPool Object from PoolRegistry\"},\"returns\":{\"_0\":\"Enriched PoolData\"}},\"getPoolsSupportedByAsset(address,address)\":{\"params\":{\"asset\":\"The underlying asset of vToken\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"A list of Comptroller contracts\"}},\"getVTokenForAsset(address,address,address)\":{\"params\":{\"asset\":\"The underlyingAsset of VToken\",\"comptroller\":\"The pool comptroller\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"Address of the vToken\"}},\"vTokenBalances(address,address)\":{\"params\":{\"account\":\"The user Account\",\"vToken\":\"vToken address\"},\"returns\":{\"_0\":\"A struct containing the balances data\"}},\"vTokenBalancesAll(address[],address)\":{\"params\":{\"account\":\"The user Account\",\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"A list of structs containing balances data\"}},\"vTokenMetadata(address)\":{\"params\":{\"vToken\":\"The address of vToken\"},\"returns\":{\"_0\":\"VTokenMetadata struct\"}},\"vTokenMetadataAll(address[])\":{\"params\":{\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"An array of VTokenMetadata structs\"}},\"vTokenUnderlyingPrice(address)\":{\"params\":{\"vToken\":\"vToken address\"},\"returns\":{\"_0\":\"The price data for each asset\"}},\"vTokenUnderlyingPriceAll(address[])\":{\"params\":{\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"An array containing the price data for each asset\"}}},\"title\":\"PoolLens\",\"version\":1},\"userdoc\":{\"errors\":{\"InvalidBlocksPerYear()\":[{\"notice\":\"Thrown when blocks per year is invalid\"}],\"InvalidTimeBasedConfiguration()\":[{\"notice\":\"Thrown when time based but blocks per year is provided\"}]},\"kind\":\"user\",\"methods\":{\"blocksOrSecondsPerYear()\":{\"notice\":\"Stores blocksPerYear if isTimeBased is true else secondsPerYear is stored\"},\"getAllPools(address)\":{\"notice\":\"Queries all pools with addtional details for each of them\"},\"getPendingRewards(address,address)\":{\"notice\":\"Returns the pending rewards for a user for a given pool.\"},\"getPoolBadDebt(address)\":{\"notice\":\"Returns a summary of a pool's bad debt broken down by market\"},\"getPoolByComptroller(address,address)\":{\"notice\":\"Queries the details of a pool identified by Comptroller address\"},\"getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))\":{\"notice\":\"Queries additional information for the pool\"},\"getPoolsSupportedByAsset(address,address)\":{\"notice\":\"Returns all pools that support the specified underlying asset\"},\"getVTokenForAsset(address,address,address)\":{\"notice\":\"Returns vToken holding the specified underlying asset in the specified pool\"},\"isTimeBased()\":{\"notice\":\"Acknowledges if a contract is time based or not\"},\"vTokenBalances(address,address)\":{\"notice\":\"Queries the user's supply/borrow balances in the specified vToken\"},\"vTokenBalancesAll(address[],address)\":{\"notice\":\"Queries the user's supply/borrow balances in vTokens\"},\"vTokenMetadata(address)\":{\"notice\":\"Returns the metadata of VToken\"},\"vTokenMetadataAll(address[])\":{\"notice\":\"Returns the metadata of all VTokens\"},\"vTokenUnderlyingPrice(address)\":{\"notice\":\"Returns the price data for the underlying asset of the specified vToken\"},\"vTokenUnderlyingPriceAll(address[])\":{\"notice\":\"Returns the price data for the underlying assets of the specified vTokens\"}},\"notice\":\"The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be looked up for specific pools and markets: - the vToken balance of a given user; - the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address; - the vToken address in a pool for a given asset; - a list of all pools that support an asset; - the underlying asset price of a vToken; - the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Lens/PoolLens.sol\":\"PoolLens\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"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\",\"keccak256\":\"0x9140dabc466abab21b48b72dbda26736b1183a310d0e677d3719d201df026510\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x359a1ab89b46b9aba7bcad3fb651924baf4893d15153049b9976b0fc9be1358e\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x07e881de3b9f6d2c07909f193f24b96c7fe4ea60013260f3f25aecd8bab3c2f8\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x75097e35253e7fb282ee4d7f27a80eaacfa759923185bf17302a89cbc059c5ef\",\"license\":\"MIT\"},\"@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\"},\"@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 private _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\",\"keccak256\":\"0x0dcf283925f4dddc23ca0ee71d2cb96a9dd6e4cf08061b69fde1697ea39dc514\",\"license\":\"BSD-3-Clause\"},\"@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/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface IProtocolShareReserve {\\n /// @notice it represents the type of vToken income\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION\\n }\\n\\n function updateAssetsState(\\n address comptroller,\\n address asset,\\n IncomeType incomeType\\n ) external;\\n}\\n\",\"keccak256\":\"0x5fddc5b63fdd850b3b5c83576cda50dcb27a205dbb1a23af17d9da0d9f04fa0a\",\"license\":\"BSD-3-Clause\"},\"@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\",\"keccak256\":\"0x57a2bbb9b8e02b1c0a5c0e305fef1328a22db56c3d4b148c362010a6e767243c\",\"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\"},\"@venusprotocol/venus-protocol/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\",\"keccak256\":\"0xd112f60183416ad796093b4a83a80ddc1b8b655965f02ae55ca82e2a0c68f97d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/venus-protocol/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\",\"keccak256\":\"0x5285c875114db2ea2be0b81b65722d5761806217022db733323c4e03365a95e7\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IPrime } from \\\"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\\\";\\n\\nimport { ComptrollerInterface, Action } from \\\"./ComptrollerInterface.sol\\\";\\nimport { ComptrollerStorage } from \\\"./ComptrollerStorage.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"./MaxLoopsLimitHelper.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title Comptroller\\n * @author Venus\\n * @notice The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating,\\n * and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts\\n * with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows\\n * or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing\\n * liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow,\\n * as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the\\n * markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market\\u2019s corresponding liquidation threshold,\\n * the borrow is eligible for liquidation.\\n *\\n * The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed\\n * the `minLiquidatableCollateral` for the `Comptroller`:\\n *\\n * - `healAccount()`: This function is called to seize all of a given user\\u2019s collateral, requiring the `msg.sender` repay a certain percentage\\n * of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed\\n * 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt\\n * and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool.\\n * - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation\\n * incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic\\n * verifying that the repay amount does not exceed the close factor.\\n */\\ncontract Comptroller is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n ComptrollerStorage,\\n ComptrollerInterface,\\n ExponentialNoError,\\n MaxLoopsLimitHelper\\n{\\n // PoolRegistry, immutable to save on gas\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable poolRegistry;\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(VToken indexed vToken, address indexed account);\\n\\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(VToken vToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa);\\n\\n /// @notice Emitted when liquidation threshold is changed by admin\\n event NewLiquidationThreshold(\\n VToken vToken,\\n uint256 oldLiquidationThresholdMantissa,\\n uint256 newLiquidationThresholdMantissa\\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 an action is paused on a market\\n event ActionPausedMarket(VToken vToken, Action action, bool pauseState);\\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 the collateral threshold (in USD) for non-batch liquidations is changed\\n event NewMinLiquidatableCollateral(uint256 oldMinLiquidatableCollateral, uint256 newMinLiquidatableCollateral);\\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 a rewards distributor is added\\n event NewRewardsDistributor(address indexed rewardsDistributor, address indexed rewardToken);\\n\\n /// @notice Emitted when a market is supported\\n event MarketSupported(VToken vToken);\\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 a market\\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\\n\\n /// @notice Emitted when a market is unlisted\\n event MarketUnlisted(address indexed vToken);\\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 Thrown when collateral factor exceeds the upper bound\\n error InvalidCollateralFactor();\\n\\n /// @notice Thrown when liquidation threshold exceeds the collateral factor\\n error InvalidLiquidationThreshold();\\n\\n /// @notice Thrown when the action is only available to specific sender, but the real sender was different\\n error UnexpectedSender(address expectedSender, address actualSender);\\n\\n /// @notice Thrown when the oracle returns an invalid price for some asset\\n error PriceError(address vToken);\\n\\n /// @notice Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\\n error SnapshotError(address vToken, address user);\\n\\n /// @notice Thrown when the market is not listed\\n error MarketNotListed(address market);\\n\\n /// @notice Thrown when a market has an unexpected comptroller\\n error ComptrollerMismatch();\\n\\n /// @notice Thrown when user is not member of market\\n error MarketNotCollateral(address vToken, address user);\\n\\n /// @notice Thrown when borrow action is not paused\\n error BorrowActionNotPaused();\\n\\n /// @notice Thrown when mint action is not paused\\n error MintActionNotPaused();\\n\\n /// @notice Thrown when redeem action is not paused\\n error RedeemActionNotPaused();\\n\\n /// @notice Thrown when repay action is not paused\\n error RepayActionNotPaused();\\n\\n /// @notice Thrown when seize action is not paused\\n error SeizeActionNotPaused();\\n\\n /// @notice Thrown when exit market action is not paused\\n error ExitMarketActionNotPaused();\\n\\n /// @notice Thrown when transfer action is not paused\\n error TransferActionNotPaused();\\n\\n /// @notice Thrown when enter market action is not paused\\n error EnterMarketActionNotPaused();\\n\\n /// @notice Thrown when liquidate action is not paused\\n error LiquidateActionNotPaused();\\n\\n /// @notice Thrown when borrow cap is not zero\\n error BorrowCapIsNotZero();\\n\\n /// @notice Thrown when supply cap is not zero\\n error SupplyCapIsNotZero();\\n\\n /// @notice Thrown when collateral factor is not zero\\n error CollateralFactorIsNotZero();\\n\\n /**\\n * @notice Thrown during the liquidation if user's total collateral amount is lower than\\n * a predefined threshold. In this case only batch liquidations (either liquidateAccount\\n * or healAccount) are available.\\n */\\n error MinimalCollateralViolated(uint256 expectedGreaterThan, uint256 actual);\\n error CollateralExceedsThreshold(uint256 expectedLessThanOrEqualTo, uint256 actual);\\n error InsufficientCollateral(uint256 collateralToSeize, uint256 availableCollateral);\\n\\n /// @notice Thrown when the account doesn't have enough liquidity to redeem or borrow\\n error InsufficientLiquidity();\\n\\n /// @notice Thrown when trying to liquidate a healthy account\\n error InsufficientShortfall();\\n\\n /// @notice Thrown when trying to repay more than allowed by close factor\\n error TooMuchRepay();\\n\\n /// @notice Thrown if the user is trying to exit a market in which they have an outstanding debt\\n error NonzeroBorrowBalance();\\n\\n /// @notice Thrown when trying to perform an action that is paused\\n error ActionPaused(address market, Action action);\\n\\n /// @notice Thrown when trying to add a market that is already listed\\n error MarketAlreadyListed(address market);\\n\\n /// @notice Thrown if the supply cap is exceeded\\n error SupplyCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if the borrow cap is exceeded\\n error BorrowCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if delegate approval status is already set to the requested value\\n error DelegationStatusUnchanged();\\n\\n /// @param poolRegistry_ Pool registry address\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n constructor(address poolRegistry_) {\\n ensureNonzeroAddress(poolRegistry_);\\n\\n poolRegistry = poolRegistry_;\\n _disableInitializers();\\n }\\n\\n /**\\n * @param loopLimit Limit for the loops can iterate to avoid the DOS\\n * @param accessControlManager Access control manager contract address\\n */\\n function initialize(uint256 loopLimit, address accessControlManager) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager);\\n\\n _setMaxLoopsLimit(loopLimit);\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation; enabling them to be used as collateral\\n * @param vTokens The list of addresses of the vToken markets to be enabled\\n * @return errors An array of NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketEntered is emitted for each market on success\\n * @custom:error ActionPaused error is thrown if entering any of the markets is paused\\n * @custom:error MarketNotListed error is thrown if any of the markets is not listed\\n * @custom:access Not restricted\\n */\\n function enterMarkets(address[] memory vTokens) external override returns (uint256[] memory) {\\n uint256 len = vTokens.length;\\n\\n uint256[] memory results = new uint256[](len);\\n for (uint256 i; i < len; ++i) {\\n VToken vToken = VToken(vTokens[i]);\\n\\n _addToMarket(vToken, msg.sender);\\n results[i] = NO_ERROR;\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Unlist a market by setting isListed to false\\n * @dev Checks if all actions are paused, borrow/supply caps is set to 0 and collateral factor is to 0.\\n * @param market The address of the market (token) to unlist\\n * @return uint256 Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketUnlisted is emitted on success\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error BorrowActionNotPaused error is thrown if borrow action is not paused\\n * @custom:error MintActionNotPaused error is thrown if mint action is not paused\\n * @custom:error RedeemActionNotPaused error is thrown if redeem action is not paused\\n * @custom:error RepayActionNotPaused error is thrown if repay action is not paused\\n * @custom:error EnterMarketActionNotPaused error is thrown if enter market action is not paused\\n * @custom:error LiquidateActionNotPaused error is thrown if liquidate action is not paused\\n * @custom:error BorrowCapIsNotZero error is thrown if borrow cap is not zero\\n * @custom:error SupplyCapIsNotZero error is thrown if supply cap is not zero\\n * @custom:error CollateralFactorIsNotZero error is thrown if collateral factor is not zero\\n */\\n function unlistMarket(address market) external returns (uint256) {\\n _checkAccessAllowed(\\\"unlistMarket(address)\\\");\\n\\n Market storage _market = markets[market];\\n\\n if (!_market.isListed) {\\n revert MarketNotListed(market);\\n }\\n\\n if (!actionPaused(market, Action.BORROW)) {\\n revert BorrowActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.MINT)) {\\n revert MintActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.REDEEM)) {\\n revert RedeemActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.REPAY)) {\\n revert RepayActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.SEIZE)) {\\n revert SeizeActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.ENTER_MARKET)) {\\n revert EnterMarketActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.LIQUIDATE)) {\\n revert LiquidateActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.TRANSFER)) {\\n revert TransferActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.EXIT_MARKET)) {\\n revert ExitMarketActionNotPaused();\\n }\\n\\n if (borrowCaps[market] != 0) {\\n revert BorrowCapIsNotZero();\\n }\\n\\n if (supplyCaps[market] != 0) {\\n revert SupplyCapIsNotZero();\\n }\\n\\n if (_market.collateralFactorMantissa != 0) {\\n revert CollateralFactorIsNotZero();\\n }\\n\\n _market.isListed = false;\\n emit MarketUnlisted(market);\\n\\n return NO_ERROR;\\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 * @custom:event DelegateUpdated emits on success\\n * @custom:error ZeroAddressNotAllowed is thrown when delegate address is zero\\n * @custom:error DelegationStatusUnchanged is thrown if approval status is already set to the requested value\\n * @custom:access Not restricted\\n */\\n function updateDelegate(address delegate, bool approved) external {\\n ensureNonzeroAddress(delegate);\\n if (approvedDelegates[msg.sender][delegate] == approved) {\\n revert DelegationStatusUnchanged();\\n }\\n\\n approvedDelegates[msg.sender][delegate] = approved;\\n emit DelegateUpdated(msg.sender, delegate, approved);\\n }\\n\\n /**\\n * @notice Removes asset from sender's account liquidity calculation; disabling them as collateral\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketExited is emitted on success\\n * @custom:error ActionPaused error is thrown if exiting the market is paused\\n * @custom:error NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function exitMarket(address vTokenAddress) external override returns (uint256) {\\n _checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\\n VToken vToken = VToken(vTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\\n (uint256 tokensHeld, uint256 amountOwed, ) = _safeGetAccountSnapshot(vToken, msg.sender);\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n revert NonzeroBorrowBalance();\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n _checkRedeemAllowed(vTokenAddress, msg.sender, tokensHeld);\\n\\n Market storage marketToExit = markets[address(vToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return 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 // load into memory for faster iteration\\n VToken[] memory userAssetList = accountAssets[msg.sender];\\n uint256 len = userAssetList.length;\\n\\n uint256 assetIndex = len;\\n for (uint256 i; i < len; ++i) {\\n if (userAssetList[i] == vToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n VToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.pop();\\n\\n emit MarketExited(vToken, msg.sender);\\n\\n return NO_ERROR;\\n }\\n\\n /*** Policy Hooks ***/\\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 * @custom:error ActionPaused error is thrown if supplying to this market is paused\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\\n * @custom:access Not restricted\\n */\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external override {\\n _checkActionPauseState(vToken, Action.MINT);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n uint256 supplyCap = supplyCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (supplyCap != type(uint256).max) {\\n uint256 vTokenSupply = VToken(vToken).totalSupply();\\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\\n if (nextTotalSupply > supplyCap) {\\n revert SupplyCapExceeded(vToken, supplyCap);\\n }\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, minter);\\n }\\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external override {\\n _checkActionPauseState(vToken, Action.REDEEM);\\n\\n _checkRedeemAllowed(vToken, redeemer, redeemTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, redeemer);\\n }\\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 if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(redeemer, vToken);\\n }\\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 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 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 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 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 * @custom:error ActionPaused error is thrown if borrowing is paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if there is not enough collateral to borrow\\n * @custom:error BorrowCapExceeded is thrown if the borrow cap will be exceeded should this borrow succeed\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted if vToken is enabled as collateral, otherwise only vToken\\n */\\n /// disable-eslint\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external override {\\n _checkActionPauseState(vToken, Action.BORROW);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (!markets[vToken].accountMembership[borrower]) {\\n // only vTokens may call borrowAllowed if borrower not in market\\n _checkSenderIs(vToken);\\n\\n // attempt to add borrower to the market or revert\\n _addToMarket(VToken(msg.sender), borrower);\\n }\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (oracle.getUnderlyingPrice(vToken) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 borrowCap = borrowCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (borrowCap != type(uint256).max) {\\n uint256 totalBorrows = VToken(vToken).totalBorrows();\\n uint256 badDebt = VToken(vToken).badDebt();\\n uint256 nextTotalBorrows = totalBorrows + borrowAmount + badDebt;\\n if (nextTotalBorrows > borrowCap) {\\n revert BorrowCapExceeded(vToken, borrowCap);\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n borrower,\\n VToken(vToken),\\n 0,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\n }\\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 borrower The account which would borrowed the asset\\n * @custom:error ActionPaused error is thrown if repayments are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:access Not restricted\\n */\\n function preRepayHook(address vToken, address borrower) external override {\\n _checkActionPauseState(vToken, Action.REPAY);\\n\\n oracle.updatePrice(vToken);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\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 borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n * @param skipLiquidityCheck Allows the borrow to be liquidated regardless of the account liquidity\\n * @custom:error ActionPaused error is thrown if liquidations are paused in this market\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor\\n * @custom:error MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations\\n * @custom:error InsufficientShortfall is thrown when trying to liquidate a healthy account\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n */\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external override {\\n // Pause Action.LIQUIDATE on BORROWED TOKEN to prevent liquidating it.\\n // If we want to pause liquidating to vTokenCollateral, we should pause\\n // Action.SEIZE on it\\n _checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(address(vTokenBorrowed));\\n }\\n if (!markets[vTokenCollateral].isListed) {\\n revert MarketNotListed(address(vTokenCollateral));\\n }\\n\\n uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\\n\\n /* Allow accounts to be liquidated if it is a forced liquidation */\\n if (skipLiquidityCheck || isForcedLiquidationEnabled[vTokenBorrowed]) {\\n if (repayAmount > borrowBalance) {\\n revert TooMuchRepay();\\n }\\n return;\\n }\\n\\n /* The borrower must have shortfall and collateral > threshold in order to be liquidatable */\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral <= minLiquidatableCollateral) {\\n /* The liquidator should use either liquidateAccount or healAccount */\\n revert MinimalCollateralViolated(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint256 maxClose = mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance);\\n if (repayAmount > maxClose) {\\n revert TooMuchRepay();\\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 seizerContract Contract that tries to seize the asset (either borrowed vToken or Comptroller)\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @custom:error ActionPaused error is thrown if seizing this type of collateral is paused\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error ComptrollerMismatch error is when seizer contract or seized asset belong to different pools\\n * @custom:access Not restricted\\n */\\n function preSeizeHook(\\n address vTokenCollateral,\\n address seizerContract,\\n address liquidator,\\n address borrower\\n ) external override {\\n // Pause Action.SEIZE on COLLATERAL to prevent seizing it.\\n // If we want to pause liquidating vTokenBorrowed, we should pause\\n // Action.LIQUIDATE on it\\n _checkActionPauseState(vTokenCollateral, Action.SEIZE);\\n\\n Market storage market = markets[vTokenCollateral];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(vTokenCollateral);\\n }\\n\\n if (seizerContract == address(this)) {\\n // If Comptroller is the seizer, just check if collateral's comptroller\\n // is equal to the current address\\n if (address(VToken(vTokenCollateral).comptroller()) != address(this)) {\\n revert ComptrollerMismatch();\\n }\\n } else {\\n // If the seizer is not the Comptroller, check that the seizer is a\\n // listed market, and that the markets' comptrollers match\\n if (!markets[seizerContract].isListed) {\\n revert MarketNotListed(seizerContract);\\n }\\n if (VToken(vTokenCollateral).comptroller() != VToken(seizerContract).comptroller()) {\\n revert ComptrollerMismatch();\\n }\\n }\\n\\n if (!market.accountMembership[borrower]) {\\n revert MarketNotCollateral(vTokenCollateral, borrower);\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vTokenCollateral);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, borrower);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, liquidator);\\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external override {\\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 _checkRedeemAllowed(vToken, src, transferTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, src);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, dst);\\n }\\n }\\n\\n /*** Pool-level operations ***/\\n\\n /**\\n * @notice Seizes all the remaining collateral, makes msg.sender repay the existing\\n * borrows, and treats the rest of the debt as bad debt (for each market).\\n * The sender has to repay a certain percentage of the debt, computed as\\n * collateral / (borrows * liquidationIncentive).\\n * @param user account to heal\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for healing\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function healAccount(address user) external {\\n VToken[] memory userAssets = getAssetsIn(user);\\n uint256 userAssetsCount = userAssets.length;\\n\\n address liquidator = msg.sender;\\n {\\n ResilientOracleInterface oracle_ = oracle;\\n // We need all user's markets to be fresh for the computations to be correct\\n for (uint256 i; i < userAssetsCount; ++i) {\\n userAssets[i].accrueInterest();\\n oracle_.updatePrice(address(userAssets[i]));\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(user, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n // percentage = collateral / (borrows * liquidation incentive)\\n Exp memory collateral = Exp({ mantissa: snapshot.totalCollateral });\\n Exp memory scaledBorrows = mul_(\\n Exp({ mantissa: snapshot.borrows }),\\n Exp({ mantissa: liquidationIncentiveMantissa })\\n );\\n\\n Exp memory percentage = div_(collateral, scaledBorrows);\\n if (lessThanExp(Exp({ mantissa: MANTISSA_ONE }), percentage)) {\\n revert CollateralExceedsThreshold(scaledBorrows.mantissa, collateral.mantissa);\\n }\\n\\n for (uint256 i; i < userAssetsCount; ++i) {\\n VToken market = userAssets[i];\\n\\n (uint256 tokens, uint256 borrowBalance, ) = _safeGetAccountSnapshot(market, user);\\n uint256 repaymentAmount = mul_ScalarTruncate(percentage, borrowBalance);\\n\\n // Seize the entire collateral\\n if (tokens != 0) {\\n market.seize(liquidator, user, tokens);\\n }\\n // Repay a certain percentage of the borrow, forgive the rest\\n if (borrowBalance != 0) {\\n market.healBorrow(liquidator, user, repaymentAmount);\\n }\\n }\\n }\\n\\n /**\\n * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than\\n * a predefined threshold, and the account collateral can be seized to cover all borrows. If\\n * the collateral is higher than the threshold, use regular liquidations. If the collateral is\\n * below the threshold, and the account is insolvent, use healAccount.\\n * @param borrower the borrower address\\n * @param orders an array of liquidation orders\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation\\n * @custom:error InsufficientCollateral error is thrown when there is not enough collateral to cover the debt\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function liquidateAccount(address borrower, LiquidationOrder[] calldata orders) external {\\n // We will accrue interest and update the oracle prices later during the liquidation\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n // You should use the regular vToken.liquidateBorrow(...) call\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n uint256 collateralToSeize = mul_ScalarTruncate(\\n Exp({ mantissa: liquidationIncentiveMantissa }),\\n snapshot.borrows\\n );\\n if (collateralToSeize >= snapshot.totalCollateral) {\\n // There is not enough collateral to seize. Use healBorrow to repay some part of the borrow\\n // and record bad debt.\\n revert InsufficientCollateral(collateralToSeize, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n uint256 ordersCount = orders.length;\\n\\n _ensureMaxLoops(ordersCount / 2);\\n\\n for (uint256 i; i < ordersCount; ++i) {\\n if (!markets[address(orders[i].vTokenBorrowed)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenBorrowed));\\n }\\n if (!markets[address(orders[i].vTokenCollateral)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenCollateral));\\n }\\n\\n LiquidationOrder calldata order = orders[i];\\n order.vTokenBorrowed.forceLiquidateBorrow(\\n msg.sender,\\n borrower,\\n order.repayAmount,\\n order.vTokenCollateral,\\n true\\n );\\n }\\n\\n VToken[] memory borrowMarkets = getAssetsIn(borrower);\\n uint256 marketsCount = borrowMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower);\\n require(borrowBalance == 0, \\\"Nonzero borrow balance after liquidation\\\");\\n }\\n }\\n\\n /**\\n * @notice Sets the closeFactor to use when liquidating borrows\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @custom:event Emits NewCloseFactor on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCloseFactor(uint256 newCloseFactorMantissa) external {\\n _checkAccessAllowed(\\\"setCloseFactor(uint256)\\\");\\n require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, \\\"Close factor greater than maximum close factor\\\");\\n require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, \\\"Close factor smaller than minimum close factor\\\");\\n\\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev This function is restricted by the AccessControlManager\\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 * @custom:event Emits NewCollateralFactor when collateral factor is updated\\n * and NewLiquidationThreshold when liquidation threshold is updated\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InvalidCollateralFactor error is thrown when collateral factor is too high\\n * @custom:error InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor\\n * @custom:error PriceError is thrown when the oracle returns an invalid price for the asset\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCollateralFactor(\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external {\\n _checkAccessAllowed(\\\"setCollateralFactor(address,uint256,uint256)\\\");\\n\\n // Verify market is listed\\n Market storage market = markets[address(vToken)];\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Check collateral factor <= 0.9\\n if (newCollateralFactorMantissa > MAX_COLLATERAL_FACTOR_MANTISSA) {\\n revert InvalidCollateralFactor();\\n }\\n\\n // Ensure that liquidation threshold <= 1\\n if (newLiquidationThresholdMantissa > MANTISSA_ONE) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // Ensure that liquidation threshold >= CF\\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n }\\n\\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\\n emit NewLiquidationThreshold(vToken, oldLiquidationThresholdMantissa, newLiquidationThresholdMantissa);\\n }\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev This function is restricted by the AccessControlManager\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @custom:event Emits NewLiquidationIncentive on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external {\\n require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, \\\"liquidation incentive should be greater than 1e18\\\");\\n\\n _checkAccessAllowed(\\\"setLiquidationIncentive(uint256)\\\");\\n\\n // Save current value for use in log\\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\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\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Only callable by the PoolRegistry\\n * @param vToken The address of the market (token) to list\\n * @custom:error MarketAlreadyListed is thrown if the market is already listed in this pool\\n * @custom:access Only PoolRegistry\\n */\\n function supportMarket(VToken vToken) external {\\n _checkSenderIs(poolRegistry);\\n\\n if (markets[address(vToken)].isListed) {\\n revert MarketAlreadyListed(address(vToken));\\n }\\n\\n require(vToken.isVToken(), \\\"Comptroller: Invalid vToken\\\"); // Sanity check to make sure its really a VToken\\n\\n Market storage newMarket = markets[address(vToken)];\\n newMarket.isListed = true;\\n newMarket.collateralFactorMantissa = 0;\\n newMarket.liquidationThresholdMantissa = 0;\\n\\n _addMarket(address(vToken));\\n\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n rewardsDistributors[i].initializeMarket(address(vToken));\\n }\\n\\n emit MarketSupported(vToken);\\n }\\n\\n /**\\n * @notice Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A borrow cap of type(uint256).max corresponds to unlimited borrowing.\\n * @dev Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed\\n until the total borrows amount goes below the new borrow cap\\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 type(uint256).max corresponds to unlimited borrowing.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\\n _checkAccessAllowed(\\\"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 _ensureMaxLoops(numMarkets);\\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 * @notice Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A supply cap of type(uint256).max corresponds to unlimited supply.\\n * @dev Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed\\n until the total supplies amount goes below the new supply cap\\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 type(uint256).max corresponds to unlimited supply.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\\n _checkAccessAllowed(\\\"setMarketSupplyCaps(address[],uint256[])\\\");\\n uint256 vTokensCount = vTokens.length;\\n\\n require(vTokensCount != 0, \\\"invalid number of markets\\\");\\n require(vTokensCount == newSupplyCaps.length, \\\"invalid number of markets\\\");\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Pause/unpause specified actions\\n * @dev This function is restricted by the AccessControlManager\\n * @param marketsList Markets to pause/unpause the actions on\\n * @param actionsList List of action ids to pause/unpause\\n * @param paused The new paused state (true=paused, false=unpaused)\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setActionsPaused(VToken[] calldata marketsList, Action[] calldata actionsList, bool paused) external {\\n _checkAccessAllowed(\\\"setActionsPaused(address[],uint256[],bool)\\\");\\n\\n uint256 marketsCount = marketsList.length;\\n uint256 actionsCount = actionsList.length;\\n\\n _ensureMaxLoops(marketsCount * actionsCount);\\n\\n for (uint256 marketIdx; marketIdx < marketsCount; ++marketIdx) {\\n for (uint256 actionIdx; actionIdx < actionsCount; ++actionIdx) {\\n _setActionPaused(address(marketsList[marketIdx]), actionsList[actionIdx], paused);\\n }\\n }\\n }\\n\\n /**\\n * @notice Set the given collateral threshold for non-batch liquidations. Regular liquidations\\n * will fail if the collateral amount is less than this threshold. Liquidators should use batch\\n * operations like liquidateAccount or healAccount.\\n * @dev This function is restricted by the AccessControlManager\\n * @param newMinLiquidatableCollateral The new min liquidatable collateral (in USD).\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external {\\n _checkAccessAllowed(\\\"setMinLiquidatableCollateral(uint256)\\\");\\n\\n uint256 oldMinLiquidatableCollateral = minLiquidatableCollateral;\\n minLiquidatableCollateral = newMinLiquidatableCollateral;\\n emit NewMinLiquidatableCollateral(oldMinLiquidatableCollateral, newMinLiquidatableCollateral);\\n }\\n\\n /**\\n * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor\\n * contracts with the same rewardToken, and there could be overlaping among them considering the last reward slot (block or second)\\n * @dev Only callable by the admin\\n * @param _rewardsDistributor Address of the RewardDistributor contract to add\\n * @custom:access Only Governance\\n * @custom:event Emits NewRewardsDistributor with distributor address\\n */\\n function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner {\\n require(!rewardsDistributorExists[address(_rewardsDistributor)], \\\"already exists\\\");\\n\\n uint256 rewardsDistributorsLen = rewardsDistributors.length;\\n _ensureMaxLoops(rewardsDistributorsLen + 1);\\n\\n rewardsDistributors.push(_rewardsDistributor);\\n rewardsDistributorExists[address(_rewardsDistributor)] = true;\\n\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n _rewardsDistributor.initializeMarket(address(allMarkets[i]));\\n }\\n\\n emit NewRewardsDistributor(address(_rewardsDistributor), address(_rewardsDistributor.rewardToken()));\\n }\\n\\n /**\\n * @notice Sets a new price oracle for the Comptroller\\n * @dev Only callable by the admin\\n * @param newOracle Address of the new price oracle to set\\n * @custom:event Emits NewPriceOracle on success\\n * @custom:error ZeroAddressNotAllowed is thrown when the new oracle address is zero\\n */\\n function setPriceOracle(ResilientOracleInterface newOracle) external onlyOwner {\\n ensureNonzeroAddress(address(newOracle));\\n\\n ResilientOracleInterface oldOracle = oracle;\\n oracle = newOracle;\\n emit NewPriceOracle(oldOracle, newOracle);\\n }\\n\\n /**\\n * @notice Set the for loop iteration limit to avoid DOS\\n * @param limit Limit for the max loops can execute at a time\\n */\\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Sets the prime token contract for the comptroller\\n * @param _prime Address of the Prime contract\\n */\\n function setPrimeToken(IPrime _prime) external onlyOwner {\\n ensureNonzeroAddress(address(_prime));\\n\\n emit NewPrimeToken(prime, _prime);\\n prime = _prime;\\n }\\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 * @param vTokenBorrowed Borrowed vToken\\n * @param enable Whether to enable forced liquidations\\n */\\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\\n _checkAccessAllowed(\\\"setForcedLiquidation(address,bool)\\\");\\n ensureNonzeroAddress(vTokenBorrowed);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(vTokenBorrowed);\\n }\\n\\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to liquidation threshold requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of liquidation threshold requirements,\\n * @return shortfall Account shortfall below liquidation threshold requirements\\n */\\n function getAccountLiquidity(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getLiquidationThreshold);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to collateral requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of collateral requirements,\\n * @return shortfall Account shortfall below collateral requirements\\n */\\n function getBorrowingPower(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getCollateralFactor);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Hypothetical account liquidity in excess of collateral requirements,\\n * @return shortfall 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 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n account,\\n VToken(vTokenModify),\\n redeemTokens,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\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 markets The list of market addresses\\n */\\n function getAllMarkets() external view override returns (VToken[] memory) {\\n return allMarkets;\\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 /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns whether the given account is entered in a given market\\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 market specified, 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 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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return tokensToSeize Number of vTokenCollateral tokens to be seized in a liquidation\\n * @custom:error PriceError if the oracle returns an invalid price\\n */\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view override returns (uint256 error, uint256 tokensToSeize) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint256 priceBorrowedMantissa = _safeGetUnderlyingPrice(VToken(vTokenBorrowed));\\n uint256 priceCollateralMantissa = _safeGetUnderlyingPrice(VToken(vTokenCollateral));\\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 uint256 exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint256 seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n\\n numerator = mul_(Exp({ mantissa: liquidationIncentiveMantissa }), Exp({ mantissa: priceBorrowedMantissa }));\\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\\n ratio = div_(numerator, denominator);\\n\\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\\n\\n return (NO_ERROR, seizeTokens);\\n }\\n\\n /**\\n * @notice Returns reward speed given a vToken\\n * @param vToken The vToken to get the reward speeds for\\n * @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors\\n */\\n function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {\\n uint256 rewardsDistributorsLength = rewardsDistributors.length;\\n rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);\\n for (uint256 i; i < rewardsDistributorsLength; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n address rewardToken = address(rewardsDistributor.rewardToken());\\n rewardSpeeds[i] = RewardSpeeds({\\n rewardToken: rewardToken,\\n supplySpeed: rewardsDistributor.rewardTokenSupplySpeeds(vToken),\\n borrowSpeed: rewardsDistributor.rewardTokenBorrowSpeeds(vToken)\\n });\\n }\\n return rewardSpeeds;\\n }\\n\\n /**\\n * @notice Return all reward distributors for this pool\\n * @return Array of RewardDistributor addresses\\n */\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory) {\\n return rewardsDistributors;\\n }\\n\\n /**\\n * @notice A marker method that returns true for a valid Comptroller contract\\n * @return Always true\\n */\\n function isComptroller() external pure override returns (bool) {\\n return true;\\n }\\n\\n /**\\n * @notice Update the prices of all the tokens associated with the provided account\\n * @param account Address of the account to get associated tokens with\\n */\\n function updatePrices(address account) public {\\n VToken[] memory vTokens = getAssetsIn(account);\\n uint256 vTokensCount = vTokens.length;\\n\\n ResilientOracleInterface oracle_ = oracle;\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n oracle_.updatePrice(address(vTokens[i]));\\n }\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param market vToken address\\n * @param action Action to check\\n * @return paused True if the action is paused otherwise false\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][action];\\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 list with the assets the account has entered\\n */\\n function getAssetsIn(address account) public 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 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 */\\n function _addToMarket(VToken vToken, address borrower) internal {\\n _checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = markets[address(vToken)];\\n\\n if (!marketToJoin.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return;\\n }\\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\\n /**\\n * @notice Internal function to validate that a market hasn't already been added\\n * and if it hasn't adds it\\n * @param vToken The market to support\\n */\\n function _addMarket(address vToken) internal {\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n if (allMarkets[i] == VToken(vToken)) {\\n revert MarketAlreadyListed(vToken);\\n }\\n }\\n allMarkets.push(VToken(vToken));\\n marketsCount = allMarkets.length;\\n _ensureMaxLoops(marketsCount);\\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 _setActionPaused(address market, Action action, bool paused) internal {\\n require(markets[market].isListed, \\\"cannot pause a market that is not listed\\\");\\n _actionPaused[market][action] = paused;\\n emit ActionPausedMarket(VToken(market), action, paused);\\n }\\n\\n /**\\n * @dev Internal function to check that vTokens can be safely redeemed for the underlying asset.\\n * @param vToken Address of the vTokens to redeem\\n * @param redeemer Account redeeming the tokens\\n * @param redeemTokens The number of tokens to redeem\\n */\\n function _checkRedeemAllowed(address vToken, address redeemer, uint256 redeemTokens) internal {\\n Market storage market = markets[vToken];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!market.accountMembership[redeemer]) {\\n return;\\n }\\n\\n // Update the prices of tokens\\n updatePrices(redeemer);\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n _getCollateralFactor\\n );\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n }\\n\\n /**\\n * @notice Get the total collateral, weighted collateral, borrow balance, liquidity, shortfall\\n * @param account The account to get the snapshot for\\n * @param weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n * liquidation threshold. Accepts the address of the vToken and returns the weight as Exp.\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getCurrentLiquiditySnapshot(\\n address account,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n return _getHypotheticalLiquiditySnapshot(account, VToken(address(0)), 0, 0, weight);\\n }\\n\\n /**\\n * @notice Determine what the supply/borrow balances 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 weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n liquidation threshold. Accepts the address of the VToken and returns the weight\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getHypotheticalLiquiditySnapshot(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n // For each asset the account is in\\n VToken[] memory assets = getAssetsIn(account);\\n uint256 assetsCount = assets.length;\\n\\n for (uint256 i; i < assetsCount; ++i) {\\n VToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the vToken\\n (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) = _safeGetAccountSnapshot(\\n asset,\\n account\\n );\\n\\n // Get the normalized price of the asset\\n Exp memory oraclePrice = Exp({ mantissa: _safeGetUnderlyingPrice(asset) });\\n\\n // Pre-compute conversion factors from vTokens -> usd\\n Exp memory vTokenPrice = mul_(Exp({ mantissa: exchangeRateMantissa }), oraclePrice);\\n Exp memory weightedVTokenPrice = mul_(weight(asset), vTokenPrice);\\n\\n // weightedCollateral += weightedVTokenPrice * vTokenBalance\\n snapshot.weightedCollateral = mul_ScalarTruncateAddUInt(\\n weightedVTokenPrice,\\n vTokenBalance,\\n snapshot.weightedCollateral\\n );\\n\\n // totalCollateral += vTokenPrice * vTokenBalance\\n snapshot.totalCollateral = mul_ScalarTruncateAddUInt(vTokenPrice, vTokenBalance, snapshot.totalCollateral);\\n\\n // borrows += oraclePrice * borrowBalance\\n snapshot.borrows = mul_ScalarTruncateAddUInt(oraclePrice, borrowBalance, snapshot.borrows);\\n\\n // Calculate effects of interacting with vTokenModify\\n if (asset == vTokenModify) {\\n // redeem effect\\n // effects += tokensToDenom * redeemTokens\\n snapshot.effects = mul_ScalarTruncateAddUInt(weightedVTokenPrice, redeemTokens, snapshot.effects);\\n\\n // borrow effect\\n // effects += oraclePrice * borrowAmount\\n snapshot.effects = mul_ScalarTruncateAddUInt(oraclePrice, borrowAmount, snapshot.effects);\\n }\\n }\\n\\n uint256 borrowPlusEffects = snapshot.borrows + snapshot.effects;\\n // These are safe, as the underflow condition is checked first\\n unchecked {\\n if (snapshot.weightedCollateral > borrowPlusEffects) {\\n snapshot.liquidity = snapshot.weightedCollateral - borrowPlusEffects;\\n snapshot.shortfall = 0;\\n } else {\\n snapshot.liquidity = 0;\\n snapshot.shortfall = borrowPlusEffects - snapshot.weightedCollateral;\\n }\\n }\\n\\n return snapshot;\\n }\\n\\n /**\\n * @dev Retrieves price from oracle for an asset and checks it is nonzero\\n * @param asset Address for asset to query price\\n * @return Underlying price\\n */\\n function _safeGetUnderlyingPrice(VToken asset) internal view returns (uint256) {\\n uint256 oraclePriceMantissa = oracle.getUnderlyingPrice(address(asset));\\n if (oraclePriceMantissa == 0) {\\n revert PriceError(address(asset));\\n }\\n return oraclePriceMantissa;\\n }\\n\\n /**\\n * @dev Return collateral factor for a market\\n * @param asset Address for asset\\n * @return Collateral factor as exponential\\n */\\n function _getCollateralFactor(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].collateralFactorMantissa });\\n }\\n\\n /**\\n * @dev Retrieves liquidation threshold for a market as an exponential\\n * @param asset Address for asset to liquidation threshold\\n * @return Liquidation threshold as exponential\\n */\\n function _getLiquidationThreshold(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].liquidationThresholdMantissa });\\n }\\n\\n /**\\n * @dev Returns supply and borrow balances of user in vToken, reverts on failure\\n * @param vToken Market to query\\n * @param user Account address\\n * @return vTokenBalance Balance of vTokens, the same as vToken.balanceOf(user)\\n * @return borrowBalance Borrowed amount, including the interest\\n * @return exchangeRateMantissa Stored exchange rate\\n */\\n function _safeGetAccountSnapshot(\\n VToken vToken,\\n address user\\n ) internal view returns (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) {\\n uint256 err;\\n (err, vTokenBalance, borrowBalance, exchangeRateMantissa) = vToken.getAccountSnapshot(user);\\n if (err != 0) {\\n revert SnapshotError(address(vToken), user);\\n }\\n return (vTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /// @notice Reverts if the call is not from expectedSender\\n /// @param expectedSender Expected transaction sender\\n function _checkSenderIs(address expectedSender) internal view {\\n if (msg.sender != expectedSender) {\\n revert UnexpectedSender(expectedSender, msg.sender);\\n }\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n /// @param market Market to check\\n /// @param action Action to check\\n function _checkActionPauseState(address market, Action action) private view {\\n if (actionPaused(market, action)) {\\n revert ActionPaused(market, action);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7c6e1c6264e4681f82a9ac1bcd9155197a930033291ee5561ad97a56006f5e9c\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.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\\n/**\\n * @title ComptrollerInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract.\\n */\\ninterface ComptrollerInterface {\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\\n\\n function exitMarket(address vToken) external returns (uint256);\\n\\n /*** Policy Hooks ***/\\n\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external;\\n\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external;\\n\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external;\\n\\n function preRepayHook(address vToken, address borrower) external;\\n\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external;\\n\\n function preSeizeHook(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower\\n ) external;\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\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 seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external;\\n\\n function isComptroller() external view returns (bool);\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 repayAmount\\n ) external view returns (uint256, uint256);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n}\\n\\n/**\\n * @title ComptrollerViewInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract, including only some util view functions.\\n */\\ninterface ComptrollerViewInterface {\\n function markets(address) external view returns (bool, uint256);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function closeFactorMantissa() external view returns (uint256);\\n\\n function liquidationIncentiveMantissa() external view returns (uint256);\\n\\n function minLiquidatableCollateral() external view returns (uint256);\\n\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function borrowCaps(address) external view returns (uint256);\\n\\n function supplyCaps(address) external view returns (uint256);\\n\\n function approvedDelegates(address user, address delegate) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xcbf7f9977472650c61345b7cbde23e81f626e1f8863bab4c6ce3dacfc7604919\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { IPrime } from \\\"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\\\";\\nimport { Action } from \\\"./ComptrollerInterface.sol\\\";\\n\\n/**\\n * @title ComptrollerStorage\\n * @author Venus\\n * @notice Storage layout for the `Comptroller` contract.\\n */\\ncontract ComptrollerStorage {\\n struct LiquidationOrder {\\n VToken vTokenCollateral;\\n VToken vTokenBorrowed;\\n uint256 repayAmount;\\n }\\n\\n struct AccountLiquiditySnapshot {\\n uint256 totalCollateral;\\n uint256 weightedCollateral;\\n uint256 borrows;\\n uint256 effects;\\n uint256 liquidity;\\n uint256 shortfall;\\n }\\n\\n struct RewardSpeeds {\\n address rewardToken;\\n uint256 supplySpeed;\\n uint256 borrowSpeed;\\n }\\n\\n struct Market {\\n // Whether or not this market is listed\\n bool isListed;\\n // 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 uint256 collateralFactorMantissa;\\n // 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 uint256 liquidationThresholdMantissa;\\n // Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n }\\n\\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 Per-account mapping of \\\"assets you are in\\\"\\n */\\n mapping(address => VToken[]) public accountAssets;\\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 /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\\n mapping(address => uint256) public borrowCaps;\\n\\n /// @notice Minimal collateral required for regular (non-batch) liquidations\\n uint256 public minLiquidatableCollateral;\\n\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\\n mapping(address => uint256) public supplyCaps;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(Action => bool)) internal _actionPaused;\\n\\n // List of Reward Distributors added\\n RewardsDistributor[] internal rewardsDistributors;\\n\\n // Used to check if rewards distributor is added\\n mapping(address => bool) internal rewardsDistributorExists;\\n\\n /// @notice Flag indicating whether forced liquidation enabled for a market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n\\n uint256 internal constant NO_ERROR = 0;\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant MIN_CLOSE_FACTOR_MANTISSA = 0.05e18; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant MAX_CLOSE_FACTOR_MANTISSA = 0.9e18; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.95e18; // 0.95\\n\\n /// Prime token address\\n IPrime public prime;\\n\\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 /**\\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[47] private __gap;\\n}\\n\",\"keccak256\":\"0x4df44cb65ac152bac2be4b4545430e703005a74a55b72e144100b16421bd8bfd\",\"license\":\"BSD-3-Clause\"},\"contracts/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title TokenErrorReporter\\n * @author Venus\\n * @notice Errors that can be thrown by the `VToken` contract.\\n */\\ncontract TokenErrorReporter {\\n uint256 public constant NO_ERROR = 0; // support legacy return codes\\n\\n error TransferNotAllowed();\\n\\n error MintFreshnessCheck();\\n\\n error RedeemFreshnessCheck();\\n error RedeemTransferOutNotPossible();\\n\\n error BorrowFreshnessCheck();\\n error BorrowCashNotAvailable();\\n error DelegateNotApproved();\\n\\n error RepayBorrowFreshnessCheck();\\n\\n error HealBorrowUnauthorized();\\n error ForceLiquidateBorrowUnauthorized();\\n\\n error LiquidateFreshnessCheck();\\n error LiquidateCollateralFreshnessCheck();\\n error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\\n error LiquidateLiquidatorIsBorrower();\\n error LiquidateCloseAmountIsZero();\\n error LiquidateCloseAmountIsUintMax();\\n\\n error LiquidateSeizeLiquidatorIsBorrower();\\n\\n error ProtocolSeizeShareTooBig();\\n\\n error SetReserveFactorFreshCheck();\\n error SetReserveFactorBoundsCheck();\\n\\n error AddReservesFactorFreshCheck(uint256 actualAddAmount);\\n\\n error ReduceReservesFreshCheck();\\n error ReduceReservesCashNotAvailable();\\n error ReduceReservesCashValidation();\\n\\n error SetInterestRateModelFreshCheck();\\n}\\n\",\"keccak256\":\"0x7a7ced1caaac2d9242659ebd50b99f308c725ce958ac9e11f7ada404b1d97a7b\",\"license\":\"BSD-3-Clause\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from \\\"./lib/constants.sol\\\";\\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 struct Exp {\\n uint256 mantissa;\\n }\\n\\n struct Double {\\n uint256 mantissa;\\n }\\n\\n uint256 internal constant EXP_SCALE = EXP_SCALE_;\\n uint256 internal constant DOUBLE_SCALE = 1e36;\\n uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;\\n uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint256) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / EXP_SCALE;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\\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 // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint256 scalar, uint256 addend) internal pure returns (uint256) {\\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 function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\\n require(n <= type(uint224).max, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\\n require(n <= type(uint32).max, 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_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a + b;\\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_(uint256 a, uint256 b) internal pure returns (uint256) {\\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) / EXP_SCALE });\\n }\\n\\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / EXP_SCALE;\\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) / DOUBLE_SCALE });\\n }\\n\\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / DOUBLE_SCALE;\\n }\\n\\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a * b;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return div_(mul_(a, EXP_SCALE), 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, DOUBLE_SCALE), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return div_(mul_(a, DOUBLE_SCALE), b.mantissa);\\n }\\n\\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a / b;\\n }\\n\\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });\\n }\\n}\\n\",\"keccak256\":\"0x8afbe8a24fe3539c124e718681ed3dcebd24c40dd53095786c0155998213b9b0\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModel.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\nabstract contract InterestRateModel {\\n /**\\n * @notice Calculates the current borrow interest rate per slot (block or second)\\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 amount of reserves the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per slot (block or second)\\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 amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\\n * @return Always true\\n */\\n function isInterestRateModel() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xc4fda1ab75ebe4b187b707c4f10c58780f343cf343c537f641dc75d3cd28ab51\",\"license\":\"BSD-3-Clause\"},\"contracts/Lens/PoolLens.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { IERC20Metadata } from \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Action, ComptrollerInterface, ComptrollerViewInterface } from \\\"../ComptrollerInterface.sol\\\";\\nimport { PoolRegistryInterface } from \\\"../Pool/PoolRegistryInterface.sol\\\";\\nimport { PoolRegistry } from \\\"../Pool/PoolRegistry.sol\\\";\\nimport { RewardsDistributor } from \\\"../Rewards/RewardsDistributor.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\n\\n/**\\n * @title PoolLens\\n * @author Venus\\n * @notice The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information\\n * for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be\\n * looked up for specific pools and markets:\\n- the vToken balance of a given user;\\n- the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address;\\n- the vToken address in a pool for a given asset;\\n- a list of all pools that support an asset;\\n- the underlying asset price of a vToken;\\n- the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\\n */\\ncontract PoolLens is ExponentialNoError, TimeManagerV8 {\\n /**\\n * @dev Struct for PoolDetails.\\n */\\n struct PoolData {\\n string name;\\n address creator;\\n address comptroller;\\n uint256 blockPosted;\\n uint256 timestampPosted;\\n string category;\\n string logoURL;\\n string description;\\n address priceOracle;\\n uint256 closeFactor;\\n uint256 liquidationIncentive;\\n uint256 minLiquidatableCollateral;\\n VTokenMetadata[] vTokens;\\n }\\n\\n /**\\n * @dev Struct for VToken.\\n */\\n struct VTokenMetadata {\\n address vToken;\\n uint256 exchangeRateCurrent;\\n uint256 supplyRatePerBlockOrTimestamp;\\n uint256 borrowRatePerBlockOrTimestamp;\\n uint256 reserveFactorMantissa;\\n uint256 supplyCaps;\\n uint256 borrowCaps;\\n uint256 totalBorrows;\\n uint256 totalReserves;\\n uint256 totalSupply;\\n uint256 totalCash;\\n bool isListed;\\n uint256 collateralFactorMantissa;\\n address underlyingAssetAddress;\\n uint256 vTokenDecimals;\\n uint256 underlyingDecimals;\\n uint256 pausedActions;\\n }\\n\\n /**\\n * @dev Struct for VTokenBalance.\\n */\\n struct VTokenBalances {\\n address vToken;\\n uint256 balanceOf;\\n uint256 borrowBalanceCurrent;\\n uint256 balanceOfUnderlying;\\n uint256 tokenBalance;\\n uint256 tokenAllowance;\\n }\\n\\n /**\\n * @dev Struct for underlyingPrice of VToken.\\n */\\n struct VTokenUnderlyingPrice {\\n address vToken;\\n uint256 underlyingPrice;\\n }\\n\\n /**\\n * @dev Struct with pending reward info for a market.\\n */\\n struct PendingReward {\\n address vTokenAddress;\\n uint256 amount;\\n }\\n\\n /**\\n * @dev Struct with reward distribution totals for a single reward token and distributor.\\n */\\n struct RewardSummary {\\n address distributorAddress;\\n address rewardTokenAddress;\\n uint256 totalRewards;\\n PendingReward[] pendingRewards;\\n }\\n\\n /**\\n * @dev Struct used in RewardDistributor to save last updated market state.\\n */\\n struct RewardTokenState {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number or timestamp the index was last updated at\\n uint256 blockOrTimestamp;\\n // The block number or timestamp at which to stop rewards\\n uint256 lastRewardingBlockOrTimestamp;\\n }\\n\\n /**\\n * @dev Struct with bad debt of a market denominated\\n */\\n struct BadDebt {\\n address vTokenAddress;\\n uint256 badDebtUsd;\\n }\\n\\n /**\\n * @dev Struct with bad debt total denominated in usd for a pool and an array of BadDebt structs for each market\\n */\\n struct BadDebtSummary {\\n address comptroller;\\n uint256 totalBadDebtUsd;\\n BadDebt[] badDebts;\\n }\\n\\n /**\\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) {}\\n\\n /**\\n * @notice Queries the user's supply/borrow balances in vTokens\\n * @param vTokens The list of vToken addresses\\n * @param account The user Account\\n * @return A list of structs containing balances data\\n */\\n function vTokenBalancesAll(VToken[] calldata vTokens, address account) external returns (VTokenBalances[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenBalances[] memory res = new VTokenBalances[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenBalances(vTokens[i], account);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Queries all pools with addtional details for each of them\\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @return Arrays of all Venus pools' data\\n */\\n function getAllPools(address poolRegistryAddress) external view returns (PoolData[] memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n PoolRegistry.VenusPool[] memory venusPools = poolRegistryInterface.getAllPools();\\n uint256 poolLength = venusPools.length;\\n\\n PoolData[] memory poolDataItems = new PoolData[](poolLength);\\n\\n for (uint256 i; i < poolLength; ++i) {\\n PoolRegistry.VenusPool memory venusPool = venusPools[i];\\n PoolData memory poolData = getPoolDataFromVenusPool(poolRegistryAddress, venusPool);\\n poolDataItems[i] = poolData;\\n }\\n\\n return poolDataItems;\\n }\\n\\n /**\\n * @notice Queries the details of a pool identified by Comptroller address\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param comptroller The Comptroller implementation address\\n * @return PoolData structure containing the details of the pool\\n */\\n function getPoolByComptroller(\\n address poolRegistryAddress,\\n address comptroller\\n ) external view returns (PoolData memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return getPoolDataFromVenusPool(poolRegistryAddress, poolRegistryInterface.getPoolByComptroller(comptroller));\\n }\\n\\n /**\\n * @notice Returns vToken holding the specified underlying asset in the specified pool\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param comptroller The pool comptroller\\n * @param asset The underlyingAsset of VToken\\n * @return Address of the vToken\\n */\\n function getVTokenForAsset(\\n address poolRegistryAddress,\\n address comptroller,\\n address asset\\n ) external view returns (address) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return poolRegistryInterface.getVTokenForAsset(comptroller, asset);\\n }\\n\\n /**\\n * @notice Returns all pools that support the specified underlying asset\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param asset The underlying asset of vToken\\n * @return A list of Comptroller contracts\\n */\\n function getPoolsSupportedByAsset(\\n address poolRegistryAddress,\\n address asset\\n ) external view returns (address[] memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return poolRegistryInterface.getPoolsSupportedByAsset(asset);\\n }\\n\\n /**\\n * @notice Returns the price data for the underlying assets of the specified vTokens\\n * @param vTokens The list of vToken addresses\\n * @return An array containing the price data for each asset\\n */\\n function vTokenUnderlyingPriceAll(\\n VToken[] calldata vTokens\\n ) external view returns (VTokenUnderlyingPrice[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenUnderlyingPrice[] memory res = new VTokenUnderlyingPrice[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenUnderlyingPrice(vTokens[i]);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Returns the pending rewards for a user for a given pool.\\n * @param account The user account.\\n * @param comptrollerAddress address\\n * @return Pending rewards array\\n */\\n function getPendingRewards(\\n address account,\\n address comptrollerAddress\\n ) external view returns (RewardSummary[] memory) {\\n VToken[] memory markets = ComptrollerInterface(comptrollerAddress).getAllMarkets();\\n RewardsDistributor[] memory rewardsDistributors = ComptrollerViewInterface(comptrollerAddress)\\n .getRewardDistributors();\\n RewardSummary[] memory rewardSummary = new RewardSummary[](rewardsDistributors.length);\\n for (uint256 i; i < rewardsDistributors.length; ++i) {\\n RewardSummary memory reward;\\n reward.distributorAddress = address(rewardsDistributors[i]);\\n reward.rewardTokenAddress = address(rewardsDistributors[i].rewardToken());\\n reward.totalRewards = rewardsDistributors[i].rewardTokenAccrued(account);\\n reward.pendingRewards = _calculateNotDistributedAwards(account, markets, rewardsDistributors[i]);\\n rewardSummary[i] = reward;\\n }\\n return rewardSummary;\\n }\\n\\n /**\\n * @notice Returns a summary of a pool's bad debt broken down by market\\n *\\n * @param comptrollerAddress Address of the comptroller\\n *\\n * @return badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and\\n * a break down of bad debt by market\\n */\\n function getPoolBadDebt(address comptrollerAddress) external view returns (BadDebtSummary memory) {\\n uint256 totalBadDebtUsd;\\n\\n // Get every market in the pool\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\\n VToken[] memory markets = comptroller.getAllMarkets();\\n ResilientOracleInterface priceOracle = comptroller.oracle();\\n\\n BadDebt[] memory badDebts = new BadDebt[](markets.length);\\n\\n BadDebtSummary memory badDebtSummary;\\n badDebtSummary.comptroller = comptrollerAddress;\\n badDebtSummary.badDebts = badDebts;\\n\\n // // Calculate the bad debt is USD per market\\n for (uint256 i; i < markets.length; ++i) {\\n BadDebt memory badDebt;\\n badDebt.vTokenAddress = address(markets[i]);\\n badDebt.badDebtUsd =\\n (VToken(address(markets[i])).badDebt() * priceOracle.getUnderlyingPrice(address(markets[i]))) /\\n EXP_SCALE;\\n badDebtSummary.badDebts[i] = badDebt;\\n totalBadDebtUsd = totalBadDebtUsd + badDebt.badDebtUsd;\\n }\\n\\n badDebtSummary.totalBadDebtUsd = totalBadDebtUsd;\\n\\n return badDebtSummary;\\n }\\n\\n /**\\n * @notice Queries the user's supply/borrow balances in the specified vToken\\n * @param vToken vToken address\\n * @param account The user Account\\n * @return A struct containing the balances data\\n */\\n function vTokenBalances(VToken vToken, address account) public returns (VTokenBalances memory) {\\n uint256 balanceOf = vToken.balanceOf(account);\\n uint256 borrowBalanceCurrent = vToken.borrowBalanceCurrent(account);\\n uint256 balanceOfUnderlying = vToken.balanceOfUnderlying(account);\\n uint256 tokenBalance;\\n uint256 tokenAllowance;\\n\\n IERC20 underlying = IERC20(vToken.underlying());\\n tokenBalance = underlying.balanceOf(account);\\n tokenAllowance = underlying.allowance(account, address(vToken));\\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 Queries additional information for the pool\\n * @param poolRegistryAddress Address of the PoolRegistry\\n * @param venusPool The VenusPool Object from PoolRegistry\\n * @return Enriched PoolData\\n */\\n function getPoolDataFromVenusPool(\\n address poolRegistryAddress,\\n PoolRegistry.VenusPool memory venusPool\\n ) public view returns (PoolData memory) {\\n // Get tokens in the Pool\\n ComptrollerInterface comptrollerInstance = ComptrollerInterface(venusPool.comptroller);\\n\\n VToken[] memory vTokens = comptrollerInstance.getAllMarkets();\\n\\n VTokenMetadata[] memory vTokenMetadataItems = vTokenMetadataAll(vTokens);\\n\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n\\n PoolRegistry.VenusPoolMetaData memory venusPoolMetaData = poolRegistryInterface.getVenusPoolMetadata(\\n venusPool.comptroller\\n );\\n\\n ComptrollerViewInterface comptrollerViewInstance = ComptrollerViewInterface(venusPool.comptroller);\\n\\n PoolData memory poolData = PoolData({\\n name: venusPool.name,\\n creator: venusPool.creator,\\n comptroller: venusPool.comptroller,\\n blockPosted: venusPool.blockPosted,\\n timestampPosted: venusPool.timestampPosted,\\n category: venusPoolMetaData.category,\\n logoURL: venusPoolMetaData.logoURL,\\n description: venusPoolMetaData.description,\\n vTokens: vTokenMetadataItems,\\n priceOracle: address(comptrollerViewInstance.oracle()),\\n closeFactor: comptrollerViewInstance.closeFactorMantissa(),\\n liquidationIncentive: comptrollerViewInstance.liquidationIncentiveMantissa(),\\n minLiquidatableCollateral: comptrollerViewInstance.minLiquidatableCollateral()\\n });\\n\\n return poolData;\\n }\\n\\n /**\\n * @notice Returns the metadata of VToken\\n * @param vToken The address of vToken\\n * @return VTokenMetadata struct\\n */\\n function vTokenMetadata(VToken vToken) public view returns (VTokenMetadata memory) {\\n uint256 exchangeRateCurrent = vToken.exchangeRateStored();\\n address comptrollerAddress = address(vToken.comptroller());\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\\n (bool isListed, uint256 collateralFactorMantissa) = comptroller.markets(address(vToken));\\n\\n address underlyingAssetAddress = vToken.underlying();\\n uint256 underlyingDecimals = IERC20Metadata(underlyingAssetAddress).decimals();\\n\\n uint256 pausedActions;\\n for (uint8 i; i <= uint8(type(Action).max); ++i) {\\n uint256 paused = ComptrollerInterface(comptrollerAddress).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 supplyRatePerBlockOrTimestamp: vToken.supplyRatePerBlock(),\\n borrowRatePerBlockOrTimestamp: vToken.borrowRatePerBlock(),\\n reserveFactorMantissa: vToken.reserveFactorMantissa(),\\n supplyCaps: comptroller.supplyCaps(address(vToken)),\\n borrowCaps: comptroller.borrowCaps(address(vToken)),\\n totalBorrows: vToken.totalBorrows(),\\n totalReserves: vToken.totalReserves(),\\n totalSupply: vToken.totalSupply(),\\n totalCash: vToken.getCash(),\\n isListed: isListed,\\n collateralFactorMantissa: collateralFactorMantissa,\\n underlyingAssetAddress: underlyingAssetAddress,\\n vTokenDecimals: vToken.decimals(),\\n underlyingDecimals: underlyingDecimals,\\n pausedActions: pausedActions\\n });\\n }\\n\\n /**\\n * @notice Returns the metadata of all VTokens\\n * @param vTokens The list of vToken addresses\\n * @return An array of VTokenMetadata structs\\n */\\n function vTokenMetadataAll(VToken[] memory vTokens) public view returns (VTokenMetadata[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenMetadata[] memory res = new VTokenMetadata[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenMetadata(vTokens[i]);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Returns the price data for the underlying asset of the specified vToken\\n * @param vToken vToken address\\n * @return The price data for each asset\\n */\\n function vTokenUnderlyingPrice(VToken vToken) public view returns (VTokenUnderlyingPrice memory) {\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(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 function _calculateNotDistributedAwards(\\n address account,\\n VToken[] memory markets,\\n RewardsDistributor rewardsDistributor\\n ) internal view returns (PendingReward[] memory) {\\n PendingReward[] memory pendingRewards = new PendingReward[](markets.length);\\n\\n for (uint256 i; i < markets.length; ++i) {\\n // Market borrow and supply state we will modify update in-memory, in order to not modify storage\\n RewardTokenState memory borrowState;\\n RewardTokenState memory supplyState;\\n\\n if (isTimeBased) {\\n (\\n borrowState.index,\\n borrowState.blockOrTimestamp,\\n borrowState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenBorrowStateTimeBased(address(markets[i]));\\n (\\n supplyState.index,\\n supplyState.blockOrTimestamp,\\n supplyState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenSupplyStateTimeBased(address(markets[i]));\\n } else {\\n (\\n borrowState.index,\\n borrowState.blockOrTimestamp,\\n borrowState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenBorrowState(address(markets[i]));\\n (\\n supplyState.index,\\n supplyState.blockOrTimestamp,\\n supplyState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenSupplyState(address(markets[i]));\\n }\\n\\n Exp memory marketBorrowIndex = Exp({ mantissa: markets[i].borrowIndex() });\\n\\n // Update market supply and borrow index in-memory\\n updateMarketBorrowIndex(address(markets[i]), rewardsDistributor, borrowState, marketBorrowIndex);\\n updateMarketSupplyIndex(address(markets[i]), rewardsDistributor, supplyState);\\n\\n // Calculate pending rewards\\n uint256 borrowReward = calculateBorrowerReward(\\n address(markets[i]),\\n rewardsDistributor,\\n account,\\n borrowState,\\n marketBorrowIndex\\n );\\n uint256 supplyReward = calculateSupplierReward(\\n address(markets[i]),\\n rewardsDistributor,\\n account,\\n supplyState\\n );\\n\\n PendingReward memory pendingReward;\\n pendingReward.vTokenAddress = address(markets[i]);\\n pendingReward.amount = borrowReward + supplyReward;\\n pendingRewards[i] = pendingReward;\\n }\\n return pendingRewards;\\n }\\n\\n function updateMarketBorrowIndex(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n RewardTokenState memory borrowState,\\n Exp memory marketBorrowIndex\\n ) internal view {\\n uint256 borrowSpeed = rewardsDistributor.rewardTokenBorrowSpeeds(vToken);\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (\\n borrowState.lastRewardingBlockOrTimestamp > 0 &&\\n blockNumberOrTimestamp > borrowState.lastRewardingBlockOrTimestamp\\n ) {\\n blockNumberOrTimestamp = borrowState.lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, borrowState.blockOrTimestamp);\\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\\n // Remove the total earned interest rate since the opening of the market from total borrows\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, borrowSpeed);\\n Double memory ratio = borrowAmount > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\\n } else if (deltaBlocksOrTimestamp > 0) {\\n borrowState.blockOrTimestamp = blockNumberOrTimestamp;\\n }\\n }\\n\\n function updateMarketSupplyIndex(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n RewardTokenState memory supplyState\\n ) internal view {\\n uint256 supplySpeed = rewardsDistributor.rewardTokenSupplySpeeds(vToken);\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (\\n supplyState.lastRewardingBlockOrTimestamp > 0 &&\\n blockNumberOrTimestamp > supplyState.lastRewardingBlockOrTimestamp\\n ) {\\n blockNumberOrTimestamp = supplyState.lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, supplyState.blockOrTimestamp);\\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, supplySpeed);\\n Double memory ratio = supplyTokens > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\\n } else if (deltaBlocksOrTimestamp > 0) {\\n supplyState.blockOrTimestamp = blockNumberOrTimestamp;\\n }\\n }\\n\\n function calculateBorrowerReward(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n address borrower,\\n RewardTokenState memory borrowState,\\n Exp memory marketBorrowIndex\\n ) internal view returns (uint256) {\\n Double memory borrowIndex = Double({ mantissa: borrowState.index });\\n Double memory borrowerIndex = Double({\\n mantissa: rewardsDistributor.rewardTokenBorrowerIndex(vToken, borrower)\\n });\\n if (borrowerIndex.mantissa == 0 && borrowIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set\\n borrowerIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\\n }\\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n return borrowerDelta;\\n }\\n\\n function calculateSupplierReward(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n address supplier,\\n RewardTokenState memory supplyState\\n ) internal view returns (uint256) {\\n Double memory supplyIndex = Double({ mantissa: supplyState.index });\\n Double memory supplierIndex = Double({\\n mantissa: rewardsDistributor.rewardTokenSupplierIndex(vToken, supplier)\\n });\\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\\n // Covers the case where users supplied tokens before the market's supply state index was set\\n supplierIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\\n }\\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n return supplierDelta;\\n }\\n}\\n\",\"keccak256\":\"0xab04eb777ddc89a994e38e10ef0e776d165f1b7d98a4cf7715464366f931007a\",\"license\":\"BSD-3-Clause\"},\"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\",\"keccak256\":\"0x4c25e30635485d162177effa384eee51768b0141a567a0da16ff6ad673274166\",\"license\":\"BSD-3-Clause\"},\"contracts/Pool/PoolRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\nimport { PoolRegistryInterface } from \\\"./PoolRegistryInterface.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"../lib/validators.sol\\\";\\n\\n/**\\n * @title PoolRegistry\\n * @author Venus\\n * @notice The Isolated Pools architecture centers around the `PoolRegistry` contract. The `PoolRegistry` maintains a directory of isolated lending\\n * pools and can perform actions like creating and registering new pools, adding new markets to existing pools, setting and updating the pool's required\\n * metadata, and providing the getter methods to get information on the pools.\\n *\\n * Isolated lending has three main components: PoolRegistry, pools, and markets. The PoolRegistry is responsible for managing pools.\\n * It can create new pools, update pool metadata and manage markets within pools. PoolRegistry contains getter methods to get the details of\\n * any existing pool like `getVTokenForAsset` and `getPoolsSupportedByAsset`. It also contains methods for updating pool metadata (`updatePoolMetadata`)\\n * and setting pool name (`setPoolName`).\\n *\\n * The directory of pools is managed through two mappings: `_poolByComptroller` which is a hashmap with the comptroller address as the key and `VenusPool` as\\n * the value and `_poolsByID` which is an array of comptroller addresses. Individual pools can be accessed by calling `getPoolByComptroller` with the pool's\\n * comptroller address. `_poolsByID` is used to iterate through all of the pools.\\n *\\n * PoolRegistry also contains a map of asset addresses called `_supportedPools` that maps to an array of assets suppored by each pool. This array of pools by\\n * asset is retrieved by calling `getPoolsSupportedByAsset`.\\n *\\n * PoolRegistry registers new isolated pools in the directory with the `createRegistryPool` method. Isolated pools are composed of independent markets with\\n * specific assets and custom risk management configurations according to their markets.\\n */\\ncontract PoolRegistry is Ownable2StepUpgradeable, AccessControlledV8, PoolRegistryInterface {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n struct AddMarketInput {\\n VToken vToken;\\n uint256 collateralFactor;\\n uint256 liquidationThreshold;\\n uint256 initialSupply;\\n address vTokenReceiver;\\n uint256 supplyCap;\\n uint256 borrowCap;\\n }\\n\\n uint256 internal constant MAX_POOL_NAME_LENGTH = 100;\\n\\n /**\\n * @notice Maps pool's comptroller address to metadata.\\n */\\n mapping(address => VenusPoolMetaData) public metadata;\\n\\n /**\\n * @dev Maps pool ID to pool's comptroller address\\n */\\n mapping(uint256 => address) private _poolsByID;\\n\\n /**\\n * @dev Total number of pools created.\\n */\\n uint256 private _numberOfPools;\\n\\n /**\\n * @dev Maps comptroller address to Venus pool Index.\\n */\\n mapping(address => VenusPool) private _poolByComptroller;\\n\\n /**\\n * @dev Maps pool's comptroller address to asset to vToken.\\n */\\n mapping(address => mapping(address => address)) private _vTokens;\\n\\n /**\\n * @dev Maps asset to list of supported pools.\\n */\\n mapping(address => address[]) private _supportedPools;\\n\\n /**\\n * @notice Emitted when a new Venus pool is added to the directory.\\n */\\n event PoolRegistered(address indexed comptroller, VenusPool pool);\\n\\n /**\\n * @notice Emitted when a pool name is set.\\n */\\n event PoolNameSet(address indexed comptroller, string oldName, string newName);\\n\\n /**\\n * @notice Emitted when a pool metadata is updated.\\n */\\n event PoolMetadataUpdated(\\n address indexed comptroller,\\n VenusPoolMetaData oldMetadata,\\n VenusPoolMetaData newMetadata\\n );\\n\\n /**\\n * @notice Emitted when a Market is added to the pool.\\n */\\n event MarketAdded(address indexed comptroller, address indexed vTokenAddress);\\n\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor() {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializes the deployer to owner\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(address accessControlManager_) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n /**\\n * @notice Adds a new Venus pool to the directory\\n * @dev Price oracle must be configured before adding a pool\\n * @param name The name of the pool\\n * @param comptroller Pool's Comptroller contract\\n * @param closeFactor The pool's close factor (scaled by 1e18)\\n * @param liquidationIncentive The pool's liquidation incentive (scaled by 1e18)\\n * @param minLiquidatableCollateral Minimal collateral for regular (non-batch) liquidations flow\\n * @return index The index of the registered Venus pool\\n * @custom:error ZeroAddressNotAllowed is thrown when Comptroller address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\\n */\\n function addPool(\\n string calldata name,\\n Comptroller comptroller,\\n uint256 closeFactor,\\n uint256 liquidationIncentive,\\n uint256 minLiquidatableCollateral\\n ) external virtual returns (uint256 index) {\\n _checkAccessAllowed(\\\"addPool(string,address,uint256,uint256,uint256)\\\");\\n // Input validation\\n ensureNonzeroAddress(address(comptroller));\\n ensureNonzeroAddress(address(comptroller.oracle()));\\n\\n uint256 poolId = _registerPool(name, address(comptroller));\\n\\n // Set Venus pool parameters\\n comptroller.setCloseFactor(closeFactor);\\n comptroller.setLiquidationIncentive(liquidationIncentive);\\n comptroller.setMinLiquidatableCollateral(minLiquidatableCollateral);\\n\\n return poolId;\\n }\\n\\n /**\\n * @notice Add a market to an existing pool and then mint to provide initial supply\\n * @param input The structure describing the parameters for adding a market to a pool\\n * @custom:error ZeroAddressNotAllowed is thrown when vToken address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when vTokenReceiver address is zero\\n */\\n function addMarket(AddMarketInput memory input) external {\\n _checkAccessAllowed(\\\"addMarket(AddMarketInput)\\\");\\n ensureNonzeroAddress(address(input.vToken));\\n ensureNonzeroAddress(input.vTokenReceiver);\\n require(input.initialSupply > 0, \\\"PoolRegistry: initialSupply is zero\\\");\\n\\n VToken vToken = input.vToken;\\n address vTokenAddress = address(vToken);\\n address comptrollerAddress = address(vToken.comptroller());\\n Comptroller comptroller = Comptroller(comptrollerAddress);\\n address underlyingAddress = vToken.underlying();\\n IERC20Upgradeable underlying = IERC20Upgradeable(underlyingAddress);\\n\\n require(_poolByComptroller[comptrollerAddress].creator != address(0), \\\"PoolRegistry: Pool not registered\\\");\\n // solhint-disable-next-line reason-string\\n require(\\n _vTokens[comptrollerAddress][underlyingAddress] == address(0),\\n \\\"PoolRegistry: Market already added for asset comptroller combination\\\"\\n );\\n\\n comptroller.supportMarket(vToken);\\n comptroller.setCollateralFactor(vToken, input.collateralFactor, input.liquidationThreshold);\\n\\n uint256[] memory newSupplyCaps = new uint256[](1);\\n uint256[] memory newBorrowCaps = new uint256[](1);\\n VToken[] memory vTokens = new VToken[](1);\\n\\n newSupplyCaps[0] = input.supplyCap;\\n newBorrowCaps[0] = input.borrowCap;\\n vTokens[0] = vToken;\\n\\n comptroller.setMarketSupplyCaps(vTokens, newSupplyCaps);\\n comptroller.setMarketBorrowCaps(vTokens, newBorrowCaps);\\n\\n _vTokens[comptrollerAddress][underlyingAddress] = vTokenAddress;\\n _supportedPools[underlyingAddress].push(comptrollerAddress);\\n\\n uint256 amountToSupply = _transferIn(underlying, msg.sender, input.initialSupply);\\n underlying.forceApprove(vTokenAddress, 0);\\n underlying.forceApprove(vTokenAddress, amountToSupply);\\n vToken.mintBehalf(input.vTokenReceiver, amountToSupply);\\n\\n emit MarketAdded(comptrollerAddress, vTokenAddress);\\n }\\n\\n /**\\n * @notice Modify existing Venus pool name\\n * @param comptroller Pool's Comptroller\\n * @param name New pool name\\n */\\n function setPoolName(address comptroller, string calldata name) external {\\n _checkAccessAllowed(\\\"setPoolName(address,string)\\\");\\n _ensureValidName(name);\\n VenusPool storage pool = _poolByComptroller[comptroller];\\n string memory oldName = pool.name;\\n pool.name = name;\\n emit PoolNameSet(comptroller, oldName, name);\\n }\\n\\n /**\\n * @notice Update metadata of an existing pool\\n * @param comptroller Pool's Comptroller\\n * @param metadata_ New pool metadata\\n */\\n function updatePoolMetadata(address comptroller, VenusPoolMetaData calldata metadata_) external {\\n _checkAccessAllowed(\\\"updatePoolMetadata(address,VenusPoolMetaData)\\\");\\n VenusPoolMetaData memory oldMetadata = metadata[comptroller];\\n metadata[comptroller] = metadata_;\\n emit PoolMetadataUpdated(comptroller, oldMetadata, metadata_);\\n }\\n\\n /**\\n * @notice Returns arrays of all Venus pools' data\\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\\n * @return A list of all pools within PoolRegistry, with details for each pool\\n */\\n function getAllPools() external view override returns (VenusPool[] memory) {\\n uint256 numberOfPools_ = _numberOfPools; // storage load to save gas\\n VenusPool[] memory _pools = new VenusPool[](numberOfPools_);\\n for (uint256 i = 1; i <= numberOfPools_; ++i) {\\n address comptroller = _poolsByID[i];\\n _pools[i - 1] = (_poolByComptroller[comptroller]);\\n }\\n return _pools;\\n }\\n\\n /**\\n * @param comptroller The comptroller proxy address associated to the pool\\n * @return Returns Venus pool\\n */\\n function getPoolByComptroller(address comptroller) external view override returns (VenusPool memory) {\\n return _poolByComptroller[comptroller];\\n }\\n\\n /**\\n * @param comptroller comptroller of Venus pool\\n * @return Returns Metadata of Venus pool\\n */\\n function getVenusPoolMetadata(address comptroller) external view override returns (VenusPoolMetaData memory) {\\n return metadata[comptroller];\\n }\\n\\n function getVTokenForAsset(address comptroller, address asset) external view override returns (address) {\\n return _vTokens[comptroller][asset];\\n }\\n\\n function getPoolsSupportedByAsset(address asset) external view override returns (address[] memory) {\\n return _supportedPools[asset];\\n }\\n\\n /**\\n * @dev Adds a new Venus pool to the directory (without checking msg.sender).\\n * @param name The name of the pool\\n * @param comptroller The pool's Comptroller proxy contract address\\n * @return The index of the registered Venus pool\\n */\\n function _registerPool(string calldata name, address comptroller) internal returns (uint256) {\\n VenusPool storage storedPool = _poolByComptroller[comptroller];\\n\\n require(storedPool.creator == address(0), \\\"PoolRegistry: Pool already exists in the directory.\\\");\\n _ensureValidName(name);\\n\\n ++_numberOfPools;\\n uint256 numberOfPools_ = _numberOfPools; // cache on stack to save storage read gas\\n\\n VenusPool memory pool = VenusPool(name, msg.sender, comptroller, block.number, block.timestamp);\\n\\n _poolsByID[numberOfPools_] = comptroller;\\n _poolByComptroller[comptroller] = pool;\\n\\n emit PoolRegistered(comptroller, pool);\\n return numberOfPools_;\\n }\\n\\n function _transferIn(IERC20Upgradeable token, address from, uint256 amount) internal returns (uint256) {\\n uint256 balanceBefore = token.balanceOf(address(this));\\n token.safeTransferFrom(from, address(this), amount);\\n uint256 balanceAfter = token.balanceOf(address(this));\\n return balanceAfter - balanceBefore;\\n }\\n\\n function _ensureValidName(string calldata name) internal pure {\\n require(bytes(name).length <= MAX_POOL_NAME_LENGTH, \\\"Pool's name is too large\\\");\\n }\\n}\\n\",\"keccak256\":\"0xafbb871f7b4db3ef439d846baa5f18a136192f9b43ea695c81262a77b06c4b25\",\"license\":\"BSD-3-Clause\"},\"contracts/Pool/PoolRegistryInterface.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 /**\\n * @notice Struct for a Venus interest rate pool metadata.\\n */\\n struct VenusPoolMetaData {\\n string category;\\n string logoURL;\\n string description;\\n }\\n\\n /// @notice Get all pools in PoolRegistry\\n function getAllPools() external view returns (VenusPool[] memory);\\n\\n /// @notice Get a pool by comptroller address\\n function getPoolByComptroller(address comptroller) external view returns (VenusPool memory);\\n\\n /// @notice Get the address of the VToken contract in the Pool where the underlying token is the provided 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 /// @notice Get the metadata of a Pool by comptroller address\\n function getVenusPoolMetadata(address comptroller) external view returns (VenusPoolMetaData memory);\\n}\\n\",\"keccak256\":\"0x7b39cda3b372a686501ce3c2aad288c6af410148110318249d75d4516729c92c\",\"license\":\"BSD-3-Clause\"},\"contracts/Rewards/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\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 { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"../MaxLoopsLimitHelper.sol\\\";\\nimport { RewardsDistributorStorage } from \\\"./RewardsDistributorStorage.sol\\\";\\n\\n/**\\n * @title `RewardsDistributor`\\n * @author Venus\\n * @notice Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol.\\n * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward\\n * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool.\\n * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward\\n * token to be released each slot (block or second) for borrowers and suppliers, which is distributed based on a user\\u2019s percentage of the borrows or supplies\\n * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting\\n * their contributor reward token speed, which similarly allocates a fixed amount of reward token per slot (block or second).\\n *\\n * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed\\n * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized\\n * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\\n */\\ncontract RewardsDistributor is\\n ExponentialNoError,\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n MaxLoopsLimitHelper,\\n RewardsDistributorStorage,\\n TimeManagerV8\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice The initial REWARD TOKEN index for a market\\n uint224 public constant INITIAL_INDEX = 1e36;\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a supplier\\n event DistributedSupplierRewardToken(\\n VToken indexed vToken,\\n address indexed supplier,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenSupplyIndex\\n );\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a borrower\\n event DistributedBorrowerRewardToken(\\n VToken indexed vToken,\\n address indexed borrower,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenBorrowIndex\\n );\\n\\n /// @notice Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when REWARD TOKEN is granted by admin\\n event RewardTokenGranted(address indexed recipient, uint256 amount);\\n\\n /// @notice Emitted when a new REWARD TOKEN speed is set for a contributor\\n event ContributorRewardTokenSpeedUpdated(address indexed contributor, uint256 newSpeed);\\n\\n /// @notice Emitted when a market is initialized\\n event MarketInitialized(address indexed vToken);\\n\\n /// @notice Emitted when a reward token supply index is updated\\n event RewardTokenSupplyIndexUpdated(address indexed vToken);\\n\\n /// @notice Emitted when a reward token borrow index is updated\\n event RewardTokenBorrowIndexUpdated(address indexed vToken, Exp marketBorrowIndex);\\n\\n /// @notice Emitted when a reward for contributor is updated\\n event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued);\\n\\n /// @notice Emitted when a reward token last rewarding block for supply is updated\\n event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding block for borrow is updated\\n event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding timestamp for supply is updated\\n event SupplyLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\\n\\n /// @notice Emitted when a reward token last rewarding timestamp for borrow is updated\\n event BorrowLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\\n\\n modifier onlyComptroller() {\\n require(address(comptroller) == msg.sender, \\\"Only comptroller can call this function\\\");\\n _;\\n }\\n\\n /**\\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice RewardsDistributor initializer\\n * @dev Initializes the deployer to owner\\n * @param comptroller_ Comptroller to attach the reward distributor to\\n * @param rewardToken_ Reward token to distribute\\n * @param loopsLimit_ Maximum number of iterations for the loops in this contract\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(\\n Comptroller comptroller_,\\n IERC20Upgradeable rewardToken_,\\n uint256 loopsLimit_,\\n address accessControlManager_\\n ) external initializer {\\n comptroller = comptroller_;\\n rewardToken = rewardToken_;\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n\\n _setMaxLoopsLimit(loopsLimit_);\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken\\n * @param vToken The address of the vToken to be initialized\\n * @custom:event MarketInitialized emits on success\\n * @custom:access Only Comptroller\\n */\\n function initializeMarket(address vToken) external onlyComptroller {\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n isTimeBased\\n ? _initializeMarketTimestampBased(vToken, blockNumberOrTimestamp)\\n : _initializeMarketBlockBased(vToken, safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\"));\\n\\n emit MarketInitialized(vToken);\\n }\\n\\n /*** Reward Token Distribution ***/\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them\\n * Borrowers will begin to accrue after the first interaction with the protocol.\\n * @dev This function should only be called when the user has a borrow position in the market\\n * (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook)\\n * We avoid an external call to check if they are in the market to save gas because this function is called in many places\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function distributeBorrowerRewardToken(\\n address vToken,\\n address borrower,\\n Exp memory marketBorrowIndex\\n ) external onlyComptroller {\\n _distributeBorrowerRewardToken(vToken, borrower, marketBorrowIndex);\\n }\\n\\n function updateRewardTokenSupplyIndex(address vToken) external onlyComptroller {\\n _updateRewardTokenSupplyIndex(vToken);\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the recipient\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\\n * @param recipient The address of the recipient to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n */\\n function grantRewardToken(address recipient, uint256 amount) external onlyOwner {\\n uint256 amountLeft = _grantRewardToken(recipient, amount);\\n require(amountLeft == 0, \\\"insufficient rewardToken for grant\\\");\\n emit RewardTokenGranted(recipient, amount);\\n }\\n\\n function updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) external onlyComptroller {\\n _updateRewardTokenBorrowIndex(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN borrow and supply speeds for the specified markets\\n * @param vTokens The markets whose REWARD TOKEN speed to update\\n * @param supplySpeeds New supply-side REWARD TOKEN speed for the corresponding market\\n * @param borrowSpeeds New borrow-side REWARD TOKEN speed for the corresponding market\\n */\\n function setRewardTokenSpeeds(\\n VToken[] memory vTokens,\\n uint256[] memory supplySpeeds,\\n uint256[] memory borrowSpeeds\\n ) external {\\n _checkAccessAllowed(\\\"setRewardTokenSpeeds(address[],uint256[],uint256[])\\\");\\n uint256 numTokens = vTokens.length;\\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \\\"invalid setRewardTokenSpeeds\\\");\\n\\n for (uint256 i; i < numTokens; ++i) {\\n _setRewardTokenSpeed(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for the specified markets, used when contract is block based\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market\\n * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market\\n */\\n function setLastRewardingBlocks(\\n VToken[] calldata vTokens,\\n uint32[] calldata supplyLastRewardingBlocks,\\n uint32[] calldata borrowLastRewardingBlocks\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlocks(address[],uint32[],uint32[])\\\");\\n require(!isTimeBased, \\\"Block-based operation only\\\");\\n\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length,\\n \\\"RewardsDistributor::setLastRewardingBlocks invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlock(vTokens[i], supplyLastRewardingBlocks[i], borrowLastRewardingBlocks[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block timestamp for the specified markets, used when contract is time based\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlockTimestamps New supply-side REWARD TOKEN last rewarding block timestamp for the corresponding market\\n * @param borrowLastRewardingBlockTimestamps New borrow-side REWARD TOKEN last rewarding block timestamp for the corresponding market\\n */\\n function setLastRewardingBlockTimestamps(\\n VToken[] calldata vTokens,\\n uint256[] calldata supplyLastRewardingBlockTimestamps,\\n uint256[] calldata borrowLastRewardingBlockTimestamps\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlockTimestamps(address[],uint256[],uint256[])\\\");\\n require(isTimeBased, \\\"Time-based operation only\\\");\\n\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlockTimestamps.length &&\\n numTokens == borrowLastRewardingBlockTimestamps.length,\\n \\\"RewardsDistributor::setLastRewardingBlockTimestamps invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlockTimestamp(\\n vTokens[i],\\n supplyLastRewardingBlockTimestamps[i],\\n borrowLastRewardingBlockTimestamps[i]\\n );\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single contributor\\n * @param contributor The contributor whose REWARD TOKEN speed to update\\n * @param rewardTokenSpeed New REWARD TOKEN speed for contributor\\n */\\n function setContributorRewardTokenSpeed(address contributor, uint256 rewardTokenSpeed) external onlyOwner {\\n // note that REWARD TOKEN speed could be set to 0 to halt liquidity rewards for a contributor\\n updateContributorRewards(contributor);\\n if (rewardTokenSpeed == 0) {\\n // release storage\\n delete lastContributorBlock[contributor];\\n } else {\\n lastContributorBlock[contributor] = getBlockNumberOrTimestamp();\\n }\\n rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed;\\n\\n emit ContributorRewardTokenSpeedUpdated(contributor, rewardTokenSpeed);\\n }\\n\\n function distributeSupplierRewardToken(address vToken, address supplier) external onlyComptroller {\\n _distributeSupplierRewardToken(vToken, supplier);\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in all markets\\n * @param holder The address to claim REWARD TOKEN for\\n */\\n function claimRewardToken(address holder) external {\\n return claimRewardToken(holder, comptroller.getAllMarkets());\\n }\\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) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Calculate additional accrued REWARD TOKEN for a contributor since last accrual\\n * @param contributor The address to calculate contributor rewards for\\n */\\n function updateContributorRewards(address contributor) public {\\n uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, lastContributorBlock[contributor]);\\n if (deltaBlocksOrTimestamp > 0 && rewardTokenSpeed > 0) {\\n uint256 newAccrued = mul_(deltaBlocksOrTimestamp, rewardTokenSpeed);\\n uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued);\\n\\n rewardTokenAccrued[contributor] = contributorAccrued;\\n lastContributorBlock[contributor] = blockNumberOrTimestamp;\\n\\n emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]);\\n }\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in the specified markets\\n * @param holder The address to claim REWARD TOKEN for\\n * @param vTokens The list of markets to claim REWARD TOKEN in\\n */\\n function claimRewardToken(address holder, VToken[] memory vTokens) public {\\n uint256 vTokensCount = vTokens.length;\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n VToken vToken = vTokens[i];\\n require(comptroller.isMarketListed(vToken), \\\"market must be listed\\\");\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n _distributeBorrowerRewardToken(address(vToken), holder, borrowIndex);\\n _updateRewardTokenSupplyIndex(address(vToken));\\n _distributeSupplierRewardToken(address(vToken), holder);\\n }\\n rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for a single market.\\n * @param vToken market's whose reward token last rewarding block to be updated\\n * @param supplyLastRewardingBlock New supply-side REWARD TOKEN last rewarding block for market\\n * @param borrowLastRewardingBlock New borrow-side REWARD TOKEN last rewarding block for market\\n */\\n function _setLastRewardingBlock(\\n VToken vToken,\\n uint32 supplyLastRewardingBlock,\\n uint32 borrowLastRewardingBlock\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockNumber = getBlockNumberOrTimestamp();\\n\\n require(supplyLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n require(borrowLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n\\n uint32 currentSupplyLastRewardingBlock = rewardTokenSupplyState[address(vToken)].lastRewardingBlock;\\n uint32 currentBorrowLastRewardingBlock = rewardTokenBorrowState[address(vToken)].lastRewardingBlock;\\n\\n require(\\n currentSupplyLastRewardingBlock == 0 || currentSupplyLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlock == 0 || currentBorrowLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlock != supplyLastRewardingBlock) {\\n rewardTokenSupplyState[address(vToken)].lastRewardingBlock = supplyLastRewardingBlock;\\n emit SupplyLastRewardingBlockUpdated(address(vToken), supplyLastRewardingBlock);\\n }\\n\\n if (currentBorrowLastRewardingBlock != borrowLastRewardingBlock) {\\n rewardTokenBorrowState[address(vToken)].lastRewardingBlock = borrowLastRewardingBlock;\\n emit BorrowLastRewardingBlockUpdated(address(vToken), borrowLastRewardingBlock);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding timestamp for a single market.\\n * @param vToken market's whose reward token last rewarding timestamp to be updated\\n * @param supplyLastRewardingBlockTimestamp New supply-side REWARD TOKEN last rewarding timestamp for market\\n * @param borrowLastRewardingBlockTimestamp New borrow-side REWARD TOKEN last rewarding timestamp for market\\n */\\n function _setLastRewardingBlockTimestamp(\\n VToken vToken,\\n uint256 supplyLastRewardingBlockTimestamp,\\n uint256 borrowLastRewardingBlockTimestamp\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockTimestamp = getBlockNumberOrTimestamp();\\n\\n require(\\n supplyLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"setting last rewarding timestamp in the past is not allowed\\\"\\n );\\n require(\\n borrowLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"setting last rewarding timestamp in the past is not allowed\\\"\\n );\\n\\n uint256 currentSupplyLastRewardingBlockTimestamp = rewardTokenSupplyStateTimeBased[address(vToken)]\\n .lastRewardingTimestamp;\\n uint256 currentBorrowLastRewardingBlockTimestamp = rewardTokenBorrowStateTimeBased[address(vToken)]\\n .lastRewardingTimestamp;\\n\\n require(\\n currentSupplyLastRewardingBlockTimestamp == 0 || currentSupplyLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlockTimestamp == 0 || currentBorrowLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlockTimestamp != supplyLastRewardingBlockTimestamp) {\\n rewardTokenSupplyStateTimeBased[address(vToken)].lastRewardingTimestamp = supplyLastRewardingBlockTimestamp;\\n emit SupplyLastRewardingBlockTimestampUpdated(address(vToken), supplyLastRewardingBlockTimestamp);\\n }\\n\\n if (currentBorrowLastRewardingBlockTimestamp != borrowLastRewardingBlockTimestamp) {\\n rewardTokenBorrowStateTimeBased[address(vToken)].lastRewardingTimestamp = borrowLastRewardingBlockTimestamp;\\n emit BorrowLastRewardingBlockTimestampUpdated(address(vToken), borrowLastRewardingBlockTimestamp);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single market.\\n * @param vToken market's whose reward token rate to be updated\\n * @param supplySpeed New supply-side REWARD TOKEN speed for market\\n * @param borrowSpeed New borrow-side REWARD TOKEN speed for market\\n */\\n function _setRewardTokenSpeed(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n if (rewardTokenSupplySpeeds[address(vToken)] != supplySpeed) {\\n // Supply speed updated so let's update supply state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n _updateRewardTokenSupplyIndex(address(vToken));\\n\\n // Update speed and emit event\\n rewardTokenSupplySpeeds[address(vToken)] = supplySpeed;\\n emit RewardTokenSupplySpeedUpdated(vToken, supplySpeed);\\n }\\n\\n if (rewardTokenBorrowSpeeds[address(vToken)] != borrowSpeed) {\\n // Borrow speed updated so let's update borrow state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n\\n // Update speed and emit event\\n rewardTokenBorrowSpeeds[address(vToken)] = borrowSpeed;\\n emit RewardTokenBorrowSpeedUpdated(vToken, borrowSpeed);\\n }\\n }\\n\\n /**\\n * @notice Calculate REWARD TOKEN 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 REWARD TOKEN to\\n */\\n function _distributeSupplierRewardToken(address vToken, address supplier) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\\n\\n uint256 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\\n uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier];\\n\\n // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenSupplierIndex[vToken][supplier] = supplyIndex;\\n\\n if (supplierIndex == 0 && supplyIndex >= INITIAL_INDEX) {\\n // Covers the case where users supplied tokens before the market's supply state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when supplier rewards were first\\n // set for the market.\\n supplierIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per vToken accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\\n\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerVToken\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n\\n uint256 supplierAccrued = add_(rewardTokenAccrued[supplier], supplierDelta);\\n rewardTokenAccrued[supplier] = supplierAccrued;\\n\\n emit DistributedSupplierRewardToken(VToken(vToken), supplier, supplierDelta, supplierAccrued, supplyIndex);\\n }\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them.\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function _distributeBorrowerRewardToken(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\\n\\n uint256 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\\n uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower];\\n\\n // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenBorrowerIndex[vToken][borrower] = borrowIndex;\\n\\n if (borrowerIndex == 0 && borrowIndex >= INITIAL_INDEX) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when borrower rewards were first\\n // set for the market.\\n borrowerIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per borrowed unit accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\\n\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerBorrowedUnit\\n if (borrowerAmount != 0) {\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n\\n uint256 borrowerAccrued = add_(rewardTokenAccrued[borrower], borrowerDelta);\\n rewardTokenAccrued[borrower] = borrowerAccrued;\\n\\n emit DistributedBorrowerRewardToken(VToken(vToken), borrower, borrowerDelta, borrowerAccrued, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the user.\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all.\\n * @param user The address of the user to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n * @return The amount of REWARD TOKEN which was NOT transferred to the user\\n */\\n function _grantRewardToken(address user, uint256 amount) internal returns (uint256) {\\n uint256 rewardTokenRemaining = rewardToken.balanceOf(address(this));\\n if (amount > 0 && amount <= rewardTokenRemaining) {\\n rewardToken.safeTransfer(user, amount);\\n return 0;\\n }\\n return amount;\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the supply index\\n * @param vToken The market whose supply index to update\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenSupplyIndex(address vToken) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\\n\\n uint256 supplySpeed = rewardTokenSupplySpeeds[vToken];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (!isTimeBased) {\\n safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\");\\n }\\n\\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\\n ? supplyStateTimeBased.lastRewardingTimestamp\\n : uint256(supplyState.lastRewardingBlock);\\n\\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(\\n blockNumberOrTimestamp,\\n (isTimeBased ? supplyStateTimeBased.timestamp : uint256(supplyState.block))\\n );\\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, supplySpeed);\\n Double memory ratio = supplyTokens > 0\\n ? fraction(accruedSinceUpdate, supplyTokens)\\n : Double({ mantissa: 0 });\\n uint224 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\\n uint224 index = safe224(\\n add_(Double({ mantissa: supplyIndex }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n\\n if (isTimeBased) {\\n supplyStateTimeBased.index = index;\\n supplyStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n supplyState.index = index;\\n supplyState.block = uint32(blockNumberOrTimestamp);\\n }\\n } else if (deltaBlocksOrTimestamp > 0) {\\n isTimeBased ? supplyStateTimeBased.timestamp = blockNumberOrTimestamp : supplyState.block = uint32(\\n blockNumberOrTimestamp\\n );\\n }\\n\\n emit RewardTokenSupplyIndexUpdated(vToken);\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the borrow index\\n * @param vToken The market whose borrow index to update\\n * @param marketBorrowIndex The current global borrow index of vToken\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\\n\\n uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (!isTimeBased) {\\n safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\");\\n }\\n\\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\\n ? borrowStateTimeBased.lastRewardingTimestamp\\n : uint256(borrowState.lastRewardingBlock);\\n\\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(\\n blockNumberOrTimestamp,\\n (isTimeBased ? borrowStateTimeBased.timestamp : uint256(borrowState.block))\\n );\\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, borrowSpeed);\\n Double memory ratio = borrowAmount > 0\\n ? fraction(accruedSinceUpdate, borrowAmount)\\n : Double({ mantissa: 0 });\\n uint224 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\\n uint224 index = safe224(\\n add_(Double({ mantissa: borrowIndex }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n\\n if (isTimeBased) {\\n borrowStateTimeBased.index = index;\\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n borrowState.index = index;\\n borrowState.block = uint32(blockNumberOrTimestamp);\\n }\\n } else if (deltaBlocksOrTimestamp > 0) {\\n if (isTimeBased) {\\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n borrowState.block = uint32(blockNumberOrTimestamp);\\n }\\n }\\n\\n emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken called when contract is block-based\\n * @param vToken The address of the vToken to be initialized\\n * @param blockNumber current block number\\n */\\n function _initializeMarketBlockBased(address vToken, uint32 blockNumber) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n RewardToken storage borrowState = rewardTokenBorrowState[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 = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block numbers\\n */\\n supplyState.block = borrowState.block = blockNumber;\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken called when contract is time-based\\n * @param vToken The address of the vToken to be initialized\\n * @param blockTimestamp current block timestamp\\n */\\n function _initializeMarketTimestampBased(address vToken, uint256 blockTimestamp) internal {\\n TimeBasedRewardToken storage supplyState = rewardTokenSupplyStateTimeBased[vToken];\\n TimeBasedRewardToken storage borrowState = rewardTokenBorrowStateTimeBased[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 = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block timestamp\\n */\\n supplyState.timestamp = borrowState.timestamp = blockTimestamp;\\n }\\n}\\n\",\"keccak256\":\"0x3cc824e59c923cfe25c4f1a875959b7e9410cde8e73cd405de13f301298c697f\",\"license\":\"BSD-3-Clause\"},\"contracts/Rewards/RewardsDistributorStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\n\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\n\\n/**\\n * @title RewardsDistributorStorage\\n * @author Venus\\n * @dev Storage for RewardsDistributor\\n */\\ncontract RewardsDistributorStorage {\\n struct RewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number the index was last updated at\\n uint32 block;\\n // The block number at which to stop rewards\\n uint32 lastRewardingBlock;\\n }\\n\\n struct TimeBasedRewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block timestamp the index was last updated at\\n uint256 timestamp;\\n // The block timestamp at which to stop rewards\\n uint256 lastRewardingTimestamp;\\n }\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => RewardToken) public rewardTokenSupplyState;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex;\\n\\n /// @notice The REWARD TOKEN accrued but not yet transferred to each user\\n mapping(address => uint256) public rewardTokenAccrued;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding borrow market per slot (block or second)\\n mapping(address => uint256) public rewardTokenBorrowSpeeds;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding supply market per slot (block or second)\\n mapping(address => uint256) public rewardTokenSupplySpeeds;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => RewardToken) public rewardTokenBorrowState;\\n\\n /// @notice The portion of REWARD TOKEN that each contributor receives per slot (block or second)\\n mapping(address => uint256) public rewardTokenContributorSpeeds;\\n\\n /// @notice Last slot (block or second) at which a contributor's REWARD TOKEN rewards have been allocated\\n mapping(address => uint256) public lastContributorBlock;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex;\\n\\n Comptroller internal comptroller;\\n\\n IERC20Upgradeable public rewardToken;\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => TimeBasedRewardToken) public rewardTokenSupplyStateTimeBased;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => TimeBasedRewardToken) public rewardTokenBorrowStateTimeBased;\\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[37] private __gap;\\n}\\n\",\"keccak256\":\"0x70e5015a78a2acf95277949c8b4796e10b9ac194130be006d5e5217e158070c0\",\"license\":\"BSD-3-Clause\"},\"contracts/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\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 { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"@venusprotocol/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\\\";\\n\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { ComptrollerInterface, ComptrollerViewInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"./ErrorReporter.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title VToken\\n * @author Venus\\n * @notice Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview,\\n * each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of\\n * the pool. The main actions a user regularly interacts with in a market are:\\n\\n- mint/redeem of vTokens;\\n- transfer of vTokens;\\n- borrow/repay a loan on an underlying asset;\\n- liquidate a borrow or liquidate/heal an account.\\n\\n * A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`.\\n * The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted\\n * `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken`\\n * as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that\\n * a user may borrow up to a portion of their collateral determined by the market\\u2019s collateral factor. However, if their borrowed amount exceeds an amount\\n * calculated using the market\\u2019s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also\\n * pay off interest accrued on the borrow.\\n * \\n * The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller`\\n * and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a\\n * total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`.\\n * Both functions settle all of an account\\u2019s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of\\n * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\\n */\\ncontract VToken is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n VTokenInterface,\\n ExponentialNoError,\\n TokenErrorReporter,\\n TimeManagerV8\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5%\\n\\n // Maximum fraction of interest that can be set aside for reserves\\n uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18;\\n\\n // Maximum borrow rate that can ever be applied per slot(block or second)\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n uint256 internal immutable MAX_BORROW_RATE_MANTISSA;\\n\\n /**\\n * Reentrancy Guard **\\n */\\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 * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @param maxBorrowRateMantissa_ The maximum value of borrowing rate mantissa\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(\\n bool timeBased_,\\n uint256 blocksPerYear_,\\n uint256 maxBorrowRateMantissa_\\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n require(maxBorrowRateMantissa_ <= 1e18, \\\"Max borrow rate must be <= 1e18\\\");\\n\\n MAX_BORROW_RATE_MANTISSA = maxBorrowRateMantissa_;\\n _disableInitializers();\\n }\\n\\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_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n */\\n function initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) external initializer {\\n ensureNonzeroAddress(admin_);\\n\\n // Initialize the market\\n _initialize(\\n underlying_,\\n comptroller_,\\n interestRateModel_,\\n initialExchangeRateMantissa_,\\n name_,\\n symbol_,\\n decimals_,\\n admin_,\\n accessControlManager_,\\n riskManagement,\\n reserveFactorMantissa_\\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 * @return success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, msg.sender, dst, amount);\\n return true;\\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 success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, src, dst, amount);\\n return true;\\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 (uint256.max means infinite)\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Increase approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param addedValue The number of additional tokens spender can transfer\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function increaseAllowance(address spender, uint256 addedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 newAllowance = transferAllowances[src][spender];\\n newAllowance += addedValue;\\n transferAllowances[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n return true;\\n }\\n\\n /**\\n * @notice Decreases approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param subtractedValue The number of tokens to remove from total approval\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 currentAllowance = transferAllowances[src][spender];\\n require(currentAllowance >= subtractedValue, \\\"decreased allowance below zero\\\");\\n unchecked {\\n currentAllowance -= subtractedValue;\\n }\\n\\n transferAllowances[src][spender] = currentAllowance;\\n\\n emit Approval(src, spender, currentAllowance);\\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 amount The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint256) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return totalBorrows The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\\n accrueInterest();\\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 borrowBalance The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n return _borrowBalanceStored(account);\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function mint(uint256 mintAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _mintFresh(msg.sender, msg.sender, mintAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param minter User whom the supply will be attributed to\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when minter address is zero\\n */\\n function mintBehalf(address minter, uint256 mintAmount) external override nonReentrant returns (uint256) {\\n ensureNonzeroAddress(minter);\\n\\n accrueInterest();\\n\\n _mintFresh(msg.sender, minter, mintAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function redeem(uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _redeemFresh(msg.sender, msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function redeemBehalf(address redeemer, uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n _ensureSenderIsDelegateOf(redeemer);\\n\\n accrueInterest();\\n\\n _redeemFresh(redeemer, msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\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 receive from redeeming vTokens\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n */\\n function redeemUnderlying(uint256 redeemAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _redeemFresh(msg.sender, msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function redeemUnderlyingBehalf(\\n address redeemer,\\n uint256 redeemAmount\\n ) external override nonReentrant returns (uint256) {\\n _ensureSenderIsDelegateOf(redeemer);\\n\\n accrueInterest();\\n\\n _redeemFresh(redeemer, msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function borrow(uint256 borrowAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _borrowFresh(msg.sender, msg.sender, borrowAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error DelegateNotApproved is thrown if caller is not approved delegate\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function borrowBehalf(address borrower, uint256 borrowAmount) external override returns (uint256) {\\n _ensureSenderIsDelegateOf(borrower);\\n accrueInterest();\\n\\n _borrowFresh(borrower, msg.sender, borrowAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrow(uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n return NO_ERROR;\\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, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _repayBorrowFresh(msg.sender, borrower, repayAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Not restricted\\n */\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external override returns (uint256) {\\n _liquidateBorrow(msg.sender, borrower, repayAmount, vTokenCollateral, false);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice sets protocol share accumulated from liquidations\\n * @dev must be equal or less than liquidation incentive - 1\\n * @param newProtocolSeizeShareMantissa_ new protocol share mantissa\\n * @custom:event Emits NewProtocolSeizeShare event on success\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error ProtocolSeizeShareTooBig is thrown when the new seize share is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa_) external {\\n _checkAccessAllowed(\\\"setProtocolSeizeShare(uint256)\\\");\\n uint256 liquidationIncentive = ComptrollerViewInterface(address(comptroller)).liquidationIncentiveMantissa();\\n if (newProtocolSeizeShareMantissa_ + MANTISSA_ONE > liquidationIncentive) {\\n revert ProtocolSeizeShareTooBig();\\n }\\n\\n uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\\n protocolSeizeShareMantissa = newProtocolSeizeShareMantissa_;\\n emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa_);\\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 * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n * @custom:event Emits NewReserveFactor event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant {\\n _checkAccessAllowed(\\\"setReserveFactor(uint256)\\\");\\n\\n accrueInterest();\\n _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to the protocol reserve contract\\n * @dev Gracefully return if reserves already reduced in accrueInterest\\n * @param reduceAmount Amount of reduction to reserves\\n * @custom:event Emits ReservesReduced event; may emit AccrueInterest\\n * @custom:error ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash\\n * @custom:error ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\\n * @custom:access Not restricted\\n */\\n function reduceReserves(uint256 reduceAmount) external override nonReentrant {\\n accrueInterest();\\n if (reduceReservesBlockNumber == getBlockNumberOrTimestamp()) return;\\n _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice The sender adds to reserves.\\n * @param addAmount The amount of underlying token to add as reserves\\n * @custom:event Emits ReservesAdded event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function addReserves(uint256 addAmount) external override nonReentrant {\\n accrueInterest();\\n _addReservesFresh(addAmount);\\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 * @custom:event Emits NewMarketInterestRateModel event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external override {\\n _checkAccessAllowed(\\\"setInterestRateModel(address)\\\");\\n\\n accrueInterest();\\n _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially\\n * \\\"forgiving\\\" the borrower. Healing is a situation that should rarely happen. However, some pools\\n * may list risky assets or be configured improperly \\u2013 we want to still handle such cases gracefully.\\n * We assume that Comptroller does the seizing, so this function is only available to Comptroller.\\n * @dev This function does not call any Comptroller hooks (like \\\"healAllowed\\\"), because we assume\\n * the Comptroller does all the necessary checks before calling this function.\\n * @param payer account who repays the debt\\n * @param borrower account to heal\\n * @param repayAmount amount to repay\\n * @custom:event Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\\n * @custom:error HealBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:access Only Comptroller\\n */\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external override nonReentrant {\\n if (repayAmount != 0) {\\n comptroller.preRepayHook(address(this), borrower);\\n }\\n\\n if (msg.sender != address(comptroller)) {\\n revert HealBorrowUnauthorized();\\n }\\n\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 totalBorrowsNew = totalBorrows;\\n\\n uint256 actualRepayAmount;\\n if (repayAmount != 0) {\\n // _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // We violate checks-effects-interactions here to account for tokens that take transfer fees\\n actualRepayAmount = _doTransferIn(payer, repayAmount);\\n totalBorrowsNew = totalBorrowsNew - actualRepayAmount;\\n emit RepayBorrow(\\n payer,\\n borrower,\\n actualRepayAmount,\\n accountBorrowsPrev - actualRepayAmount,\\n totalBorrowsNew\\n );\\n }\\n\\n // The transaction will fail if trying to repay too much\\n uint256 badDebtDelta = accountBorrowsPrev - actualRepayAmount;\\n if (badDebtDelta != 0) {\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld + badDebtDelta;\\n totalBorrowsNew = totalBorrowsNew - badDebtDelta;\\n badDebt = badDebtNew;\\n\\n // We treat healing as \\\"repayment\\\", where vToken is the payer\\n emit RepayBorrow(address(this), borrower, badDebtDelta, 0, totalBorrowsNew);\\n emit BadDebtIncreased(borrower, badDebtDelta, badDebtOld, badDebtNew);\\n }\\n\\n accountBorrows[borrower].principal = 0;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n emit HealBorrow(payer, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice The extended version of liquidations, callable only by Comptroller. May skip\\n * the close factor check. The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Only Comptroller\\n */\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) external override {\\n if (msg.sender != address(comptroller)) {\\n revert ForceLiquidateBorrowUnauthorized();\\n }\\n _liquidateBorrow(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\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 * @custom:event Emits Transfer, ReservesAdded events\\n * @custom:error LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:access Not restricted\\n */\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external override nonReentrant {\\n _seize(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Updates bad debt\\n * @dev Called only when bad debt is recovered from auction\\n * @param recoveredAmount_ The amount of bad debt recovered\\n * @custom:event Emits BadDebtRecovered event\\n * @custom:access Only Shortfall contract\\n */\\n function badDebtRecovered(uint256 recoveredAmount_) external {\\n require(msg.sender == shortfall, \\\"only shortfall contract can update bad debt\\\");\\n require(recoveredAmount_ <= badDebt, \\\"more than bad debt recovered from auction\\\");\\n\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld - recoveredAmount_;\\n badDebt = badDebtNew;\\n\\n emit BadDebtRecovered(badDebtOld, badDebtNew);\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protocolShareReserve_ The address of the protocol share reserve contract\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n * @custom:access Only Governance\\n */\\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\\n _setProtocolShareReserve(protocolShareReserve_);\\n }\\n\\n /**\\n * @notice Sets shortfall contract address\\n * @param shortfall_ The address of the shortfall contract\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:access Only Governance\\n */\\n function setShortfallContract(address shortfall_) external onlyOwner {\\n _setShortfallContract(shortfall_);\\n }\\n\\n /**\\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\\n * @param token The address of the ERC-20 token to sweep\\n * @custom:access Only Governance\\n */\\n function sweepToken(IERC20Upgradeable token) external override {\\n require(msg.sender == owner(), \\\"VToken::sweepToken: only admin can sweep tokens\\\");\\n require(address(token) != underlying, \\\"VToken::sweepToken: can not sweep underlying token\\\");\\n uint256 balance = token.balanceOf(address(this));\\n token.safeTransfer(owner(), balance);\\n\\n emit SweepToken(address(token));\\n }\\n\\n /**\\n * @notice A public function to set new threshold of slot(block or second) difference after which funds will be sent to the protocol share reserve\\n * @param _newReduceReservesBlockOrTimestampDelta slot(block or second) difference value\\n * @custom:access Only Governance\\n */\\n function setReduceReservesBlockDelta(uint256 _newReduceReservesBlockOrTimestampDelta) external {\\n _checkAccessAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n require(_newReduceReservesBlockOrTimestampDelta > 0, \\\"Invalid Input\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, _newReduceReservesBlockOrTimestampDelta);\\n reduceReservesBlockDelta = _newReduceReservesBlockOrTimestampDelta;\\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 amount 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 amount 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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return vTokenBalance User's balance of vTokens\\n * @return borrowBalance Amount owed in terms of underlying\\n * @return exchangeRate Stored exchange rate\\n */\\n function getAccountSnapshot(\\n address account\\n )\\n external\\n view\\n override\\n returns (uint256 error, uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRate)\\n {\\n return (NO_ERROR, accountTokens[account], _borrowBalanceStored(account), _exchangeRateStored());\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return cash The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint256) {\\n return _getCashPrior();\\n }\\n\\n /**\\n * @notice Returns the current per slot(block or second) borrow interest rate for this vToken\\n * @return rate The borrow interest rate per slot(block or second), scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint256) {\\n return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt);\\n }\\n\\n /**\\n * @notice Returns the current per-slot(block or second) supply interest rate for this v\\n * @return rate The supply interest rate per slot(block or second), scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint256) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPrior(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa,\\n badDebt\\n );\\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 borrowBalance The calculated balance\\n */\\n function borrowBalanceStored(address account) external view override returns (uint256) {\\n return _borrowBalanceStored(account);\\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 exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() external view override returns (uint256) {\\n return _exchangeRateStored();\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\\n accrueInterest();\\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 slot(block or second)\\n * up to the current slot(block or second) and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentSlot - reduceReservesBlockNumber >= slotDelta\\n * @return Always NO_ERROR\\n * @custom:event Emits AccrueInterest event on success\\n * @custom:access Not restricted\\n */\\n function accrueInterest() public virtual override returns (uint256) {\\n /* Remember the initial block number or timestamp */\\n uint256 currentSlotNumber = getBlockNumberOrTimestamp();\\n uint256 accrualSlotNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualSlotNumberPrior == currentSlotNumber) {\\n return NO_ERROR;\\n }\\n\\n /* Read the previous values out of storage */\\n uint256 cashPrior = _getCashPrior();\\n uint256 borrowsPrior = totalBorrows;\\n uint256 reservesPrior = totalReserves;\\n uint256 borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt);\\n require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of slots elapsed since the last accrual */\\n uint256 slotDelta = currentSlotNumber - accrualSlotNumberPrior;\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * slotDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), slotDelta);\\n uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\\n uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;\\n uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentSlotNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n if (currentSlotNumber - reduceReservesBlockNumber >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentSlotNumber;\\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 NO_ERROR;\\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 or timestamp\\n * @param payer The address of the account which is sending the assets for supply\\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 */\\n function _mintFresh(address payer, address minter, uint256 mintAmount) internal {\\n /* Fail if mint not allowed */\\n comptroller.preMintHook(address(this), minter, mintAmount);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert MintFreshnessCheck();\\n }\\n\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\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 * `_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 uint256 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 uint256 mintTokens = div_(actualMintAmount, exchangeRate);\\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 * And write them into storage\\n */\\n totalSupply = totalSupply + mintTokens;\\n uint256 balanceAfter = accountTokens[minter] + mintTokens;\\n accountTokens[minter] = balanceAfter;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, actualMintAmount, mintTokens, balanceAfter);\\n emit Transfer(address(0), minter, mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, actualMintAmount, mintTokens);\\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 Comptroller.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current slot(block or second)\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the underlying 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 */\\n function _redeemFresh(address redeemer, address receiver, uint256 redeemTokensIn, uint256 redeemAmountIn) internal {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert RedeemFreshnessCheck();\\n }\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n\\n uint256 redeemTokens;\\n uint256 redeemAmount;\\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 */\\n redeemTokens = redeemTokensIn;\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n */\\n redeemTokens = div_(redeemAmountIn, exchangeRate);\\n\\n uint256 _redeemAmount = mul_(redeemTokens, exchangeRate);\\n if (_redeemAmount != 0 && _redeemAmount != redeemAmountIn) redeemTokens++; // round up\\n }\\n\\n // redeemAmount = exchangeRate * redeemTokens\\n redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokens);\\n\\n // Revert if amount is zero\\n if (redeemAmount == 0) {\\n revert(\\\"redeemAmount is zero\\\");\\n }\\n\\n /* Fail if redeem not allowed */\\n comptroller.preRedeemHook(address(this), redeemer, redeemTokens);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (_getCashPrior() - totalReserves < redeemAmount) {\\n revert RedeemTransferOutNotPossible();\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\\n */\\n totalSupply = totalSupply - redeemTokens;\\n uint256 balanceAfter = accountTokens[redeemer] - redeemTokens;\\n accountTokens[redeemer] = balanceAfter;\\n\\n /*\\n * We invoke _doTransferOut for the receiver and the redeemAmount.\\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 _doTransferOut(receiver, redeemAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), redeemTokens);\\n emit Redeem(redeemer, redeemAmount, redeemTokens, balanceAfter);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, redeemAmount, redeemTokens);\\n }\\n\\n /**\\n * @notice Users or their delegates borrow assets from the protocol\\n * @param borrower User who borrows the assets\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param borrowAmount The amount of the underlying asset to borrow\\n */\\n function _borrowFresh(address borrower, address receiver, uint256 borrowAmount) internal {\\n /* Fail if borrow not allowed */\\n comptroller.preBorrowHook(address(this), borrower, borrowAmount);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert BorrowFreshnessCheck();\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (_getCashPrior() - totalReserves < borrowAmount) {\\n revert BorrowCashNotAvailable();\\n }\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowNew = accountBorrow + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;\\n uint256 totalBorrowsNew = totalBorrows + borrowAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\\n `*/\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /*\\n * We invoke _doTransferOut for the receiver and the borrowAmount.\\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, accountBorrowsNew, totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\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 underlying tokens being returned, or type(uint256).max for the full outstanding amount\\n * @return (uint) the actual repayment amount.\\n */\\n function _repayBorrowFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256) {\\n /* Fail if repayBorrow not allowed */\\n comptroller.preRepayHook(address(this), borrower);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert RepayBorrowFreshnessCheck();\\n }\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n\\n uint256 repayAmountFinal = repayAmount >= accountBorrowsPrev ? accountBorrowsPrev : 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 * 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 uint256 actualRepayAmount = _doTransferIn(payer, repayAmountFinal);\\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 uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\\n uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, actualRepayAmount, borrowIndex);\\n\\n return actualRepayAmount;\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal nonReentrant {\\n accrueInterest();\\n\\n uint256 error = vTokenCollateral.accrueInterest();\\n if (error != NO_ERROR) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n revert LiquidateAccrueCollateralInterestFailed(error);\\n }\\n\\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal {\\n /* Fail if liquidate not allowed */\\n comptroller.preLiquidateHook(\\n address(this),\\n address(vTokenCollateral),\\n borrower,\\n repayAmount,\\n skipLiquidityCheck\\n );\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert LiquidateFreshnessCheck();\\n }\\n\\n /* Verify vTokenCollateral market's slot(block or second) number equals current slot(block or second) number */\\n if (vTokenCollateral.accrualBlockNumber() != getBlockNumberOrTimestamp()) {\\n revert LiquidateCollateralFreshnessCheck();\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateLiquidatorIsBorrower();\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n revert LiquidateCloseAmountIsZero();\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n revert LiquidateCloseAmountIsUintMax();\\n }\\n\\n /* Fail if repayBorrow fails */\\n uint256 actualRepayAmount = _repayBorrowFresh(liquidator, borrower, repayAmount);\\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.liquidateCalculateSeizeTokens(\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n require(amountSeizeError == 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, call _seize internally to avoid re-entrancy, otherwise make an external call\\n if (address(vTokenCollateral) == address(this)) {\\n _seize(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\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\\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 * It's absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerContract The contract seizing the collateral (either borrowed vToken or Comptroller)\\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 */\\n function _seize(address seizerContract, address liquidator, address borrower, uint256 seizeTokens) internal {\\n /* Fail if seize not allowed */\\n comptroller.preSeizeHook(address(this), seizerContract, liquidator, borrower);\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateSeizeLiquidatorIsBorrower();\\n }\\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 uint256 liquidationIncentiveMantissa = ComptrollerViewInterface(address(comptroller))\\n .liquidationIncentiveMantissa();\\n uint256 numerator = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));\\n uint256 protocolSeizeTokens = div_(numerator, Exp({ mantissa: liquidationIncentiveMantissa }));\\n uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n uint256 protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the calculated values into storage */\\n totalSupply = totalSupply - protocolSeizeTokens;\\n accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\\n accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\\n\\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, protocolSeizeAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.LIQUIDATION\\n );\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\\n emit ProtocolSeize(borrower, protocolShareReserve, protocolSeizeAmount);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerContract, liquidator, borrower, seizeTokens);\\n }\\n\\n function _setComptroller(ComptrollerInterface newComptroller) internal {\\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\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n */\\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal {\\n // Verify market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert SetReserveFactorFreshCheck();\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > MAX_RESERVE_FACTOR_MANTISSA) {\\n revert SetReserveFactorBoundsCheck();\\n }\\n\\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\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 actualAddAmount The actual amount added, excluding the potential token fees\\n */\\n function _addReservesFresh(uint256 addAmount) internal returns (uint256) {\\n // totalReserves + actualAddAmount\\n uint256 totalReservesNew;\\n uint256 actualAddAmount;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert AddReservesFactorFreshCheck(actualAddAmount);\\n }\\n\\n actualAddAmount = _doTransferIn(msg.sender, addAmount);\\n totalReservesNew = totalReserves + actualAddAmount;\\n totalReserves = totalReservesNew;\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n return actualAddAmount;\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to the protocol reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n */\\n function _reduceReservesFresh(uint256 reduceAmount) internal {\\n if (reduceAmount == 0) {\\n return;\\n }\\n // totalReserves - reduceAmount\\n uint256 totalReservesNew;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert ReduceReservesFreshCheck();\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (_getCashPrior() < reduceAmount) {\\n revert ReduceReservesCashNotAvailable();\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n revert ReduceReservesCashValidation();\\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 // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, reduceAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit SpreadReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal {\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert SetInterestRateModelFreshCheck();\\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\\n /**\\n * Safe Token **\\n */\\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 returns (uint256) {\\n IERC20Upgradeable token = IERC20Upgradeable(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 to, uint256 amount) internal virtual {\\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\\n token.safeTransfer(to, amount);\\n }\\n\\n /**\\n * @notice Transfer `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 */\\n function _transferTokens(address spender, address src, address dst, uint256 tokens) internal {\\n /* Fail if transfer not allowed */\\n comptroller.preTransferHook(address(this), src, dst, tokens);\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n revert TransferNotAllowed();\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint256 startingAllowance;\\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 uint256 allowanceNew = startingAllowance - tokens;\\n uint256 srcTokensNew = accountTokens[src] - tokens;\\n uint256 dstTokensNew = accountTokens[dst] + tokens;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n\\n accountTokens[src] = srcTokensNew;\\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\\n /**\\n * @notice Initialize the 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_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n */\\n function _initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\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 _setComptroller(comptroller_);\\n\\n // Initialize slot(block or second) number and borrow index (slot(block or second) number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumberOrTimestamp();\\n borrowIndex = MANTISSA_ONE;\\n\\n // Set the interest rate model (depends on slot(block or second) number / borrow index)\\n _setInterestRateModelFresh(interestRateModel_);\\n\\n _setReserveFactorFresh(reserveFactorMantissa_);\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n _setShortfallContract(riskManagement.shortfall);\\n _setProtocolShareReserve(riskManagement.protocolShareReserve);\\n protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA;\\n\\n // Set underlying and sanity check it\\n underlying = underlying_;\\n IERC20Upgradeable(underlying).totalSupply();\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n _transferOwnership(admin_);\\n }\\n\\n function _setShortfallContract(address shortfall_) internal {\\n ensureNonzeroAddress(shortfall_);\\n address oldShortfall = shortfall;\\n shortfall = shortfall_;\\n emit NewShortfallContract(oldShortfall, shortfall_);\\n }\\n\\n function _setProtocolShareReserve(address payable protocolShareReserve_) internal {\\n ensureNonzeroAddress(protocolShareReserve_);\\n address oldProtocolShareReserve = address(protocolShareReserve);\\n protocolShareReserve = protocolShareReserve_;\\n emit NewProtocolShareReserve(oldProtocolShareReserve, address(protocolShareReserve_));\\n }\\n\\n function _ensureSenderIsDelegateOf(address user) internal view {\\n if (!ComptrollerViewInterface(address(comptroller)).approvedDelegates(user, msg.sender)) {\\n revert DelegateNotApproved();\\n }\\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 virtual returns (uint256) {\\n return IERC20Upgradeable(underlying).balanceOf(address(this));\\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 borrowBalance the calculated balance\\n */\\n function _borrowBalanceStored(address account) internal view returns (uint256) {\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot memory 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 0;\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;\\n\\n return principalTimesIndex / borrowSnapshot.interestIndex;\\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 exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function _exchangeRateStored() internal view virtual returns (uint256) {\\n uint256 _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return initialExchangeRateMantissa;\\n }\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply\\n */\\n uint256 totalCash = _getCashPrior();\\n uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;\\n uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply;\\n\\n return exchangeRate;\\n }\\n}\\n\",\"keccak256\":\"0xa220ca317fe69b920b86e43f054c43b5f891f12160fd312c9a21668f969ee056\",\"license\":\"BSD-3-Clause\"},\"contracts/VTokenInterfaces.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\\nimport { ComptrollerInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title VTokenStorage\\n * @author Venus\\n * @notice Storage layout used by the `VToken` contract\\n */\\n// solhint-disable-next-line max-states-count\\ncontract VTokenStorage {\\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 uint256 principal;\\n uint256 interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\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 Protocol share Reserve contract address\\n */\\n address payable public protocolShareReserve;\\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 InterestRateModel public interestRateModel;\\n\\n // Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n uint256 internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint256 public reserveFactorMantissa;\\n\\n /**\\n * @notice Slot(block or second) number that interest was last accrued at\\n */\\n uint256 public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint256 public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint256 public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint256 public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint256 public totalSupply;\\n\\n /**\\n * @notice Total bad debt of the market\\n */\\n uint256 public badDebt;\\n\\n // Official record of token balances for each account\\n mapping(address => uint256) internal accountTokens;\\n\\n // Approved token transfer amounts on behalf of others\\n mapping(address => mapping(address => uint256)) internal transferAllowances;\\n\\n // Mapping of account addresses to outstanding borrow balances\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint256 public protocolSeizeShareMantissa;\\n\\n /**\\n * @notice Storage of Shortfall contract address\\n */\\n address public shortfall;\\n\\n /**\\n * @notice delta slot (block or second) after which reserves will be reduced\\n */\\n uint256 public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last slot (block or second) number at which reserves were reduced\\n */\\n uint256 public reduceReservesBlockNumber;\\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\\n/**\\n * @title VTokenInterface\\n * @author Venus\\n * @notice Interface implemented by the `VToken` contract\\n */\\nabstract contract VTokenInterface is VTokenStorage {\\n struct RiskManagementInit {\\n address shortfall;\\n address payable protocolShareReserve;\\n }\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address indexed minter, uint256 mintAmount, uint256 mintTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address indexed borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(\\n address indexed payer,\\n address indexed borrower,\\n uint256 repayAmount,\\n uint256 accountBorrows,\\n uint256 totalBorrows\\n );\\n\\n /**\\n * @notice Event emitted when bad debt is accumulated on a market\\n * @param borrower borrower to \\\"forgive\\\"\\n * @param badDebtDelta amount of new bad debt recorded\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtIncreased(address indexed borrower, uint256 badDebtDelta, uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when bad debt is recovered via an auction\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtRecovered(uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address indexed liquidator,\\n address indexed borrower,\\n uint256 repayAmount,\\n address indexed vTokenCollateral,\\n uint256 seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface indexed oldComptroller, ComptrollerInterface indexed newComptroller);\\n\\n /**\\n * @notice Event emitted when shortfall contract address is changed\\n */\\n event NewShortfallContract(address indexed oldShortfall, address indexed newShortfall);\\n\\n /**\\n * @notice Event emitted when protocol share reserve contract address is changed\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModel indexed oldInterestRateModel,\\n InterestRateModel indexed newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when protocol seize share is changed\\n */\\n event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address indexed benefactor, uint256 addAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the spread reserves are reduced\\n */\\n event SpreadReservesReduced(address indexed protocolShareReserve, uint256 reduceAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /**\\n * @notice Event emitted when healing the borrow\\n */\\n event HealBorrow(address indexed payer, address indexed borrower, uint256 repayAmount);\\n\\n /**\\n * @notice Event emitted when tokens are swept\\n */\\n event SweepToken(address indexed token);\\n\\n /**\\n * @notice Event emitted when reduce reserves slot (block or second) delta is changed\\n */\\n event NewReduceReservesBlockDelta(\\n uint256 oldReduceReservesBlockOrTimestampDelta,\\n uint256 newReduceReservesBlockOrTimestampDelta\\n );\\n\\n /**\\n * @notice Event emitted when liquidation reserves are reduced\\n */\\n event ProtocolSeize(address indexed from, address indexed to, uint256 amount);\\n\\n /*** User Interface ***/\\n\\n function mint(uint256 mintAmount) external virtual returns (uint256);\\n\\n function mintBehalf(address minter, uint256 mintAllowed) external virtual returns (uint256);\\n\\n function redeem(uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemBehalf(address redeemer, uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);\\n\\n function redeemUnderlyingBehalf(address redeemer, uint256 redeemAmount) external virtual returns (uint256);\\n\\n function borrow(uint256 borrowAmount) external virtual returns (uint256);\\n\\n function borrowBehalf(address borrwwer, uint256 borrowAmount) external virtual returns (uint256);\\n\\n function repayBorrow(uint256 repayAmount) external virtual returns (uint256);\\n\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external virtual returns (uint256);\\n\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external virtual;\\n\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipCloseFactorCheck\\n ) external virtual;\\n\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external virtual;\\n\\n function transfer(address dst, uint256 amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint256 amount) external virtual returns (bool);\\n\\n function accrueInterest() external virtual returns (uint256);\\n\\n function sweepToken(IERC20Upgradeable token) external virtual;\\n\\n /*** Admin Functions ***/\\n\\n function setReserveFactor(uint256 newReserveFactorMantissa) external virtual;\\n\\n function reduceReserves(uint256 reduceAmount) external virtual;\\n\\n function exchangeRateCurrent() external virtual returns (uint256);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint256);\\n\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external virtual;\\n\\n function addReserves(uint256 addAmount) external virtual;\\n\\n function totalBorrowsCurrent() external virtual returns (uint256);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint256);\\n\\n function approve(address spender, uint256 amount) external virtual returns (bool);\\n\\n function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool);\\n\\n function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint256);\\n\\n function balanceOf(address owner) external view virtual returns (uint256);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint256, uint256, uint256, uint256);\\n\\n function borrowRatePerBlock() external view virtual returns (uint256);\\n\\n function supplyRatePerBlock() external view virtual returns (uint256);\\n\\n function borrowBalanceStored(address account) external view virtual returns (uint256);\\n\\n function exchangeRateStored() external view virtual returns (uint256);\\n\\n function getCash() external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is a VToken contract (for inspection)\\n * @return Always true\\n */\\n function isVToken() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x7c4cbb879e3a931cfee4fa7a9eb1978eddff18087a1c4f56decedb84c2479f1e\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\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\",\"keccak256\":\"0x54ab3a6f3bc87569ed12370f3470a1ec84cea9796d4d0ccf3d07dd4280c044aa\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/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 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\",\"keccak256\":\"0x93bdd5cfb100f0f9a1d446857e23c3633df6ab12c266333c978428edd96b1367\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x60e060405234801561001057600080fd5b50604051613ffc380380613ffc83398101604081905261002f916100dc565b81818115801561003d575080155b1561005b576040516302723dfb60e21b815260040160405180910390fd5b81801561006757508015155b156100855760405163ae0fcab360e01b815260040160405180910390fd5b81151560a05281610096578061009c565b6301e133805b608052816100b3576100d460201b611d89176100be565b6100d860201b611d8d175b6001600160401b031660c0525061010f92505050565b4390565b4290565b600080604083850312156100ef57600080fd5b825180151581146100ff57600080fd5b6020939093015192949293505050565b60805160a05160c051613eb76101456000396000611d5d0152600081816102a60152611e5e015260006101d10152613eb76000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c80637c51b64211610097578063c7ad089511610066578063c7ad0895146102a1578063d77ebf96146102d8578063e0a67f11146102f8578063e1d146fb1461031857600080fd5b80637c51b642146102215780637c84e3b314610241578063aa5dbd2314610261578063b31242391461028157600080fd5b806347d86a81116100d357806347d86a811461018e57806355dd9515146101a15780636857249c146101cc5780637a27db571461020157600080fd5b80630d3ae318146101055780631f884fdf1461012e578063345954dc1461014e5780633e3e399c1461016e575b600080fd5b610118610113366004612ece565b610320565b604051610125919061323b565b60405180910390f35b61014161013c366004613299565b610655565b60405161012591906132da565b61016161015c36600461333a565b61071d565b6040516101259190613357565b61018161017c36600461333a565b610850565b60405161012591906133bb565b61011861019c366004613445565b610bc2565b6101b46101af36600461347e565b610c49565b6040516001600160a01b039091168152602001610125565b6101f37f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610125565b61021461020f366004613445565b610cc9565b60405161012591906134c9565b61023461022f3660046135a5565b610fd6565b6040516101259190613630565b61025461024f36600461333a565b61108f565b604051610125919061367e565b61027461026f36600461333a565b6111f9565b604051610125919061369e565b61029461028f366004613445565b611947565b60405161012591906136ad565b6102c87f000000000000000000000000000000000000000000000000000000000000000081565b6040519015158152602001610125565b6102eb6102e6366004613445565b611c2e565b60405161012591906136bb565b61030b61030636600461371f565b611ca1565b60405161012591906137b8565b6101f3611d56565b610328612c95565b6000826040015190506000816001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610371573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261039991908101906137fb565b905060006103a682611ca1565b60408681015190516328ebbe8b60e21b81526001600160a01b039182166004820152919250879160009183169063a3aefa2c90602401600060405180830381865afa1580156103f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261042191908101906138ce565b90506000876040015190506000604051806101a001604052808a6000015181526020018a602001516001600160a01b031681526020018a604001516001600160a01b031681526020018a6060015181526020018a608001518152602001846000015181526020018460200151815260200184604001518152602001836001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104fe9190613982565b6001600160a01b03168152602001836001600160a01b031663e87554466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561054a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061056e919061399f565b8152602001836001600160a01b0316634ada90af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d5919061399f565b8152602001836001600160a01b031663db5c65de6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610618573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063c919061399f565b8152602001959095525092955050505050505b92915050565b6060816000816001600160401b0381111561067257610672612e17565b6040519080825280602002602001820160405280156106b757816020015b60408051808201909152600080825260208201528152602001906001900390816106905790505b50905060005b82811015610714576106ef8686838181106106da576106da6139b8565b905060200201602081019061024f919061333a565b828281518110610701576107016139b8565b60209081029190910101526001016106bd565b50949350505050565b606060008290506000816001600160a01b031663d88ff1f46040518163ffffffff1660e01b8152600401600060405180830381865afa158015610764573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261078c9190810190613a51565b80519091506000816001600160401b038111156107ab576107ab612e17565b6040519080825280602002602001820160405280156107e457816020015b6107d1612c95565b8152602001906001900390816107c95790505b50905060005b82811015610846576000848281518110610806576108066139b8565b60200260200101519050600061081c8983610320565b905080848481518110610831576108316139b8565b602090810291909101015250506001016107ea565b5095945050505050565b604080516060808201835260008083526020830152918101919091526000808390506000816001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156108b2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108da91908101906137fb565b90506000826001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561091c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109409190613982565b9050600082516001600160401b0381111561095d5761095d612e17565b6040519080825280602002602001820160405280156109a257816020015b604080518082019091526000808252602082015281526020019060019003908161097b5790505b5090506109d2604051806060016040528060006001600160a01b0316815260200160008152602001606081525090565b6001600160a01b03881681526040810182905260005b8451811015610bae576040805180820190915260008082526020820152858281518110610a1757610a176139b8565b602002602001015181600001906001600160a01b031690816001600160a01b031681525050670de0b6b3a7640000856001600160a01b031663fc57d4df888581518110610a6657610a666139b8565b60200260200101516040518263ffffffff1660e01b8152600401610a9991906001600160a01b0391909116815260200190565b602060405180830381865afa158015610ab6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ada919061399f565b878481518110610aec57610aec6139b8565b60200260200101516001600160a01b031663bbcac5576040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b55919061399f565b610b5f9190613b17565b610b699190613b2e565b60208201526040830151805182919084908110610b8857610b886139b8565b6020026020010181905250806020015188610ba39190613b50565b9750506001016109e8565b506020810195909552509295945050505050565b610bca612c95565b604051637aee632d60e01b81526001600160a01b0383811660048301528491610c4191839190821690637aee632d90602401600060405180830381865afa158015610c19573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526101139190810190613b63565b949350505050565b60405163266e0a7f60e01b81526001600160a01b0383811660048301528281166024830152600091859182169063266e0a7f90604401602060405180830381865afa158015610c9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc09190613982565b95945050505050565b60606000826001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610d0b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d3391908101906137fb565b90506000836001600160a01b03166361252fd16040518163ffffffff1660e01b8152600401600060405180830381865afa158015610d75573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d9d9190810190613b97565b9050600081516001600160401b03811115610dba57610dba612e17565b604051908082528060200260200182016040528015610e0b57816020015b6040805160808101825260008082526020808301829052928201526060808201528252600019909201910181610dd85790505b50905060005b8251811015610846576040805160808101825260008082526020820181905291810191909152606080820152838281518110610e4f57610e4f6139b8565b60209081029190910101516001600160a01b031681528351849083908110610e7957610e796139b8565b60200260200101516001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ebe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee29190613982565b6001600160a01b031660208201528351849083908110610f0457610f046139b8565b6020908102919091010151604051631627ee8960e01b81526001600160a01b038a8116600483015290911690631627ee8990602401602060405180830381865afa158015610f56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7a919061399f565b816040018181525050610fa78886868581518110610f9a57610f9a6139b8565b6020026020010151611d91565b816060018190525080838381518110610fc257610fc26139b8565b602090810291909101015250600101610e11565b6060826000816001600160401b03811115610ff357610ff3612e17565b60405190808252806020026020018201604052801561102c57816020015b611019612d18565b8152602001906001900390816110115790505b50905060005b828110156108465761106a87878381811061104f5761104f6139b8565b9050602002016020810190611064919061333a565b86611947565b82828151811061107c5761107c6139b8565b6020908102919091010152600101611032565b60408051808201909152600080825260208201526000826001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111079190613982565b90506000816001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611149573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116d9190613982565b6040805180820182526001600160a01b03808816808352925163fc57d4df60e01b815260048101939093529293509160208301919084169063fc57d4df90602401602060405180830381865afa1580156111cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ef919061399f565b9052949350505050565b611201612d57565b6000826001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611241573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611265919061399f565b90506000836001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cb9190613982565b604051638e8f294b60e01b81526001600160a01b03868116600483015291925082916000918291841690638e8f294b906024016040805180830381865afa15801561131a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133e9190613c35565b915091506000876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a69190613982565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061140c9190613c61565b60ff1690506000805b600860ff8216116114d2576000886001600160a01b031663e85a29608d8460ff16600881111561144757611447613c84565b6040518363ffffffff1660e01b8152600401611464929190613c9a565b602060405180830381865afa158015611481573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a59190613cd5565b6114b05760006114b3565b60015b60ff9081169083161b9290921791506114cb81613cf0565b9050611415565b506040518061022001604052808b6001600160a01b031681526020018981526020018b6001600160a01b031663ae9d70b06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611532573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611556919061399f565b81526020018b6001600160a01b031663f8f9da286040518163ffffffff1660e01b8152600401602060405180830381865afa158015611599573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115bd919061399f565b81526020018b6001600160a01b031663173b99046040518163ffffffff1660e01b8152600401602060405180830381865afa158015611600573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611624919061399f565b81526040516302c3bcbb60e01b81526001600160a01b038d811660048301526020909201918916906302c3bcbb90602401602060405180830381865afa158015611672573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611696919061399f565b815260405163252c221960e11b81526001600160a01b038d81166004830152602090920191891690634a58443290602401602060405180830381865afa1580156116e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611708919061399f565b81526020018b6001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561174b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176f919061399f565b81526020018b6001600160a01b0316638f840ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117d6919061399f565b81526020018b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611819573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061183d919061399f565b81526020018b6001600160a01b0316633b1d21a26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611880573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118a4919061399f565b81526020018615158152602001858152602001846001600160a01b031681526020018b6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611904573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119289190613c61565b60ff168152602081019390935260409092015298975050505050505050565b61194f612d18565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908516906370a0823190602401602060405180830381865afa158015611999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119bd919061399f565b6040516305eff7ef60e21b81526001600160a01b0385811660048301529192506000918616906317bfdfbc906024016020604051808303816000875af1158015611a0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a2f919061399f565b604051633af9e66960e01b81526001600160a01b038681166004830152919250600091871690633af9e669906024016020604051808303816000875af1158015611a7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa1919061399f565b90506000806000886001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0a9190613982565b6040516370a0823160e01b81526001600160a01b038a81166004830152919250908216906370a0823190602401602060405180830381865afa158015611b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b78919061399f565b604051636eb1769f60e11b81526001600160a01b038a811660048301528b811660248301529194509082169063dd62ed3e90604401602060405180830381865afa158015611bca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bee919061399f565b6040805160c0810182526001600160a01b038c168152602081019890985287019590955250506060840191909152608083015260a0820152905092915050565b604051631e6db74760e31b81526001600160a01b038281166004830152606091849182169063f36dba3890602401600060405180830381865afa158015611c79573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c419190810190613d0f565b80516060906000816001600160401b03811115611cc057611cc0612e17565b604051908082528060200260200182016040528015611cf957816020015b611ce6612d57565b815260200190600190039081611cde5790505b50905060005b82811015611d4e57611d29858281518110611d1c57611d1c6139b8565b60200260200101516111f9565b828281518110611d3b57611d3b6139b8565b6020908102919091010152600101611cff565b509392505050565b6000611d847f000000000000000000000000000000000000000000000000000000000000000063ffffffff16565b905090565b4390565b4290565b6060600083516001600160401b03811115611dae57611dae612e17565b604051908082528060200260200182016040528015611df357816020015b6040805180820190915260008082526020820152815260200190600190039081611dcc5790505b50905060005b845181101561071457611e2f604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b611e5c604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b7f000000000000000000000000000000000000000000000000000000000000000015611fdf57856001600160a01b0316638f693ec7888581518110611ea357611ea36139b8565b60200260200101516040518263ffffffff1660e01b8152600401611ed691906001600160a01b0391909116815260200190565b606060405180830381865afa158015611ef3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f179190613db4565b604085015260208401526001600160e01b0316825286516001600160a01b03871690638181494590899086908110611f5157611f516139b8565b60200260200101516040518263ffffffff1660e01b8152600401611f8491906001600160a01b0391909116815260200190565b606060405180830381865afa158015611fa1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fc59190613db4565b604084015260208301526001600160e01b0316815261214a565b856001600160a01b0316632c427b57888581518110612000576120006139b8565b60200260200101516040518263ffffffff1660e01b815260040161203391906001600160a01b0391909116815260200190565b606060405180830381865afa158015612050573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120749190613dfd565b63ffffffff90811660408601521660208401526001600160e01b0316825286516001600160a01b038716906392a18235908990869081106120b7576120b76139b8565b60200260200101516040518263ffffffff1660e01b81526004016120ea91906001600160a01b0391909116815260200190565b606060405180830381865afa158015612107573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061212b9190613dfd565b63ffffffff90811660408501521660208301526001600160e01b031681525b60006040518060200160405280898681518110612169576121696139b8565b60200260200101516001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121d2919061399f565b81525090506121fc8885815181106121ec576121ec6139b8565b60200260200101518885846122f1565b612220888581518110612211576122116139b8565b602002602001015188846124f2565b6000612248898681518110612237576122376139b8565b6020026020010151898c87866126e9565b905060006122718a8781518110612261576122616139b8565b60200260200101518a8d87612919565b60408051808201909152600080825260208201529091508a878151811061229a5761229a6139b8565b60209081029190910101516001600160a01b031681526122ba8284613b50565b6020820152875181908990899081106122d5576122d56139b8565b6020026020010181905250505050505050806001019050611df9565b604051637c05a7c560e01b81526001600160a01b03858116600483015260009190851690637c05a7c590602401602060405180830381865afa15801561233b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061235f919061399f565b9050600061236b611d56565b9050600084604001511180156123845750836040015181115b15612390575060408301515b60006123a0828660200151612b3d565b90506000811180156123b25750600083115b156124db576000612424886001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061241e919061399f565b86612b50565b905060006124328386612b6e565b90506000808311612452576040518060200160405280600081525061245c565b61245c8284612b7a565b9050600061248560405180602001604052808b600001516001600160e01b031681525083612bbf565b90506124c08160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612beb565b6001600160e01b0316895250505050602085018290526124e9565b80156124e957602085018290525b50505050505050565b604051631d31307360e21b81526001600160a01b038481166004830152600091908416906374c4c1cc90602401602060405180830381865afa15801561253c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612560919061399f565b9050600061256c611d56565b9050600083604001511180156125855750826040015181115b15612591575060408201515b60006125a1828560200151612b3d565b90506000811180156125b35750600083115b156126d3576000866001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156125f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061261c919061399f565b9050600061262a8386612b6e565b9050600080831161264a5760405180602001604052806000815250612654565b6126548284612b7a565b9050600061267d60405180602001604052808a600001516001600160e01b031681525083612bbf565b90506126b88160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612beb565b6001600160e01b0316885250505050602084018290526126e1565b80156126e157602084018290525b505050505050565b604080516020808201835284516001600160e01b031682528251908101928390526336fe846560e11b9092526001600160a01b0387811660248401528581166044840152600092839181908916636dfd08ca60648301602060405180830381865afa15801561275c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612780919061399f565b905280519091501580156128025750866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f19190613e40565b6001600160e01b0316826000015110155b1561287557866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612845573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128699190613e40565b6001600160e01b031681525b60006128818383612c27565b6040516395dd919360e01b81526001600160a01b0389811660048301529192506000916128fc91908c16906395dd919390602401602060405180830381865afa1580156128d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128f6919061399f565b87612b50565b9050600061290a8284612c53565b9b9a5050505050505050505050565b604080516020808201835283516001600160e01b0316825282519081019283905263552c097160e01b9092526001600160a01b038681166024840152848116604484015260009283918190881663552c097160648301602060405180830381865afa15801561298c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129b0919061399f565b90528051909150158015612a325750856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a219190613e40565b6001600160e01b0316826000015110155b15612aa557856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a999190613e40565b6001600160e01b031681525b6000612ab18383612c27565b6040516370a0823160e01b81526001600160a01b0388811660048301529192506000918a16906370a0823190602401602060405180830381865afa158015612afd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b21919061399f565b90506000612b2f8284612c53565b9a9950505050505050505050565b6000612b498284613e5b565b9392505050565b6000612b49612b6784670de0b6b3a7640000612b6e565b8351612c7d565b6000612b498284613b17565b6040805160208101909152600081526040518060200160405280612bb6612bb0866ec097ce7bc90715b34b9f1000000000612b6e565b85612c7d565b90529392505050565b6040805160208101909152600081526040518060200160405280612bb685600001518560000151612c89565b6000816001600160e01b03841115612c1f5760405162461bcd60e51b8152600401612c169190613e6e565b60405180910390fd5b509192915050565b6040805160208101909152600081526040518060200160405280612bb685600001518560000151612b3d565b60006ec097ce7bc90715b34b9f1000000000612c73848460000151612b6e565b612b499190613b2e565b6000612b498284613b2e565b6000612b498284613b50565b604051806101a001604052806060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160608152602001606081526020016060815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001606081525090565b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180610220016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b6001600160a01b0381168114612e0457600080fd5b50565b8035612e1281612def565b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715612e4f57612e4f612e17565b60405290565b604051606081016001600160401b0381118282101715612e4f57612e4f612e17565b604051601f8201601f191681016001600160401b0381118282101715612e9f57612e9f612e17565b604052919050565b60006001600160401b03821115612ec057612ec0612e17565b50601f01601f191660200190565b60008060408385031215612ee157600080fd5b8235612eec81612def565b91506020838101356001600160401b0380821115612f0957600080fd5b9085019060a08288031215612f1d57600080fd5b612f25612e2d565b823582811115612f3457600080fd5b83019150601f82018813612f4757600080fd5b8135612f5a612f5582612ea7565b612e77565b8181528986838601011115612f6e57600080fd5b818685018783013760008683830101528083525050612f8e848401612e07565b84820152612f9e60408401612e07565b60408201526060830135606082015260808301356080820152809450505050509250929050565b60005b83811015612fe0578181015183820152602001612fc8565b50506000910152565b60008151808452613001816020860160208601612fc5565b601f01601f19169290920160200192915050565b80516001600160a01b031682526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e0830152610100808201518184015250610120808201518184015250610140808201518184015250610160808201516130a08285018215159052565b505061018081810151908301526101a0808201516001600160a01b0316908301526101c080820151908301526101e0808201519083015261020090810151910152565b60008151808452602080850194506020840160005b8381101561311f5761310b878351613015565b6102209690960195908201906001016130f8565b509495945050505050565b60006101a0825181855261314082860182612fe9565b915050602083015161315d60208601826001600160a01b03169052565b50604083015161317860408601826001600160a01b03169052565b50606083015160608501526080830151608085015260a083015184820360a08601526131a48282612fe9565b91505060c083015184820360c08601526131be8282612fe9565b91505060e083015184820360e08601526131d88282612fe9565b915050610100808401516131f6828701826001600160a01b03169052565b5050610120838101519085015261014080840151908501526101608084015190850152610180808401518583038287015261323183826130e3565b9695505050505050565b602081526000612b49602083018461312a565b60008083601f84011261326057600080fd5b5081356001600160401b0381111561327757600080fd5b6020830191508360208260051b850101111561329257600080fd5b9250929050565b600080602083850312156132ac57600080fd5b82356001600160401b038111156132c257600080fd5b6132ce8582860161324e565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b8281101561332d5761331d84835180516001600160a01b03168252602090810151910152565b92840192908501906001016132f7565b5091979650505050505050565b60006020828403121561334c57600080fd5b8135612b4981612def565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156133ae57603f1988860301845261339c85835161312a565b94509285019290850190600101613380565b5092979650505050505050565b602080825282516001600160a01b03168282015282810151604080840191909152808401516060808501528051608085018190526000939291830191849160a08701905b808410156134395761342582865180516001600160a01b03168252602090810151910152565b9385019360019390930192908201906133ff565b50979650505050505050565b6000806040838503121561345857600080fd5b823561346381612def565b9150602083013561347381612def565b809150509250929050565b60008060006060848603121561349357600080fd5b833561349e81612def565b925060208401356134ae81612def565b915060408401356134be81612def565b809150509250925092565b600060208083018184528085518083526040925060408601915060408160051b8701018488016000805b8481101561359657898403603f19018652825180516001600160a01b03908116865289820151168986015287810151888601526060908101516080918601829052805191860182905289019060a086019084905b808210156135815761356d83855180516001600160a01b03168252602090810151910152565b928b0192918a019160019190910190613547565b505096890196945050918701916001016134f3565b50919998505050505050505050565b6000806000604084860312156135ba57600080fd5b83356001600160401b038111156135d057600080fd5b6135dc8682870161324e565b90945092505060208401356134be81612def565b80516001600160a01b031682526020808201519083015260408082015190830152606080820151908301526080808201519083015260a090810151910152565b6020808252825182820181905260009190848201906040850190845b818110156136725761365f8385516135f0565b9284019260c0929092019160010161364c565b50909695505050505050565b81516001600160a01b03168152602080830151908201526040810161064f565b610220810161064f8284613015565b60c0810161064f82846135f0565b6020808252825182820181905260009190848201906040850190845b818110156136725783516001600160a01b0316835292840192918401916001016136d7565b60006001600160401b0382111561371557613715612e17565b5060051b60200190565b6000602080838503121561373257600080fd5b82356001600160401b0381111561374857600080fd5b8301601f8101851361375957600080fd5b8035613767612f55826136fc565b81815260059190911b8201830190838101908783111561378657600080fd5b928401925b828410156137ad57833561379e81612def565b8252928401929084019061378b565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b81811015613672576137e7838551613015565b9284019261022092909201916001016137d4565b6000602080838503121561380e57600080fd5b82516001600160401b0381111561382457600080fd5b8301601f8101851361383557600080fd5b8051613843612f55826136fc565b81815260059190911b8201830190838101908783111561386257600080fd5b928401925b828410156137ad57835161387a81612def565b82529284019290840190613867565b600082601f83011261389a57600080fd5b81516138a8612f5582612ea7565b8181528460208386010111156138bd57600080fd5b610c41826020830160208701612fc5565b6000602082840312156138e057600080fd5b81516001600160401b03808211156138f757600080fd5b908301906060828603121561390b57600080fd5b613913612e55565b82518281111561392257600080fd5b61392e87828601613889565b82525060208301518281111561394357600080fd5b61394f87828601613889565b60208301525060408301518281111561396757600080fd5b61397387828601613889565b60408301525095945050505050565b60006020828403121561399457600080fd5b8151612b4981612def565b6000602082840312156139b157600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600060a082840312156139e057600080fd5b6139e8612e2d565b905081516001600160401b03811115613a0057600080fd5b613a0c84828501613889565b8252506020820151613a1d81612def565b60208201526040820151613a3081612def565b80604083015250606082015160608201526080820151608082015292915050565b60006020808385031215613a6457600080fd5b82516001600160401b0380821115613a7b57600080fd5b818501915085601f830112613a8f57600080fd5b8151613a9d612f55826136fc565b81815260059190911b83018401908481019088831115613abc57600080fd5b8585015b83811015613af457805185811115613ad85760008081fd5b613ae68b89838a01016139ce565b845250918601918601613ac0565b5098975050505050505050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761064f5761064f613b01565b600082613b4b57634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561064f5761064f613b01565b600060208284031215613b7557600080fd5b81516001600160401b03811115613b8b57600080fd5b610c41848285016139ce565b60006020808385031215613baa57600080fd5b82516001600160401b03811115613bc057600080fd5b8301601f81018513613bd157600080fd5b8051613bdf612f55826136fc565b81815260059190911b82018301908381019087831115613bfe57600080fd5b928401925b828410156137ad578351613c1681612def565b82529284019290840190613c03565b80518015158114612e1257600080fd5b60008060408385031215613c4857600080fd5b613c5183613c25565b9150602083015190509250929050565b600060208284031215613c7357600080fd5b815160ff81168114612b4957600080fd5b634e487b7160e01b600052602160045260246000fd5b6001600160a01b03831681526040810160098310613cc857634e487b7160e01b600052602160045260246000fd5b8260208301529392505050565b600060208284031215613ce757600080fd5b612b4982613c25565b600060ff821660ff8103613d0657613d06613b01565b60010192915050565b60006020808385031215613d2257600080fd5b82516001600160401b03811115613d3857600080fd5b8301601f81018513613d4957600080fd5b8051613d57612f55826136fc565b81815260059190911b82018301908381019087831115613d7657600080fd5b928401925b828410156137ad578351613d8e81612def565b82529284019290840190613d7b565b80516001600160e01b0381168114612e1257600080fd5b600080600060608486031215613dc957600080fd5b613dd284613d9d565b925060208401519150604084015190509250925092565b805163ffffffff81168114612e1257600080fd5b600080600060608486031215613e1257600080fd5b613e1b84613d9d565b9250613e2960208501613de9565b9150613e3760408501613de9565b90509250925092565b600060208284031215613e5257600080fd5b612b4982613d9d565b8181038181111561064f5761064f613b01565b602081526000612b496020830184612fe956fea2646970667358221220b9946cc7fdc900bd3735319cd04868b3796a2261574b7617c9cbf91cb2f997ca64736f6c63430008190033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101005760003560e01c80637c51b64211610097578063c7ad089511610066578063c7ad0895146102a1578063d77ebf96146102d8578063e0a67f11146102f8578063e1d146fb1461031857600080fd5b80637c51b642146102215780637c84e3b314610241578063aa5dbd2314610261578063b31242391461028157600080fd5b806347d86a81116100d357806347d86a811461018e57806355dd9515146101a15780636857249c146101cc5780637a27db571461020157600080fd5b80630d3ae318146101055780631f884fdf1461012e578063345954dc1461014e5780633e3e399c1461016e575b600080fd5b610118610113366004612ece565b610320565b604051610125919061323b565b60405180910390f35b61014161013c366004613299565b610655565b60405161012591906132da565b61016161015c36600461333a565b61071d565b6040516101259190613357565b61018161017c36600461333a565b610850565b60405161012591906133bb565b61011861019c366004613445565b610bc2565b6101b46101af36600461347e565b610c49565b6040516001600160a01b039091168152602001610125565b6101f37f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610125565b61021461020f366004613445565b610cc9565b60405161012591906134c9565b61023461022f3660046135a5565b610fd6565b6040516101259190613630565b61025461024f36600461333a565b61108f565b604051610125919061367e565b61027461026f36600461333a565b6111f9565b604051610125919061369e565b61029461028f366004613445565b611947565b60405161012591906136ad565b6102c87f000000000000000000000000000000000000000000000000000000000000000081565b6040519015158152602001610125565b6102eb6102e6366004613445565b611c2e565b60405161012591906136bb565b61030b61030636600461371f565b611ca1565b60405161012591906137b8565b6101f3611d56565b610328612c95565b6000826040015190506000816001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610371573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261039991908101906137fb565b905060006103a682611ca1565b60408681015190516328ebbe8b60e21b81526001600160a01b039182166004820152919250879160009183169063a3aefa2c90602401600060405180830381865afa1580156103f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261042191908101906138ce565b90506000876040015190506000604051806101a001604052808a6000015181526020018a602001516001600160a01b031681526020018a604001516001600160a01b031681526020018a6060015181526020018a608001518152602001846000015181526020018460200151815260200184604001518152602001836001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104fe9190613982565b6001600160a01b03168152602001836001600160a01b031663e87554466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561054a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061056e919061399f565b8152602001836001600160a01b0316634ada90af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d5919061399f565b8152602001836001600160a01b031663db5c65de6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610618573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063c919061399f565b8152602001959095525092955050505050505b92915050565b6060816000816001600160401b0381111561067257610672612e17565b6040519080825280602002602001820160405280156106b757816020015b60408051808201909152600080825260208201528152602001906001900390816106905790505b50905060005b82811015610714576106ef8686838181106106da576106da6139b8565b905060200201602081019061024f919061333a565b828281518110610701576107016139b8565b60209081029190910101526001016106bd565b50949350505050565b606060008290506000816001600160a01b031663d88ff1f46040518163ffffffff1660e01b8152600401600060405180830381865afa158015610764573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261078c9190810190613a51565b80519091506000816001600160401b038111156107ab576107ab612e17565b6040519080825280602002602001820160405280156107e457816020015b6107d1612c95565b8152602001906001900390816107c95790505b50905060005b82811015610846576000848281518110610806576108066139b8565b60200260200101519050600061081c8983610320565b905080848481518110610831576108316139b8565b602090810291909101015250506001016107ea565b5095945050505050565b604080516060808201835260008083526020830152918101919091526000808390506000816001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156108b2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108da91908101906137fb565b90506000826001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561091c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109409190613982565b9050600082516001600160401b0381111561095d5761095d612e17565b6040519080825280602002602001820160405280156109a257816020015b604080518082019091526000808252602082015281526020019060019003908161097b5790505b5090506109d2604051806060016040528060006001600160a01b0316815260200160008152602001606081525090565b6001600160a01b03881681526040810182905260005b8451811015610bae576040805180820190915260008082526020820152858281518110610a1757610a176139b8565b602002602001015181600001906001600160a01b031690816001600160a01b031681525050670de0b6b3a7640000856001600160a01b031663fc57d4df888581518110610a6657610a666139b8565b60200260200101516040518263ffffffff1660e01b8152600401610a9991906001600160a01b0391909116815260200190565b602060405180830381865afa158015610ab6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ada919061399f565b878481518110610aec57610aec6139b8565b60200260200101516001600160a01b031663bbcac5576040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b55919061399f565b610b5f9190613b17565b610b699190613b2e565b60208201526040830151805182919084908110610b8857610b886139b8565b6020026020010181905250806020015188610ba39190613b50565b9750506001016109e8565b506020810195909552509295945050505050565b610bca612c95565b604051637aee632d60e01b81526001600160a01b0383811660048301528491610c4191839190821690637aee632d90602401600060405180830381865afa158015610c19573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526101139190810190613b63565b949350505050565b60405163266e0a7f60e01b81526001600160a01b0383811660048301528281166024830152600091859182169063266e0a7f90604401602060405180830381865afa158015610c9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc09190613982565b95945050505050565b60606000826001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610d0b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d3391908101906137fb565b90506000836001600160a01b03166361252fd16040518163ffffffff1660e01b8152600401600060405180830381865afa158015610d75573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d9d9190810190613b97565b9050600081516001600160401b03811115610dba57610dba612e17565b604051908082528060200260200182016040528015610e0b57816020015b6040805160808101825260008082526020808301829052928201526060808201528252600019909201910181610dd85790505b50905060005b8251811015610846576040805160808101825260008082526020820181905291810191909152606080820152838281518110610e4f57610e4f6139b8565b60209081029190910101516001600160a01b031681528351849083908110610e7957610e796139b8565b60200260200101516001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ebe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee29190613982565b6001600160a01b031660208201528351849083908110610f0457610f046139b8565b6020908102919091010151604051631627ee8960e01b81526001600160a01b038a8116600483015290911690631627ee8990602401602060405180830381865afa158015610f56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7a919061399f565b816040018181525050610fa78886868581518110610f9a57610f9a6139b8565b6020026020010151611d91565b816060018190525080838381518110610fc257610fc26139b8565b602090810291909101015250600101610e11565b6060826000816001600160401b03811115610ff357610ff3612e17565b60405190808252806020026020018201604052801561102c57816020015b611019612d18565b8152602001906001900390816110115790505b50905060005b828110156108465761106a87878381811061104f5761104f6139b8565b9050602002016020810190611064919061333a565b86611947565b82828151811061107c5761107c6139b8565b6020908102919091010152600101611032565b60408051808201909152600080825260208201526000826001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111079190613982565b90506000816001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611149573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116d9190613982565b6040805180820182526001600160a01b03808816808352925163fc57d4df60e01b815260048101939093529293509160208301919084169063fc57d4df90602401602060405180830381865afa1580156111cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ef919061399f565b9052949350505050565b611201612d57565b6000826001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611241573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611265919061399f565b90506000836001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cb9190613982565b604051638e8f294b60e01b81526001600160a01b03868116600483015291925082916000918291841690638e8f294b906024016040805180830381865afa15801561131a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133e9190613c35565b915091506000876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a69190613982565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061140c9190613c61565b60ff1690506000805b600860ff8216116114d2576000886001600160a01b031663e85a29608d8460ff16600881111561144757611447613c84565b6040518363ffffffff1660e01b8152600401611464929190613c9a565b602060405180830381865afa158015611481573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a59190613cd5565b6114b05760006114b3565b60015b60ff9081169083161b9290921791506114cb81613cf0565b9050611415565b506040518061022001604052808b6001600160a01b031681526020018981526020018b6001600160a01b031663ae9d70b06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611532573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611556919061399f565b81526020018b6001600160a01b031663f8f9da286040518163ffffffff1660e01b8152600401602060405180830381865afa158015611599573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115bd919061399f565b81526020018b6001600160a01b031663173b99046040518163ffffffff1660e01b8152600401602060405180830381865afa158015611600573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611624919061399f565b81526040516302c3bcbb60e01b81526001600160a01b038d811660048301526020909201918916906302c3bcbb90602401602060405180830381865afa158015611672573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611696919061399f565b815260405163252c221960e11b81526001600160a01b038d81166004830152602090920191891690634a58443290602401602060405180830381865afa1580156116e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611708919061399f565b81526020018b6001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561174b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176f919061399f565b81526020018b6001600160a01b0316638f840ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117d6919061399f565b81526020018b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611819573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061183d919061399f565b81526020018b6001600160a01b0316633b1d21a26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611880573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118a4919061399f565b81526020018615158152602001858152602001846001600160a01b031681526020018b6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611904573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119289190613c61565b60ff168152602081019390935260409092015298975050505050505050565b61194f612d18565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908516906370a0823190602401602060405180830381865afa158015611999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119bd919061399f565b6040516305eff7ef60e21b81526001600160a01b0385811660048301529192506000918616906317bfdfbc906024016020604051808303816000875af1158015611a0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a2f919061399f565b604051633af9e66960e01b81526001600160a01b038681166004830152919250600091871690633af9e669906024016020604051808303816000875af1158015611a7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa1919061399f565b90506000806000886001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0a9190613982565b6040516370a0823160e01b81526001600160a01b038a81166004830152919250908216906370a0823190602401602060405180830381865afa158015611b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b78919061399f565b604051636eb1769f60e11b81526001600160a01b038a811660048301528b811660248301529194509082169063dd62ed3e90604401602060405180830381865afa158015611bca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bee919061399f565b6040805160c0810182526001600160a01b038c168152602081019890985287019590955250506060840191909152608083015260a0820152905092915050565b604051631e6db74760e31b81526001600160a01b038281166004830152606091849182169063f36dba3890602401600060405180830381865afa158015611c79573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c419190810190613d0f565b80516060906000816001600160401b03811115611cc057611cc0612e17565b604051908082528060200260200182016040528015611cf957816020015b611ce6612d57565b815260200190600190039081611cde5790505b50905060005b82811015611d4e57611d29858281518110611d1c57611d1c6139b8565b60200260200101516111f9565b828281518110611d3b57611d3b6139b8565b6020908102919091010152600101611cff565b509392505050565b6000611d847f000000000000000000000000000000000000000000000000000000000000000063ffffffff16565b905090565b4390565b4290565b6060600083516001600160401b03811115611dae57611dae612e17565b604051908082528060200260200182016040528015611df357816020015b6040805180820190915260008082526020820152815260200190600190039081611dcc5790505b50905060005b845181101561071457611e2f604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b611e5c604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b7f000000000000000000000000000000000000000000000000000000000000000015611fdf57856001600160a01b0316638f693ec7888581518110611ea357611ea36139b8565b60200260200101516040518263ffffffff1660e01b8152600401611ed691906001600160a01b0391909116815260200190565b606060405180830381865afa158015611ef3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f179190613db4565b604085015260208401526001600160e01b0316825286516001600160a01b03871690638181494590899086908110611f5157611f516139b8565b60200260200101516040518263ffffffff1660e01b8152600401611f8491906001600160a01b0391909116815260200190565b606060405180830381865afa158015611fa1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fc59190613db4565b604084015260208301526001600160e01b0316815261214a565b856001600160a01b0316632c427b57888581518110612000576120006139b8565b60200260200101516040518263ffffffff1660e01b815260040161203391906001600160a01b0391909116815260200190565b606060405180830381865afa158015612050573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120749190613dfd565b63ffffffff90811660408601521660208401526001600160e01b0316825286516001600160a01b038716906392a18235908990869081106120b7576120b76139b8565b60200260200101516040518263ffffffff1660e01b81526004016120ea91906001600160a01b0391909116815260200190565b606060405180830381865afa158015612107573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061212b9190613dfd565b63ffffffff90811660408501521660208301526001600160e01b031681525b60006040518060200160405280898681518110612169576121696139b8565b60200260200101516001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121d2919061399f565b81525090506121fc8885815181106121ec576121ec6139b8565b60200260200101518885846122f1565b612220888581518110612211576122116139b8565b602002602001015188846124f2565b6000612248898681518110612237576122376139b8565b6020026020010151898c87866126e9565b905060006122718a8781518110612261576122616139b8565b60200260200101518a8d87612919565b60408051808201909152600080825260208201529091508a878151811061229a5761229a6139b8565b60209081029190910101516001600160a01b031681526122ba8284613b50565b6020820152875181908990899081106122d5576122d56139b8565b6020026020010181905250505050505050806001019050611df9565b604051637c05a7c560e01b81526001600160a01b03858116600483015260009190851690637c05a7c590602401602060405180830381865afa15801561233b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061235f919061399f565b9050600061236b611d56565b9050600084604001511180156123845750836040015181115b15612390575060408301515b60006123a0828660200151612b3d565b90506000811180156123b25750600083115b156124db576000612424886001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061241e919061399f565b86612b50565b905060006124328386612b6e565b90506000808311612452576040518060200160405280600081525061245c565b61245c8284612b7a565b9050600061248560405180602001604052808b600001516001600160e01b031681525083612bbf565b90506124c08160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612beb565b6001600160e01b0316895250505050602085018290526124e9565b80156124e957602085018290525b50505050505050565b604051631d31307360e21b81526001600160a01b038481166004830152600091908416906374c4c1cc90602401602060405180830381865afa15801561253c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612560919061399f565b9050600061256c611d56565b9050600083604001511180156125855750826040015181115b15612591575060408201515b60006125a1828560200151612b3d565b90506000811180156125b35750600083115b156126d3576000866001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156125f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061261c919061399f565b9050600061262a8386612b6e565b9050600080831161264a5760405180602001604052806000815250612654565b6126548284612b7a565b9050600061267d60405180602001604052808a600001516001600160e01b031681525083612bbf565b90506126b88160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612beb565b6001600160e01b0316885250505050602084018290526126e1565b80156126e157602084018290525b505050505050565b604080516020808201835284516001600160e01b031682528251908101928390526336fe846560e11b9092526001600160a01b0387811660248401528581166044840152600092839181908916636dfd08ca60648301602060405180830381865afa15801561275c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612780919061399f565b905280519091501580156128025750866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f19190613e40565b6001600160e01b0316826000015110155b1561287557866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612845573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128699190613e40565b6001600160e01b031681525b60006128818383612c27565b6040516395dd919360e01b81526001600160a01b0389811660048301529192506000916128fc91908c16906395dd919390602401602060405180830381865afa1580156128d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128f6919061399f565b87612b50565b9050600061290a8284612c53565b9b9a5050505050505050505050565b604080516020808201835283516001600160e01b0316825282519081019283905263552c097160e01b9092526001600160a01b038681166024840152848116604484015260009283918190881663552c097160648301602060405180830381865afa15801561298c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129b0919061399f565b90528051909150158015612a325750856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a219190613e40565b6001600160e01b0316826000015110155b15612aa557856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a999190613e40565b6001600160e01b031681525b6000612ab18383612c27565b6040516370a0823160e01b81526001600160a01b0388811660048301529192506000918a16906370a0823190602401602060405180830381865afa158015612afd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b21919061399f565b90506000612b2f8284612c53565b9a9950505050505050505050565b6000612b498284613e5b565b9392505050565b6000612b49612b6784670de0b6b3a7640000612b6e565b8351612c7d565b6000612b498284613b17565b6040805160208101909152600081526040518060200160405280612bb6612bb0866ec097ce7bc90715b34b9f1000000000612b6e565b85612c7d565b90529392505050565b6040805160208101909152600081526040518060200160405280612bb685600001518560000151612c89565b6000816001600160e01b03841115612c1f5760405162461bcd60e51b8152600401612c169190613e6e565b60405180910390fd5b509192915050565b6040805160208101909152600081526040518060200160405280612bb685600001518560000151612b3d565b60006ec097ce7bc90715b34b9f1000000000612c73848460000151612b6e565b612b499190613b2e565b6000612b498284613b2e565b6000612b498284613b50565b604051806101a001604052806060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160608152602001606081526020016060815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001606081525090565b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180610220016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b6001600160a01b0381168114612e0457600080fd5b50565b8035612e1281612def565b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715612e4f57612e4f612e17565b60405290565b604051606081016001600160401b0381118282101715612e4f57612e4f612e17565b604051601f8201601f191681016001600160401b0381118282101715612e9f57612e9f612e17565b604052919050565b60006001600160401b03821115612ec057612ec0612e17565b50601f01601f191660200190565b60008060408385031215612ee157600080fd5b8235612eec81612def565b91506020838101356001600160401b0380821115612f0957600080fd5b9085019060a08288031215612f1d57600080fd5b612f25612e2d565b823582811115612f3457600080fd5b83019150601f82018813612f4757600080fd5b8135612f5a612f5582612ea7565b612e77565b8181528986838601011115612f6e57600080fd5b818685018783013760008683830101528083525050612f8e848401612e07565b84820152612f9e60408401612e07565b60408201526060830135606082015260808301356080820152809450505050509250929050565b60005b83811015612fe0578181015183820152602001612fc8565b50506000910152565b60008151808452613001816020860160208601612fc5565b601f01601f19169290920160200192915050565b80516001600160a01b031682526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e0830152610100808201518184015250610120808201518184015250610140808201518184015250610160808201516130a08285018215159052565b505061018081810151908301526101a0808201516001600160a01b0316908301526101c080820151908301526101e0808201519083015261020090810151910152565b60008151808452602080850194506020840160005b8381101561311f5761310b878351613015565b6102209690960195908201906001016130f8565b509495945050505050565b60006101a0825181855261314082860182612fe9565b915050602083015161315d60208601826001600160a01b03169052565b50604083015161317860408601826001600160a01b03169052565b50606083015160608501526080830151608085015260a083015184820360a08601526131a48282612fe9565b91505060c083015184820360c08601526131be8282612fe9565b91505060e083015184820360e08601526131d88282612fe9565b915050610100808401516131f6828701826001600160a01b03169052565b5050610120838101519085015261014080840151908501526101608084015190850152610180808401518583038287015261323183826130e3565b9695505050505050565b602081526000612b49602083018461312a565b60008083601f84011261326057600080fd5b5081356001600160401b0381111561327757600080fd5b6020830191508360208260051b850101111561329257600080fd5b9250929050565b600080602083850312156132ac57600080fd5b82356001600160401b038111156132c257600080fd5b6132ce8582860161324e565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b8281101561332d5761331d84835180516001600160a01b03168252602090810151910152565b92840192908501906001016132f7565b5091979650505050505050565b60006020828403121561334c57600080fd5b8135612b4981612def565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156133ae57603f1988860301845261339c85835161312a565b94509285019290850190600101613380565b5092979650505050505050565b602080825282516001600160a01b03168282015282810151604080840191909152808401516060808501528051608085018190526000939291830191849160a08701905b808410156134395761342582865180516001600160a01b03168252602090810151910152565b9385019360019390930192908201906133ff565b50979650505050505050565b6000806040838503121561345857600080fd5b823561346381612def565b9150602083013561347381612def565b809150509250929050565b60008060006060848603121561349357600080fd5b833561349e81612def565b925060208401356134ae81612def565b915060408401356134be81612def565b809150509250925092565b600060208083018184528085518083526040925060408601915060408160051b8701018488016000805b8481101561359657898403603f19018652825180516001600160a01b03908116865289820151168986015287810151888601526060908101516080918601829052805191860182905289019060a086019084905b808210156135815761356d83855180516001600160a01b03168252602090810151910152565b928b0192918a019160019190910190613547565b505096890196945050918701916001016134f3565b50919998505050505050505050565b6000806000604084860312156135ba57600080fd5b83356001600160401b038111156135d057600080fd5b6135dc8682870161324e565b90945092505060208401356134be81612def565b80516001600160a01b031682526020808201519083015260408082015190830152606080820151908301526080808201519083015260a090810151910152565b6020808252825182820181905260009190848201906040850190845b818110156136725761365f8385516135f0565b9284019260c0929092019160010161364c565b50909695505050505050565b81516001600160a01b03168152602080830151908201526040810161064f565b610220810161064f8284613015565b60c0810161064f82846135f0565b6020808252825182820181905260009190848201906040850190845b818110156136725783516001600160a01b0316835292840192918401916001016136d7565b60006001600160401b0382111561371557613715612e17565b5060051b60200190565b6000602080838503121561373257600080fd5b82356001600160401b0381111561374857600080fd5b8301601f8101851361375957600080fd5b8035613767612f55826136fc565b81815260059190911b8201830190838101908783111561378657600080fd5b928401925b828410156137ad57833561379e81612def565b8252928401929084019061378b565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b81811015613672576137e7838551613015565b9284019261022092909201916001016137d4565b6000602080838503121561380e57600080fd5b82516001600160401b0381111561382457600080fd5b8301601f8101851361383557600080fd5b8051613843612f55826136fc565b81815260059190911b8201830190838101908783111561386257600080fd5b928401925b828410156137ad57835161387a81612def565b82529284019290840190613867565b600082601f83011261389a57600080fd5b81516138a8612f5582612ea7565b8181528460208386010111156138bd57600080fd5b610c41826020830160208701612fc5565b6000602082840312156138e057600080fd5b81516001600160401b03808211156138f757600080fd5b908301906060828603121561390b57600080fd5b613913612e55565b82518281111561392257600080fd5b61392e87828601613889565b82525060208301518281111561394357600080fd5b61394f87828601613889565b60208301525060408301518281111561396757600080fd5b61397387828601613889565b60408301525095945050505050565b60006020828403121561399457600080fd5b8151612b4981612def565b6000602082840312156139b157600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600060a082840312156139e057600080fd5b6139e8612e2d565b905081516001600160401b03811115613a0057600080fd5b613a0c84828501613889565b8252506020820151613a1d81612def565b60208201526040820151613a3081612def565b80604083015250606082015160608201526080820151608082015292915050565b60006020808385031215613a6457600080fd5b82516001600160401b0380821115613a7b57600080fd5b818501915085601f830112613a8f57600080fd5b8151613a9d612f55826136fc565b81815260059190911b83018401908481019088831115613abc57600080fd5b8585015b83811015613af457805185811115613ad85760008081fd5b613ae68b89838a01016139ce565b845250918601918601613ac0565b5098975050505050505050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761064f5761064f613b01565b600082613b4b57634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561064f5761064f613b01565b600060208284031215613b7557600080fd5b81516001600160401b03811115613b8b57600080fd5b610c41848285016139ce565b60006020808385031215613baa57600080fd5b82516001600160401b03811115613bc057600080fd5b8301601f81018513613bd157600080fd5b8051613bdf612f55826136fc565b81815260059190911b82018301908381019087831115613bfe57600080fd5b928401925b828410156137ad578351613c1681612def565b82529284019290840190613c03565b80518015158114612e1257600080fd5b60008060408385031215613c4857600080fd5b613c5183613c25565b9150602083015190509250929050565b600060208284031215613c7357600080fd5b815160ff81168114612b4957600080fd5b634e487b7160e01b600052602160045260246000fd5b6001600160a01b03831681526040810160098310613cc857634e487b7160e01b600052602160045260246000fd5b8260208301529392505050565b600060208284031215613ce757600080fd5b612b4982613c25565b600060ff821660ff8103613d0657613d06613b01565b60010192915050565b60006020808385031215613d2257600080fd5b82516001600160401b03811115613d3857600080fd5b8301601f81018513613d4957600080fd5b8051613d57612f55826136fc565b81815260059190911b82018301908381019087831115613d7657600080fd5b928401925b828410156137ad578351613d8e81612def565b82529284019290840190613d7b565b80516001600160e01b0381168114612e1257600080fd5b600080600060608486031215613dc957600080fd5b613dd284613d9d565b925060208401519150604084015190509250925092565b805163ffffffff81168114612e1257600080fd5b600080600060608486031215613e1257600080fd5b613e1b84613d9d565b9250613e2960208501613de9565b9150613e3760408501613de9565b90509250925092565b600060208284031215613e5257600080fd5b612b4982613d9d565b8181038181111561064f5761064f613b01565b602081526000612b496020830184612fe956fea2646970667358221220b9946cc7fdc900bd3735319cd04868b3796a2261574b7617c9cbf91cb2f997ca64736f6c63430008190033", + "args": [true, 0, "0x0C7973F9598AA62f9e03B94E92C967fD5437426C"], + "numDeployments": 2, + "solcInputHash": "09f8b2889a382752688c03578bc27f8d", + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"timeBased_\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"blocksPerYear_\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"corePoolComptroller_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidBlocksPerYear\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTimeBasedConfiguration\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"blocksOrSecondsPerYear\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"corePoolComptroller\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"}],\"name\":\"getAllPools\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockNumberOrTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getPendingRewards\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"distributorAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"rewardTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalRewards\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.PendingReward[]\",\"name\":\"pendingRewards\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.RewardSummary[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getPoolBadDebt\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalBadDebtUsd\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"badDebtUsd\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.BadDebt[]\",\"name\":\"badDebts\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.BadDebtSummary\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolByComptroller\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolRegistryInterface.VenusPool\",\"name\":\"venusPool\",\"type\":\"tuple\"}],\"name\":\"getPoolDataFromVenusPool\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getPoolsSupportedByAsset\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getVTokenForAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isTimeBased\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"vTokenBalances\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalanceCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balanceOfUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenAllowance\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenBalances\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"vTokenBalancesAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalanceCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balanceOfUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenAllowance\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenBalances[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"vTokenMetadata\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"vTokenMetadataAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"vTokenUnderlyingPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"underlyingPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenUnderlyingPrice\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"vTokenUnderlyingPriceAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"underlyingPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenUnderlyingPrice[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"params\":{\"blocksPerYear_\":\"The number of blocks per year\",\"corePoolComptroller_\":\"The address of the core pool comptroller\",\"timeBased_\":\"A boolean indicating whether the contract is based on time or block.\"}},\"getAllPools(address)\":{\"details\":\"This function is not designed to be called in a transaction: it is too gas-intensive\",\"params\":{\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"Arrays of all Venus pools' data\"}},\"getBlockNumberOrTimestamp()\":{\"details\":\"Function to simply retrieve block number or block timestamp\",\"returns\":{\"_0\":\"Current block number or block timestamp\"}},\"getPendingRewards(address,address)\":{\"params\":{\"account\":\"The user account.\",\"comptrollerAddress\":\"address\"},\"returns\":{\"_0\":\"Pending rewards array\"}},\"getPoolBadDebt(address)\":{\"params\":{\"comptrollerAddress\":\"Address of the comptroller\"},\"returns\":{\"_0\":\"badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and a break down of bad debt by market\"}},\"getPoolByComptroller(address,address)\":{\"params\":{\"comptroller\":\"The Comptroller implementation address\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"PoolData structure containing the details of the pool\"}},\"getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))\":{\"params\":{\"poolRegistryAddress\":\"Address of the PoolRegistry\",\"venusPool\":\"The VenusPool Object from PoolRegistry\"},\"returns\":{\"_0\":\"Enriched PoolData\"}},\"getPoolsSupportedByAsset(address,address)\":{\"params\":{\"asset\":\"The underlying asset of vToken\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"A list of Comptroller contracts\"}},\"getVTokenForAsset(address,address,address)\":{\"params\":{\"asset\":\"The underlyingAsset of VToken\",\"comptroller\":\"The pool comptroller\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"Address of the vToken\"}},\"vTokenBalances(address,address)\":{\"params\":{\"account\":\"The user Account\",\"vToken\":\"vToken address\"},\"returns\":{\"_0\":\"A struct containing the balances data\"}},\"vTokenBalancesAll(address[],address)\":{\"params\":{\"account\":\"The user Account\",\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"A list of structs containing balances data\"}},\"vTokenMetadata(address)\":{\"params\":{\"vToken\":\"The address of vToken\"},\"returns\":{\"_0\":\"VTokenMetadata struct\"}},\"vTokenMetadataAll(address[])\":{\"params\":{\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"An array of VTokenMetadata structs\"}},\"vTokenUnderlyingPrice(address)\":{\"params\":{\"vToken\":\"vToken address\"},\"returns\":{\"_0\":\"The price data for each asset\"}},\"vTokenUnderlyingPriceAll(address[])\":{\"params\":{\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"An array containing the price data for each asset\"}}},\"title\":\"PoolLens\",\"version\":1},\"userdoc\":{\"errors\":{\"InvalidBlocksPerYear()\":[{\"notice\":\"Thrown when blocks per year is invalid\"}],\"InvalidTimeBasedConfiguration()\":[{\"notice\":\"Thrown when time based but blocks per year is provided\"}]},\"kind\":\"user\",\"methods\":{\"blocksOrSecondsPerYear()\":{\"notice\":\"Stores blocksPerYear if isTimeBased is true else secondsPerYear is stored\"},\"corePoolComptroller()\":{\"notice\":\"Address of the core pool comptroller (all markets are returned for this pool, including paused ones)\"},\"getAllPools(address)\":{\"notice\":\"Queries all pools with addtional details for each of them\"},\"getPendingRewards(address,address)\":{\"notice\":\"Returns the pending rewards for a user for a given pool.\"},\"getPoolBadDebt(address)\":{\"notice\":\"Returns a summary of a pool's bad debt broken down by market\"},\"getPoolByComptroller(address,address)\":{\"notice\":\"Queries the details of a pool identified by Comptroller address\"},\"getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))\":{\"notice\":\"Queries additional information for the pool\"},\"getPoolsSupportedByAsset(address,address)\":{\"notice\":\"Returns all pools that support the specified underlying asset\"},\"getVTokenForAsset(address,address,address)\":{\"notice\":\"Returns vToken holding the specified underlying asset in the specified pool\"},\"isTimeBased()\":{\"notice\":\"Acknowledges if a contract is time based or not\"},\"vTokenBalances(address,address)\":{\"notice\":\"Queries the user's supply/borrow balances in the specified vToken\"},\"vTokenBalancesAll(address[],address)\":{\"notice\":\"Queries the user's supply/borrow balances in vTokens\"},\"vTokenMetadata(address)\":{\"notice\":\"Returns the metadata of VToken\"},\"vTokenMetadataAll(address[])\":{\"notice\":\"Returns the metadata of all VTokens\"},\"vTokenUnderlyingPrice(address)\":{\"notice\":\"Returns the price data for the underlying asset of the specified vToken\"},\"vTokenUnderlyingPriceAll(address[])\":{\"notice\":\"Returns the price data for the underlying assets of the specified vTokens\"}},\"notice\":\"The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be looked up for specific pools and markets: - the vToken balance of a given user; - the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address; - the vToken address in a pool for a given asset; - a list of all pools that support an asset; - the underlying asset price of a vToken; - the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Lens/PoolLens.sol\":\"PoolLens\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"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\",\"keccak256\":\"0x9140dabc466abab21b48b72dbda26736b1183a310d0e677d3719d201df026510\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x359a1ab89b46b9aba7bcad3fb651924baf4893d15153049b9976b0fc9be1358e\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x07e881de3b9f6d2c07909f193f24b96c7fe4ea60013260f3f25aecd8bab3c2f8\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x75097e35253e7fb282ee4d7f27a80eaacfa759923185bf17302a89cbc059c5ef\",\"license\":\"MIT\"},\"@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\"},\"@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\",\"keccak256\":\"0xfe0fd441c84ac907cabc88db69ef04f6d7532d770c7e6a1dfe6e7d6305debb49\",\"license\":\"BSD-3-Clause\"},\"@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 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/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface IProtocolShareReserve {\\n /// @notice it represents the type of vToken income\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(\\n address comptroller,\\n address asset,\\n IncomeType incomeType\\n ) external;\\n}\\n\",\"keccak256\":\"0x0f341bbef8f12885d79b7acaad7aaf11b84809e8f6b059ef4efc011c8f6c39a5\",\"license\":\"BSD-3-Clause\"},\"@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\",\"keccak256\":\"0x57a2bbb9b8e02b1c0a5c0e305fef1328a22db56c3d4b148c362010a6e767243c\",\"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\"},\"@venusprotocol/venus-protocol/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\",\"keccak256\":\"0xd112f60183416ad796093b4a83a80ddc1b8b655965f02ae55ca82e2a0c68f97d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/venus-protocol/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\",\"keccak256\":\"0x5285c875114db2ea2be0b81b65722d5761806217022db733323c4e03365a95e7\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IPrime } from \\\"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\\\";\\n\\nimport { ComptrollerInterface, Action } from \\\"./ComptrollerInterface.sol\\\";\\nimport { ComptrollerStorage } from \\\"./ComptrollerStorage.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"./MaxLoopsLimitHelper.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title Comptroller\\n * @author Venus\\n * @notice The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating,\\n * and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts\\n * with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows\\n * or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing\\n * liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow,\\n * as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the\\n * markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market\\u2019s corresponding liquidation threshold,\\n * the borrow is eligible for liquidation.\\n *\\n * The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed\\n * the `minLiquidatableCollateral` for the `Comptroller`:\\n *\\n * - `healAccount()`: This function is called to seize all of a given user\\u2019s collateral, requiring the `msg.sender` repay a certain percentage\\n * of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed\\n * 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt\\n * and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool.\\n * - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation\\n * incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic\\n * verifying that the repay amount does not exceed the close factor.\\n */\\ncontract Comptroller is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n ComptrollerStorage,\\n ComptrollerInterface,\\n ExponentialNoError,\\n MaxLoopsLimitHelper\\n{\\n // PoolRegistry, immutable to save on gas\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable poolRegistry;\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(VToken indexed vToken, address indexed account);\\n\\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(VToken vToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa);\\n\\n /// @notice Emitted when liquidation threshold is changed by admin\\n event NewLiquidationThreshold(\\n VToken vToken,\\n uint256 oldLiquidationThresholdMantissa,\\n uint256 newLiquidationThresholdMantissa\\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 an action is paused on a market\\n event ActionPausedMarket(VToken vToken, Action action, bool pauseState);\\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 the collateral threshold (in USD) for non-batch liquidations is changed\\n event NewMinLiquidatableCollateral(uint256 oldMinLiquidatableCollateral, uint256 newMinLiquidatableCollateral);\\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 a rewards distributor is added\\n event NewRewardsDistributor(address indexed rewardsDistributor, address indexed rewardToken);\\n\\n /// @notice Emitted when a market is supported\\n event MarketSupported(VToken vToken);\\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 a market\\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\\n\\n /// @notice Emitted when a market is unlisted\\n event MarketUnlisted(address indexed vToken);\\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 Thrown when collateral factor exceeds the upper bound\\n error InvalidCollateralFactor();\\n\\n /// @notice Thrown when liquidation threshold exceeds the collateral factor\\n error InvalidLiquidationThreshold();\\n\\n /// @notice Thrown when the action is only available to specific sender, but the real sender was different\\n error UnexpectedSender(address expectedSender, address actualSender);\\n\\n /// @notice Thrown when the oracle returns an invalid price for some asset\\n error PriceError(address vToken);\\n\\n /// @notice Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\\n error SnapshotError(address vToken, address user);\\n\\n /// @notice Thrown when the market is not listed\\n error MarketNotListed(address market);\\n\\n /// @notice Thrown when a market has an unexpected comptroller\\n error ComptrollerMismatch();\\n\\n /// @notice Thrown when user is not member of market\\n error MarketNotCollateral(address vToken, address user);\\n\\n /// @notice Thrown when borrow action is not paused\\n error BorrowActionNotPaused();\\n\\n /// @notice Thrown when mint action is not paused\\n error MintActionNotPaused();\\n\\n /// @notice Thrown when redeem action is not paused\\n error RedeemActionNotPaused();\\n\\n /// @notice Thrown when repay action is not paused\\n error RepayActionNotPaused();\\n\\n /// @notice Thrown when seize action is not paused\\n error SeizeActionNotPaused();\\n\\n /// @notice Thrown when exit market action is not paused\\n error ExitMarketActionNotPaused();\\n\\n /// @notice Thrown when transfer action is not paused\\n error TransferActionNotPaused();\\n\\n /// @notice Thrown when enter market action is not paused\\n error EnterMarketActionNotPaused();\\n\\n /// @notice Thrown when liquidate action is not paused\\n error LiquidateActionNotPaused();\\n\\n /// @notice Thrown when borrow cap is not zero\\n error BorrowCapIsNotZero();\\n\\n /// @notice Thrown when supply cap is not zero\\n error SupplyCapIsNotZero();\\n\\n /// @notice Thrown when collateral factor is not zero\\n error CollateralFactorIsNotZero();\\n\\n /**\\n * @notice Thrown during the liquidation if user's total collateral amount is lower than\\n * a predefined threshold. In this case only batch liquidations (either liquidateAccount\\n * or healAccount) are available.\\n */\\n error MinimalCollateralViolated(uint256 expectedGreaterThan, uint256 actual);\\n error CollateralExceedsThreshold(uint256 expectedLessThanOrEqualTo, uint256 actual);\\n error InsufficientCollateral(uint256 collateralToSeize, uint256 availableCollateral);\\n\\n /// @notice Thrown when the account doesn't have enough liquidity to redeem or borrow\\n error InsufficientLiquidity();\\n\\n /// @notice Thrown when trying to liquidate a healthy account\\n error InsufficientShortfall();\\n\\n /// @notice Thrown when trying to repay more than allowed by close factor\\n error TooMuchRepay();\\n\\n /// @notice Thrown if the user is trying to exit a market in which they have an outstanding debt\\n error NonzeroBorrowBalance();\\n\\n /// @notice Thrown when trying to perform an action that is paused\\n error ActionPaused(address market, Action action);\\n\\n /// @notice Thrown when trying to add a market that is already listed\\n error MarketAlreadyListed(address market);\\n\\n /// @notice Thrown if the supply cap is exceeded\\n error SupplyCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if the borrow cap is exceeded\\n error BorrowCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if delegate approval status is already set to the requested value\\n error DelegationStatusUnchanged();\\n\\n /// @param poolRegistry_ Pool registry address\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n constructor(address poolRegistry_) {\\n ensureNonzeroAddress(poolRegistry_);\\n\\n poolRegistry = poolRegistry_;\\n _disableInitializers();\\n }\\n\\n /**\\n * @param loopLimit Limit for the loops can iterate to avoid the DOS\\n * @param accessControlManager Access control manager contract address\\n */\\n function initialize(uint256 loopLimit, address accessControlManager) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager);\\n\\n _setMaxLoopsLimit(loopLimit);\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation; enabling them to be used as collateral\\n * @param vTokens The list of addresses of the vToken markets to be enabled\\n * @return errors An array of NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketEntered is emitted for each market on success\\n * @custom:error ActionPaused error is thrown if entering any of the markets is paused\\n * @custom:error MarketNotListed error is thrown if any of the markets is not listed\\n * @custom:access Not restricted\\n */\\n function enterMarkets(address[] memory vTokens) external override returns (uint256[] memory) {\\n uint256 len = vTokens.length;\\n\\n uint256[] memory results = new uint256[](len);\\n for (uint256 i; i < len; ++i) {\\n VToken vToken = VToken(vTokens[i]);\\n\\n _addToMarket(vToken, msg.sender);\\n results[i] = NO_ERROR;\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Unlist a market by setting isListed to false\\n * @dev Checks if all actions are paused, borrow/supply caps is set to 0 and collateral factor is to 0.\\n * @param market The address of the market (token) to unlist\\n * @return uint256 Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketUnlisted is emitted on success\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error BorrowActionNotPaused error is thrown if borrow action is not paused\\n * @custom:error MintActionNotPaused error is thrown if mint action is not paused\\n * @custom:error RedeemActionNotPaused error is thrown if redeem action is not paused\\n * @custom:error RepayActionNotPaused error is thrown if repay action is not paused\\n * @custom:error EnterMarketActionNotPaused error is thrown if enter market action is not paused\\n * @custom:error LiquidateActionNotPaused error is thrown if liquidate action is not paused\\n * @custom:error BorrowCapIsNotZero error is thrown if borrow cap is not zero\\n * @custom:error SupplyCapIsNotZero error is thrown if supply cap is not zero\\n * @custom:error CollateralFactorIsNotZero error is thrown if collateral factor is not zero\\n */\\n function unlistMarket(address market) external returns (uint256) {\\n _checkAccessAllowed(\\\"unlistMarket(address)\\\");\\n\\n Market storage _market = markets[market];\\n\\n if (!_market.isListed) {\\n revert MarketNotListed(market);\\n }\\n\\n if (!actionPaused(market, Action.BORROW)) {\\n revert BorrowActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.MINT)) {\\n revert MintActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.REDEEM)) {\\n revert RedeemActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.REPAY)) {\\n revert RepayActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.SEIZE)) {\\n revert SeizeActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.ENTER_MARKET)) {\\n revert EnterMarketActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.LIQUIDATE)) {\\n revert LiquidateActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.TRANSFER)) {\\n revert TransferActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.EXIT_MARKET)) {\\n revert ExitMarketActionNotPaused();\\n }\\n\\n if (borrowCaps[market] != 0) {\\n revert BorrowCapIsNotZero();\\n }\\n\\n if (supplyCaps[market] != 0) {\\n revert SupplyCapIsNotZero();\\n }\\n\\n if (_market.collateralFactorMantissa != 0) {\\n revert CollateralFactorIsNotZero();\\n }\\n\\n _market.isListed = false;\\n emit MarketUnlisted(market);\\n\\n return NO_ERROR;\\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 * @custom:event DelegateUpdated emits on success\\n * @custom:error ZeroAddressNotAllowed is thrown when delegate address is zero\\n * @custom:error DelegationStatusUnchanged is thrown if approval status is already set to the requested value\\n * @custom:access Not restricted\\n */\\n function updateDelegate(address delegate, bool approved) external {\\n ensureNonzeroAddress(delegate);\\n if (approvedDelegates[msg.sender][delegate] == approved) {\\n revert DelegationStatusUnchanged();\\n }\\n\\n approvedDelegates[msg.sender][delegate] = approved;\\n emit DelegateUpdated(msg.sender, delegate, approved);\\n }\\n\\n /**\\n * @notice Removes asset from sender's account liquidity calculation; disabling them as collateral\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketExited is emitted on success\\n * @custom:error ActionPaused error is thrown if exiting the market is paused\\n * @custom:error NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function exitMarket(address vTokenAddress) external override returns (uint256) {\\n _checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\\n VToken vToken = VToken(vTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\\n (uint256 tokensHeld, uint256 amountOwed, ) = _safeGetAccountSnapshot(vToken, msg.sender);\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n revert NonzeroBorrowBalance();\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n _checkRedeemAllowed(vTokenAddress, msg.sender, tokensHeld);\\n\\n Market storage marketToExit = markets[address(vToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return 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 // load into memory for faster iteration\\n VToken[] memory userAssetList = accountAssets[msg.sender];\\n uint256 len = userAssetList.length;\\n\\n uint256 assetIndex = len;\\n for (uint256 i; i < len; ++i) {\\n if (userAssetList[i] == vToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n VToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.pop();\\n\\n emit MarketExited(vToken, msg.sender);\\n\\n return NO_ERROR;\\n }\\n\\n /*** Policy Hooks ***/\\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 * @custom:error ActionPaused error is thrown if supplying to this market is paused\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\\n * @custom:access Not restricted\\n */\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external override {\\n _checkActionPauseState(vToken, Action.MINT);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n uint256 supplyCap = supplyCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (supplyCap != type(uint256).max) {\\n uint256 vTokenSupply = VToken(vToken).totalSupply();\\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\\n if (nextTotalSupply > supplyCap) {\\n revert SupplyCapExceeded(vToken, supplyCap);\\n }\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, minter);\\n }\\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external override {\\n _checkActionPauseState(vToken, Action.REDEEM);\\n\\n _checkRedeemAllowed(vToken, redeemer, redeemTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, redeemer);\\n }\\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 if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(redeemer, vToken);\\n }\\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 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 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 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 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 * @custom:error ActionPaused error is thrown if borrowing is paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if there is not enough collateral to borrow\\n * @custom:error BorrowCapExceeded is thrown if the borrow cap will be exceeded should this borrow succeed\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted if vToken is enabled as collateral, otherwise only vToken\\n */\\n /// disable-eslint\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external override {\\n _checkActionPauseState(vToken, Action.BORROW);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (!markets[vToken].accountMembership[borrower]) {\\n // only vTokens may call borrowAllowed if borrower not in market\\n _checkSenderIs(vToken);\\n\\n // attempt to add borrower to the market or revert\\n _addToMarket(VToken(msg.sender), borrower);\\n }\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (oracle.getUnderlyingPrice(vToken) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 borrowCap = borrowCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (borrowCap != type(uint256).max) {\\n uint256 totalBorrows = VToken(vToken).totalBorrows();\\n uint256 badDebt = VToken(vToken).badDebt();\\n uint256 nextTotalBorrows = totalBorrows + borrowAmount + badDebt;\\n if (nextTotalBorrows > borrowCap) {\\n revert BorrowCapExceeded(vToken, borrowCap);\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n borrower,\\n VToken(vToken),\\n 0,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\n }\\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 borrower The account which would borrowed the asset\\n * @custom:error ActionPaused error is thrown if repayments are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:access Not restricted\\n */\\n function preRepayHook(address vToken, address borrower) external override {\\n _checkActionPauseState(vToken, Action.REPAY);\\n\\n oracle.updatePrice(vToken);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\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 borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n * @param skipLiquidityCheck Allows the borrow to be liquidated regardless of the account liquidity\\n * @custom:error ActionPaused error is thrown if liquidations are paused in this market\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor\\n * @custom:error MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations\\n * @custom:error InsufficientShortfall is thrown when trying to liquidate a healthy account\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n */\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external override {\\n // Pause Action.LIQUIDATE on BORROWED TOKEN to prevent liquidating it.\\n // If we want to pause liquidating to vTokenCollateral, we should pause\\n // Action.SEIZE on it\\n _checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(address(vTokenBorrowed));\\n }\\n if (!markets[vTokenCollateral].isListed) {\\n revert MarketNotListed(address(vTokenCollateral));\\n }\\n\\n uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\\n\\n /* Allow accounts to be liquidated if it is a forced liquidation */\\n if (skipLiquidityCheck || isForcedLiquidationEnabled[vTokenBorrowed]) {\\n if (repayAmount > borrowBalance) {\\n revert TooMuchRepay();\\n }\\n return;\\n }\\n\\n /* The borrower must have shortfall and collateral > threshold in order to be liquidatable */\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral <= minLiquidatableCollateral) {\\n /* The liquidator should use either liquidateAccount or healAccount */\\n revert MinimalCollateralViolated(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint256 maxClose = mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance);\\n if (repayAmount > maxClose) {\\n revert TooMuchRepay();\\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 seizerContract Contract that tries to seize the asset (either borrowed vToken or Comptroller)\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @custom:error ActionPaused error is thrown if seizing this type of collateral is paused\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error ComptrollerMismatch error is when seizer contract or seized asset belong to different pools\\n * @custom:access Not restricted\\n */\\n function preSeizeHook(\\n address vTokenCollateral,\\n address seizerContract,\\n address liquidator,\\n address borrower\\n ) external override {\\n // Pause Action.SEIZE on COLLATERAL to prevent seizing it.\\n // If we want to pause liquidating vTokenBorrowed, we should pause\\n // Action.LIQUIDATE on it\\n _checkActionPauseState(vTokenCollateral, Action.SEIZE);\\n\\n Market storage market = markets[vTokenCollateral];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(vTokenCollateral);\\n }\\n\\n if (seizerContract == address(this)) {\\n // If Comptroller is the seizer, just check if collateral's comptroller\\n // is equal to the current address\\n if (address(VToken(vTokenCollateral).comptroller()) != address(this)) {\\n revert ComptrollerMismatch();\\n }\\n } else {\\n // If the seizer is not the Comptroller, check that the seizer is a\\n // listed market, and that the markets' comptrollers match\\n if (!markets[seizerContract].isListed) {\\n revert MarketNotListed(seizerContract);\\n }\\n if (VToken(vTokenCollateral).comptroller() != VToken(seizerContract).comptroller()) {\\n revert ComptrollerMismatch();\\n }\\n }\\n\\n if (!market.accountMembership[borrower]) {\\n revert MarketNotCollateral(vTokenCollateral, borrower);\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vTokenCollateral);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, borrower);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, liquidator);\\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external override {\\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 _checkRedeemAllowed(vToken, src, transferTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, src);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, dst);\\n }\\n }\\n\\n /*** Pool-level operations ***/\\n\\n /**\\n * @notice Seizes all the remaining collateral, makes msg.sender repay the existing\\n * borrows, and treats the rest of the debt as bad debt (for each market).\\n * The sender has to repay a certain percentage of the debt, computed as\\n * collateral / (borrows * liquidationIncentive).\\n * @param user account to heal\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for healing\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function healAccount(address user) external {\\n VToken[] memory userAssets = getAssetsIn(user);\\n uint256 userAssetsCount = userAssets.length;\\n\\n address liquidator = msg.sender;\\n {\\n ResilientOracleInterface oracle_ = oracle;\\n // We need all user's markets to be fresh for the computations to be correct\\n for (uint256 i; i < userAssetsCount; ++i) {\\n userAssets[i].accrueInterest();\\n oracle_.updatePrice(address(userAssets[i]));\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(user, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n // percentage = collateral / (borrows * liquidation incentive)\\n Exp memory collateral = Exp({ mantissa: snapshot.totalCollateral });\\n Exp memory scaledBorrows = mul_(\\n Exp({ mantissa: snapshot.borrows }),\\n Exp({ mantissa: liquidationIncentiveMantissa })\\n );\\n\\n Exp memory percentage = div_(collateral, scaledBorrows);\\n if (lessThanExp(Exp({ mantissa: MANTISSA_ONE }), percentage)) {\\n revert CollateralExceedsThreshold(scaledBorrows.mantissa, collateral.mantissa);\\n }\\n\\n for (uint256 i; i < userAssetsCount; ++i) {\\n VToken market = userAssets[i];\\n\\n (uint256 tokens, uint256 borrowBalance, ) = _safeGetAccountSnapshot(market, user);\\n uint256 repaymentAmount = mul_ScalarTruncate(percentage, borrowBalance);\\n\\n // Seize the entire collateral\\n if (tokens != 0) {\\n market.seize(liquidator, user, tokens);\\n }\\n // Repay a certain percentage of the borrow, forgive the rest\\n if (borrowBalance != 0) {\\n market.healBorrow(liquidator, user, repaymentAmount);\\n }\\n }\\n }\\n\\n /**\\n * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than\\n * a predefined threshold, and the account collateral can be seized to cover all borrows. If\\n * the collateral is higher than the threshold, use regular liquidations. If the collateral is\\n * below the threshold, and the account is insolvent, use healAccount.\\n * @param borrower the borrower address\\n * @param orders an array of liquidation orders\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation\\n * @custom:error InsufficientCollateral error is thrown when there is not enough collateral to cover the debt\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function liquidateAccount(address borrower, LiquidationOrder[] calldata orders) external {\\n // We will accrue interest and update the oracle prices later during the liquidation\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n // You should use the regular vToken.liquidateBorrow(...) call\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n uint256 collateralToSeize = mul_ScalarTruncate(\\n Exp({ mantissa: liquidationIncentiveMantissa }),\\n snapshot.borrows\\n );\\n if (collateralToSeize >= snapshot.totalCollateral) {\\n // There is not enough collateral to seize. Use healBorrow to repay some part of the borrow\\n // and record bad debt.\\n revert InsufficientCollateral(collateralToSeize, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n uint256 ordersCount = orders.length;\\n\\n _ensureMaxLoops(ordersCount / 2);\\n\\n for (uint256 i; i < ordersCount; ++i) {\\n if (!markets[address(orders[i].vTokenBorrowed)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenBorrowed));\\n }\\n if (!markets[address(orders[i].vTokenCollateral)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenCollateral));\\n }\\n\\n LiquidationOrder calldata order = orders[i];\\n order.vTokenBorrowed.forceLiquidateBorrow(\\n msg.sender,\\n borrower,\\n order.repayAmount,\\n order.vTokenCollateral,\\n true\\n );\\n }\\n\\n VToken[] memory borrowMarkets = getAssetsIn(borrower);\\n uint256 marketsCount = borrowMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower);\\n require(borrowBalance == 0, \\\"Nonzero borrow balance after liquidation\\\");\\n }\\n }\\n\\n /**\\n * @notice Sets the closeFactor to use when liquidating borrows\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @custom:event Emits NewCloseFactor on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCloseFactor(uint256 newCloseFactorMantissa) external {\\n _checkAccessAllowed(\\\"setCloseFactor(uint256)\\\");\\n require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, \\\"Close factor greater than maximum close factor\\\");\\n require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, \\\"Close factor smaller than minimum close factor\\\");\\n\\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev This function is restricted by the AccessControlManager\\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 * @custom:event Emits NewCollateralFactor when collateral factor is updated\\n * and NewLiquidationThreshold when liquidation threshold is updated\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InvalidCollateralFactor error is thrown when collateral factor is too high\\n * @custom:error InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor\\n * @custom:error PriceError is thrown when the oracle returns an invalid price for the asset\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCollateralFactor(\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external {\\n _checkAccessAllowed(\\\"setCollateralFactor(address,uint256,uint256)\\\");\\n\\n // Verify market is listed\\n Market storage market = markets[address(vToken)];\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Check collateral factor <= 0.9\\n if (newCollateralFactorMantissa > MAX_COLLATERAL_FACTOR_MANTISSA) {\\n revert InvalidCollateralFactor();\\n }\\n\\n // Ensure that liquidation threshold <= 1\\n if (newLiquidationThresholdMantissa > MANTISSA_ONE) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // Ensure that liquidation threshold >= CF\\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n }\\n\\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\\n emit NewLiquidationThreshold(vToken, oldLiquidationThresholdMantissa, newLiquidationThresholdMantissa);\\n }\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev This function is restricted by the AccessControlManager\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @custom:event Emits NewLiquidationIncentive on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external {\\n require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, \\\"liquidation incentive should be greater than 1e18\\\");\\n\\n _checkAccessAllowed(\\\"setLiquidationIncentive(uint256)\\\");\\n\\n // Save current value for use in log\\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\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\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Only callable by the PoolRegistry\\n * @param vToken The address of the market (token) to list\\n * @custom:error MarketAlreadyListed is thrown if the market is already listed in this pool\\n * @custom:access Only PoolRegistry\\n */\\n function supportMarket(VToken vToken) external {\\n _checkSenderIs(poolRegistry);\\n\\n if (markets[address(vToken)].isListed) {\\n revert MarketAlreadyListed(address(vToken));\\n }\\n\\n require(vToken.isVToken(), \\\"Comptroller: Invalid vToken\\\"); // Sanity check to make sure its really a VToken\\n\\n Market storage newMarket = markets[address(vToken)];\\n newMarket.isListed = true;\\n newMarket.collateralFactorMantissa = 0;\\n newMarket.liquidationThresholdMantissa = 0;\\n\\n _addMarket(address(vToken));\\n\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n rewardsDistributors[i].initializeMarket(address(vToken));\\n }\\n\\n emit MarketSupported(vToken);\\n }\\n\\n /**\\n * @notice Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A borrow cap of type(uint256).max corresponds to unlimited borrowing.\\n * @dev Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed\\n until the total borrows amount goes below the new borrow cap\\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 type(uint256).max corresponds to unlimited borrowing.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\\n _checkAccessAllowed(\\\"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 _ensureMaxLoops(numMarkets);\\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 * @notice Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A supply cap of type(uint256).max corresponds to unlimited supply.\\n * @dev Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed\\n until the total supplies amount goes below the new supply cap\\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 type(uint256).max corresponds to unlimited supply.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\\n _checkAccessAllowed(\\\"setMarketSupplyCaps(address[],uint256[])\\\");\\n uint256 vTokensCount = vTokens.length;\\n\\n require(vTokensCount != 0, \\\"invalid number of markets\\\");\\n require(vTokensCount == newSupplyCaps.length, \\\"invalid number of markets\\\");\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Pause/unpause specified actions\\n * @dev This function is restricted by the AccessControlManager\\n * @param marketsList Markets to pause/unpause the actions on\\n * @param actionsList List of action ids to pause/unpause\\n * @param paused The new paused state (true=paused, false=unpaused)\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setActionsPaused(VToken[] calldata marketsList, Action[] calldata actionsList, bool paused) external {\\n _checkAccessAllowed(\\\"setActionsPaused(address[],uint256[],bool)\\\");\\n\\n uint256 marketsCount = marketsList.length;\\n uint256 actionsCount = actionsList.length;\\n\\n _ensureMaxLoops(marketsCount * actionsCount);\\n\\n for (uint256 marketIdx; marketIdx < marketsCount; ++marketIdx) {\\n for (uint256 actionIdx; actionIdx < actionsCount; ++actionIdx) {\\n _setActionPaused(address(marketsList[marketIdx]), actionsList[actionIdx], paused);\\n }\\n }\\n }\\n\\n /**\\n * @notice Set the given collateral threshold for non-batch liquidations. Regular liquidations\\n * will fail if the collateral amount is less than this threshold. Liquidators should use batch\\n * operations like liquidateAccount or healAccount.\\n * @dev This function is restricted by the AccessControlManager\\n * @param newMinLiquidatableCollateral The new min liquidatable collateral (in USD).\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external {\\n _checkAccessAllowed(\\\"setMinLiquidatableCollateral(uint256)\\\");\\n\\n uint256 oldMinLiquidatableCollateral = minLiquidatableCollateral;\\n minLiquidatableCollateral = newMinLiquidatableCollateral;\\n emit NewMinLiquidatableCollateral(oldMinLiquidatableCollateral, newMinLiquidatableCollateral);\\n }\\n\\n /**\\n * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor\\n * contracts with the same rewardToken, and there could be overlaping among them considering the last reward slot (block or second)\\n * @dev Only callable by the admin\\n * @param _rewardsDistributor Address of the RewardDistributor contract to add\\n * @custom:access Only Governance\\n * @custom:event Emits NewRewardsDistributor with distributor address\\n */\\n function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner {\\n require(!rewardsDistributorExists[address(_rewardsDistributor)], \\\"already exists\\\");\\n\\n uint256 rewardsDistributorsLen = rewardsDistributors.length;\\n _ensureMaxLoops(rewardsDistributorsLen + 1);\\n\\n rewardsDistributors.push(_rewardsDistributor);\\n rewardsDistributorExists[address(_rewardsDistributor)] = true;\\n\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n _rewardsDistributor.initializeMarket(address(allMarkets[i]));\\n }\\n\\n emit NewRewardsDistributor(address(_rewardsDistributor), address(_rewardsDistributor.rewardToken()));\\n }\\n\\n /**\\n * @notice Sets a new price oracle for the Comptroller\\n * @dev Only callable by the admin\\n * @param newOracle Address of the new price oracle to set\\n * @custom:event Emits NewPriceOracle on success\\n * @custom:error ZeroAddressNotAllowed is thrown when the new oracle address is zero\\n */\\n function setPriceOracle(ResilientOracleInterface newOracle) external onlyOwner {\\n ensureNonzeroAddress(address(newOracle));\\n\\n ResilientOracleInterface oldOracle = oracle;\\n oracle = newOracle;\\n emit NewPriceOracle(oldOracle, newOracle);\\n }\\n\\n /**\\n * @notice Set the for loop iteration limit to avoid DOS\\n * @param limit Limit for the max loops can execute at a time\\n */\\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Sets the prime token contract for the comptroller\\n * @param _prime Address of the Prime contract\\n */\\n function setPrimeToken(IPrime _prime) external onlyOwner {\\n ensureNonzeroAddress(address(_prime));\\n\\n emit NewPrimeToken(prime, _prime);\\n prime = _prime;\\n }\\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 * @param vTokenBorrowed Borrowed vToken\\n * @param enable Whether to enable forced liquidations\\n */\\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\\n _checkAccessAllowed(\\\"setForcedLiquidation(address,bool)\\\");\\n ensureNonzeroAddress(vTokenBorrowed);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(vTokenBorrowed);\\n }\\n\\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to liquidation threshold requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of liquidation threshold requirements,\\n * @return shortfall Account shortfall below liquidation threshold requirements\\n */\\n function getAccountLiquidity(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getLiquidationThreshold);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to collateral requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of collateral requirements,\\n * @return shortfall Account shortfall below collateral requirements\\n */\\n function getBorrowingPower(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getCollateralFactor);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Hypothetical account liquidity in excess of collateral requirements,\\n * @return shortfall 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 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n account,\\n VToken(vTokenModify),\\n redeemTokens,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\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 markets The list of market addresses\\n */\\n function getAllMarkets() external view override returns (VToken[] memory) {\\n return allMarkets;\\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 /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns whether the given account is entered in a given market\\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 market specified, 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 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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return tokensToSeize Number of vTokenCollateral tokens to be seized in a liquidation\\n * @custom:error PriceError if the oracle returns an invalid price\\n */\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view override returns (uint256 error, uint256 tokensToSeize) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint256 priceBorrowedMantissa = _safeGetUnderlyingPrice(VToken(vTokenBorrowed));\\n uint256 priceCollateralMantissa = _safeGetUnderlyingPrice(VToken(vTokenCollateral));\\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 uint256 exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint256 seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n\\n numerator = mul_(Exp({ mantissa: liquidationIncentiveMantissa }), Exp({ mantissa: priceBorrowedMantissa }));\\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\\n ratio = div_(numerator, denominator);\\n\\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\\n\\n return (NO_ERROR, seizeTokens);\\n }\\n\\n /**\\n * @notice Returns reward speed given a vToken\\n * @param vToken The vToken to get the reward speeds for\\n * @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors\\n */\\n function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {\\n uint256 rewardsDistributorsLength = rewardsDistributors.length;\\n rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);\\n for (uint256 i; i < rewardsDistributorsLength; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n address rewardToken = address(rewardsDistributor.rewardToken());\\n rewardSpeeds[i] = RewardSpeeds({\\n rewardToken: rewardToken,\\n supplySpeed: rewardsDistributor.rewardTokenSupplySpeeds(vToken),\\n borrowSpeed: rewardsDistributor.rewardTokenBorrowSpeeds(vToken)\\n });\\n }\\n return rewardSpeeds;\\n }\\n\\n /**\\n * @notice Return all reward distributors for this pool\\n * @return Array of RewardDistributor addresses\\n */\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory) {\\n return rewardsDistributors;\\n }\\n\\n /**\\n * @notice A marker method that returns true for a valid Comptroller contract\\n * @return Always true\\n */\\n function isComptroller() external pure override returns (bool) {\\n return true;\\n }\\n\\n /**\\n * @notice Update the prices of all the tokens associated with the provided account\\n * @param account Address of the account to get associated tokens with\\n */\\n function updatePrices(address account) public {\\n VToken[] memory vTokens = getAssetsIn(account);\\n uint256 vTokensCount = vTokens.length;\\n\\n ResilientOracleInterface oracle_ = oracle;\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n oracle_.updatePrice(address(vTokens[i]));\\n }\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param market vToken address\\n * @param action Action to check\\n * @return paused True if the action is paused otherwise false\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][action];\\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 list with the assets the account has entered\\n */\\n function getAssetsIn(address account) public 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 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 */\\n function _addToMarket(VToken vToken, address borrower) internal {\\n _checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = markets[address(vToken)];\\n\\n if (!marketToJoin.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return;\\n }\\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\\n /**\\n * @notice Internal function to validate that a market hasn't already been added\\n * and if it hasn't adds it\\n * @param vToken The market to support\\n */\\n function _addMarket(address vToken) internal {\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n if (allMarkets[i] == VToken(vToken)) {\\n revert MarketAlreadyListed(vToken);\\n }\\n }\\n allMarkets.push(VToken(vToken));\\n marketsCount = allMarkets.length;\\n _ensureMaxLoops(marketsCount);\\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 _setActionPaused(address market, Action action, bool paused) internal {\\n require(markets[market].isListed, \\\"cannot pause a market that is not listed\\\");\\n _actionPaused[market][action] = paused;\\n emit ActionPausedMarket(VToken(market), action, paused);\\n }\\n\\n /**\\n * @dev Internal function to check that vTokens can be safely redeemed for the underlying asset.\\n * @param vToken Address of the vTokens to redeem\\n * @param redeemer Account redeeming the tokens\\n * @param redeemTokens The number of tokens to redeem\\n */\\n function _checkRedeemAllowed(address vToken, address redeemer, uint256 redeemTokens) internal {\\n Market storage market = markets[vToken];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!market.accountMembership[redeemer]) {\\n return;\\n }\\n\\n // Update the prices of tokens\\n updatePrices(redeemer);\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n _getCollateralFactor\\n );\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n }\\n\\n /**\\n * @notice Get the total collateral, weighted collateral, borrow balance, liquidity, shortfall\\n * @param account The account to get the snapshot for\\n * @param weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n * liquidation threshold. Accepts the address of the vToken and returns the weight as Exp.\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getCurrentLiquiditySnapshot(\\n address account,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n return _getHypotheticalLiquiditySnapshot(account, VToken(address(0)), 0, 0, weight);\\n }\\n\\n /**\\n * @notice Determine what the supply/borrow balances 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 weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n liquidation threshold. Accepts the address of the VToken and returns the weight\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getHypotheticalLiquiditySnapshot(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n // For each asset the account is in\\n VToken[] memory assets = getAssetsIn(account);\\n uint256 assetsCount = assets.length;\\n\\n for (uint256 i; i < assetsCount; ++i) {\\n VToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the vToken\\n (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) = _safeGetAccountSnapshot(\\n asset,\\n account\\n );\\n\\n // Get the normalized price of the asset\\n Exp memory oraclePrice = Exp({ mantissa: _safeGetUnderlyingPrice(asset) });\\n\\n // Pre-compute conversion factors from vTokens -> usd\\n Exp memory vTokenPrice = mul_(Exp({ mantissa: exchangeRateMantissa }), oraclePrice);\\n Exp memory weightedVTokenPrice = mul_(weight(asset), vTokenPrice);\\n\\n // weightedCollateral += weightedVTokenPrice * vTokenBalance\\n snapshot.weightedCollateral = mul_ScalarTruncateAddUInt(\\n weightedVTokenPrice,\\n vTokenBalance,\\n snapshot.weightedCollateral\\n );\\n\\n // totalCollateral += vTokenPrice * vTokenBalance\\n snapshot.totalCollateral = mul_ScalarTruncateAddUInt(vTokenPrice, vTokenBalance, snapshot.totalCollateral);\\n\\n // borrows += oraclePrice * borrowBalance\\n snapshot.borrows = mul_ScalarTruncateAddUInt(oraclePrice, borrowBalance, snapshot.borrows);\\n\\n // Calculate effects of interacting with vTokenModify\\n if (asset == vTokenModify) {\\n // redeem effect\\n // effects += tokensToDenom * redeemTokens\\n snapshot.effects = mul_ScalarTruncateAddUInt(weightedVTokenPrice, redeemTokens, snapshot.effects);\\n\\n // borrow effect\\n // effects += oraclePrice * borrowAmount\\n snapshot.effects = mul_ScalarTruncateAddUInt(oraclePrice, borrowAmount, snapshot.effects);\\n }\\n }\\n\\n uint256 borrowPlusEffects = snapshot.borrows + snapshot.effects;\\n // These are safe, as the underflow condition is checked first\\n unchecked {\\n if (snapshot.weightedCollateral > borrowPlusEffects) {\\n snapshot.liquidity = snapshot.weightedCollateral - borrowPlusEffects;\\n snapshot.shortfall = 0;\\n } else {\\n snapshot.liquidity = 0;\\n snapshot.shortfall = borrowPlusEffects - snapshot.weightedCollateral;\\n }\\n }\\n\\n return snapshot;\\n }\\n\\n /**\\n * @dev Retrieves price from oracle for an asset and checks it is nonzero\\n * @param asset Address for asset to query price\\n * @return Underlying price\\n */\\n function _safeGetUnderlyingPrice(VToken asset) internal view returns (uint256) {\\n uint256 oraclePriceMantissa = oracle.getUnderlyingPrice(address(asset));\\n if (oraclePriceMantissa == 0) {\\n revert PriceError(address(asset));\\n }\\n return oraclePriceMantissa;\\n }\\n\\n /**\\n * @dev Return collateral factor for a market\\n * @param asset Address for asset\\n * @return Collateral factor as exponential\\n */\\n function _getCollateralFactor(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].collateralFactorMantissa });\\n }\\n\\n /**\\n * @dev Retrieves liquidation threshold for a market as an exponential\\n * @param asset Address for asset to liquidation threshold\\n * @return Liquidation threshold as exponential\\n */\\n function _getLiquidationThreshold(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].liquidationThresholdMantissa });\\n }\\n\\n /**\\n * @dev Returns supply and borrow balances of user in vToken, reverts on failure\\n * @param vToken Market to query\\n * @param user Account address\\n * @return vTokenBalance Balance of vTokens, the same as vToken.balanceOf(user)\\n * @return borrowBalance Borrowed amount, including the interest\\n * @return exchangeRateMantissa Stored exchange rate\\n */\\n function _safeGetAccountSnapshot(\\n VToken vToken,\\n address user\\n ) internal view returns (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) {\\n uint256 err;\\n (err, vTokenBalance, borrowBalance, exchangeRateMantissa) = vToken.getAccountSnapshot(user);\\n if (err != 0) {\\n revert SnapshotError(address(vToken), user);\\n }\\n return (vTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /// @notice Reverts if the call is not from expectedSender\\n /// @param expectedSender Expected transaction sender\\n function _checkSenderIs(address expectedSender) internal view {\\n if (msg.sender != expectedSender) {\\n revert UnexpectedSender(expectedSender, msg.sender);\\n }\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n /// @param market Market to check\\n /// @param action Action to check\\n function _checkActionPauseState(address market, Action action) private view {\\n if (actionPaused(market, action)) {\\n revert ActionPaused(market, action);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7c6e1c6264e4681f82a9ac1bcd9155197a930033291ee5561ad97a56006f5e9c\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.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\\n/**\\n * @title ComptrollerInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract.\\n */\\ninterface ComptrollerInterface {\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\\n\\n function exitMarket(address vToken) external returns (uint256);\\n\\n /*** Policy Hooks ***/\\n\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external;\\n\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external;\\n\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external;\\n\\n function preRepayHook(address vToken, address borrower) external;\\n\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external;\\n\\n function preSeizeHook(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower\\n ) external;\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\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 seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external;\\n\\n function isComptroller() external view returns (bool);\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 repayAmount\\n ) external view returns (uint256, uint256);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n}\\n\\n/**\\n * @title ComptrollerViewInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract, including only some util view functions.\\n */\\ninterface ComptrollerViewInterface {\\n function markets(address) external view returns (bool, uint256);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function closeFactorMantissa() external view returns (uint256);\\n\\n function liquidationIncentiveMantissa() external view returns (uint256);\\n\\n function minLiquidatableCollateral() external view returns (uint256);\\n\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function borrowCaps(address) external view returns (uint256);\\n\\n function supplyCaps(address) external view returns (uint256);\\n\\n function approvedDelegates(address user, address delegate) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xcbf7f9977472650c61345b7cbde23e81f626e1f8863bab4c6ce3dacfc7604919\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { IPrime } from \\\"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\\\";\\nimport { Action } from \\\"./ComptrollerInterface.sol\\\";\\n\\n/**\\n * @title ComptrollerStorage\\n * @author Venus\\n * @notice Storage layout for the `Comptroller` contract.\\n */\\ncontract ComptrollerStorage {\\n struct LiquidationOrder {\\n VToken vTokenCollateral;\\n VToken vTokenBorrowed;\\n uint256 repayAmount;\\n }\\n\\n struct AccountLiquiditySnapshot {\\n uint256 totalCollateral;\\n uint256 weightedCollateral;\\n uint256 borrows;\\n uint256 effects;\\n uint256 liquidity;\\n uint256 shortfall;\\n }\\n\\n struct RewardSpeeds {\\n address rewardToken;\\n uint256 supplySpeed;\\n uint256 borrowSpeed;\\n }\\n\\n struct Market {\\n // Whether or not this market is listed\\n bool isListed;\\n // 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 uint256 collateralFactorMantissa;\\n // 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 uint256 liquidationThresholdMantissa;\\n // Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n }\\n\\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 Per-account mapping of \\\"assets you are in\\\"\\n */\\n mapping(address => VToken[]) public accountAssets;\\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 /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\\n mapping(address => uint256) public borrowCaps;\\n\\n /// @notice Minimal collateral required for regular (non-batch) liquidations\\n uint256 public minLiquidatableCollateral;\\n\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\\n mapping(address => uint256) public supplyCaps;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(Action => bool)) internal _actionPaused;\\n\\n // List of Reward Distributors added\\n RewardsDistributor[] internal rewardsDistributors;\\n\\n // Used to check if rewards distributor is added\\n mapping(address => bool) internal rewardsDistributorExists;\\n\\n /// @notice Flag indicating whether forced liquidation enabled for a market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n\\n uint256 internal constant NO_ERROR = 0;\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant MIN_CLOSE_FACTOR_MANTISSA = 0.05e18; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant MAX_CLOSE_FACTOR_MANTISSA = 0.9e18; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.95e18; // 0.95\\n\\n /// Prime token address\\n IPrime public prime;\\n\\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 /**\\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[47] private __gap;\\n}\\n\",\"keccak256\":\"0x4df44cb65ac152bac2be4b4545430e703005a74a55b72e144100b16421bd8bfd\",\"license\":\"BSD-3-Clause\"},\"contracts/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title TokenErrorReporter\\n * @author Venus\\n * @notice Errors that can be thrown by the `VToken` contract.\\n */\\ncontract TokenErrorReporter {\\n uint256 public constant NO_ERROR = 0; // support legacy return codes\\n\\n error TransferNotAllowed();\\n\\n error MintFreshnessCheck();\\n\\n error RedeemFreshnessCheck();\\n error RedeemTransferOutNotPossible();\\n\\n error BorrowFreshnessCheck();\\n error BorrowCashNotAvailable();\\n error DelegateNotApproved();\\n\\n error RepayBorrowFreshnessCheck();\\n\\n error HealBorrowUnauthorized();\\n error ForceLiquidateBorrowUnauthorized();\\n\\n error LiquidateFreshnessCheck();\\n error LiquidateCollateralFreshnessCheck();\\n error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\\n error LiquidateLiquidatorIsBorrower();\\n error LiquidateCloseAmountIsZero();\\n error LiquidateCloseAmountIsUintMax();\\n\\n error LiquidateSeizeLiquidatorIsBorrower();\\n\\n error ProtocolSeizeShareTooBig();\\n\\n error SetReserveFactorFreshCheck();\\n error SetReserveFactorBoundsCheck();\\n\\n error AddReservesFactorFreshCheck(uint256 actualAddAmount);\\n\\n error ReduceReservesFreshCheck();\\n error ReduceReservesCashNotAvailable();\\n error ReduceReservesCashValidation();\\n\\n error SetInterestRateModelFreshCheck();\\n}\\n\",\"keccak256\":\"0x7a7ced1caaac2d9242659ebd50b99f308c725ce958ac9e11f7ada404b1d97a7b\",\"license\":\"BSD-3-Clause\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from \\\"./lib/constants.sol\\\";\\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 struct Exp {\\n uint256 mantissa;\\n }\\n\\n struct Double {\\n uint256 mantissa;\\n }\\n\\n uint256 internal constant EXP_SCALE = EXP_SCALE_;\\n uint256 internal constant DOUBLE_SCALE = 1e36;\\n uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;\\n uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint256) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / EXP_SCALE;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\\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 // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint256 scalar, uint256 addend) internal pure returns (uint256) {\\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 function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\\n require(n <= type(uint224).max, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\\n require(n <= type(uint32).max, 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_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a + b;\\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_(uint256 a, uint256 b) internal pure returns (uint256) {\\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) / EXP_SCALE });\\n }\\n\\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / EXP_SCALE;\\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) / DOUBLE_SCALE });\\n }\\n\\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / DOUBLE_SCALE;\\n }\\n\\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a * b;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return div_(mul_(a, EXP_SCALE), 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, DOUBLE_SCALE), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return div_(mul_(a, DOUBLE_SCALE), b.mantissa);\\n }\\n\\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a / b;\\n }\\n\\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });\\n }\\n}\\n\",\"keccak256\":\"0x8afbe8a24fe3539c124e718681ed3dcebd24c40dd53095786c0155998213b9b0\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModel.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\nabstract contract InterestRateModel {\\n /**\\n * @notice Calculates the current borrow interest rate per slot (block or second)\\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 amount of reserves the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per slot (block or second)\\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 amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\\n * @return Always true\\n */\\n function isInterestRateModel() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xc4fda1ab75ebe4b187b707c4f10c58780f343cf343c537f641dc75d3cd28ab51\",\"license\":\"BSD-3-Clause\"},\"contracts/Lens/PoolLens.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { IERC20Metadata } from \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Action, ComptrollerInterface, ComptrollerViewInterface } from \\\"../ComptrollerInterface.sol\\\";\\nimport { PoolRegistryInterface } from \\\"../Pool/PoolRegistryInterface.sol\\\";\\nimport { PoolRegistry } from \\\"../Pool/PoolRegistry.sol\\\";\\nimport { RewardsDistributor } from \\\"../Rewards/RewardsDistributor.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\n\\n/**\\n * @title PoolLens\\n * @author Venus\\n * @notice The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information\\n * for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be\\n * looked up for specific pools and markets:\\n- the vToken balance of a given user;\\n- the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address;\\n- the vToken address in a pool for a given asset;\\n- a list of all pools that support an asset;\\n- the underlying asset price of a vToken;\\n- the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\\n */\\ncontract PoolLens is ExponentialNoError, TimeManagerV8 {\\n /**\\n * @dev Struct for PoolDetails.\\n */\\n struct PoolData {\\n string name;\\n address creator;\\n address comptroller;\\n uint256 blockPosted;\\n uint256 timestampPosted;\\n string category;\\n string logoURL;\\n string description;\\n address priceOracle;\\n uint256 closeFactor;\\n uint256 liquidationIncentive;\\n uint256 minLiquidatableCollateral;\\n VTokenMetadata[] vTokens;\\n }\\n\\n /**\\n * @dev Struct for VToken.\\n */\\n struct VTokenMetadata {\\n address vToken;\\n uint256 exchangeRateCurrent;\\n uint256 supplyRatePerBlockOrTimestamp;\\n uint256 borrowRatePerBlockOrTimestamp;\\n uint256 reserveFactorMantissa;\\n uint256 supplyCaps;\\n uint256 borrowCaps;\\n uint256 totalBorrows;\\n uint256 totalReserves;\\n uint256 totalSupply;\\n uint256 totalCash;\\n bool isListed;\\n uint256 collateralFactorMantissa;\\n address underlyingAssetAddress;\\n uint256 vTokenDecimals;\\n uint256 underlyingDecimals;\\n uint256 pausedActions;\\n }\\n\\n /**\\n * @dev Struct for VTokenBalance.\\n */\\n struct VTokenBalances {\\n address vToken;\\n uint256 balanceOf;\\n uint256 borrowBalanceCurrent;\\n uint256 balanceOfUnderlying;\\n uint256 tokenBalance;\\n uint256 tokenAllowance;\\n }\\n\\n /**\\n * @dev Struct for underlyingPrice of VToken.\\n */\\n struct VTokenUnderlyingPrice {\\n address vToken;\\n uint256 underlyingPrice;\\n }\\n\\n /**\\n * @dev Struct with pending reward info for a market.\\n */\\n struct PendingReward {\\n address vTokenAddress;\\n uint256 amount;\\n }\\n\\n /**\\n * @dev Struct with reward distribution totals for a single reward token and distributor.\\n */\\n struct RewardSummary {\\n address distributorAddress;\\n address rewardTokenAddress;\\n uint256 totalRewards;\\n PendingReward[] pendingRewards;\\n }\\n\\n /**\\n * @dev Struct used in RewardDistributor to save last updated market state.\\n */\\n struct RewardTokenState {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number or timestamp the index was last updated at\\n uint256 blockOrTimestamp;\\n // The block number or timestamp at which to stop rewards\\n uint256 lastRewardingBlockOrTimestamp;\\n }\\n\\n /**\\n * @dev Struct with bad debt of a market denominated\\n */\\n struct BadDebt {\\n address vTokenAddress;\\n uint256 badDebtUsd;\\n }\\n\\n /**\\n * @dev Struct with bad debt total denominated in usd for a pool and an array of BadDebt structs for each market\\n */\\n struct BadDebtSummary {\\n address comptroller;\\n uint256 totalBadDebtUsd;\\n BadDebt[] badDebts;\\n }\\n\\n /// @notice Address of the core pool comptroller (all markets are returned for this pool, including paused ones)\\n address public immutable corePoolComptroller;\\n\\n /**\\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @param corePoolComptroller_ The address of the core pool comptroller\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(\\n bool timeBased_,\\n uint256 blocksPerYear_,\\n address corePoolComptroller_\\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\\n corePoolComptroller = corePoolComptroller_;\\n }\\n\\n /**\\n * @notice Queries the user's supply/borrow balances in vTokens\\n * @param vTokens The list of vToken addresses\\n * @param account The user Account\\n * @return A list of structs containing balances data\\n */\\n function vTokenBalancesAll(VToken[] calldata vTokens, address account) external returns (VTokenBalances[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenBalances[] memory res = new VTokenBalances[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenBalances(vTokens[i], account);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Queries all pools with addtional details for each of them\\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @return Arrays of all Venus pools' data\\n */\\n function getAllPools(address poolRegistryAddress) external view returns (PoolData[] memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n PoolRegistry.VenusPool[] memory venusPools = poolRegistryInterface.getAllPools();\\n uint256 poolLength = venusPools.length;\\n\\n PoolData[] memory poolDataItems = new PoolData[](poolLength);\\n\\n for (uint256 i; i < poolLength; ++i) {\\n PoolRegistry.VenusPool memory venusPool = venusPools[i];\\n PoolData memory poolData = getPoolDataFromVenusPool(poolRegistryAddress, venusPool);\\n poolDataItems[i] = poolData;\\n }\\n\\n return poolDataItems;\\n }\\n\\n /**\\n * @notice Queries the details of a pool identified by Comptroller address\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param comptroller The Comptroller implementation address\\n * @return PoolData structure containing the details of the pool\\n */\\n function getPoolByComptroller(\\n address poolRegistryAddress,\\n address comptroller\\n ) external view returns (PoolData memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return getPoolDataFromVenusPool(poolRegistryAddress, poolRegistryInterface.getPoolByComptroller(comptroller));\\n }\\n\\n /**\\n * @notice Returns vToken holding the specified underlying asset in the specified pool\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param comptroller The pool comptroller\\n * @param asset The underlyingAsset of VToken\\n * @return Address of the vToken\\n */\\n function getVTokenForAsset(\\n address poolRegistryAddress,\\n address comptroller,\\n address asset\\n ) external view returns (address) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return poolRegistryInterface.getVTokenForAsset(comptroller, asset);\\n }\\n\\n /**\\n * @notice Returns all pools that support the specified underlying asset\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param asset The underlying asset of vToken\\n * @return A list of Comptroller contracts\\n */\\n function getPoolsSupportedByAsset(\\n address poolRegistryAddress,\\n address asset\\n ) external view returns (address[] memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return poolRegistryInterface.getPoolsSupportedByAsset(asset);\\n }\\n\\n /**\\n * @notice Returns the price data for the underlying assets of the specified vTokens\\n * @param vTokens The list of vToken addresses\\n * @return An array containing the price data for each asset\\n */\\n function vTokenUnderlyingPriceAll(\\n VToken[] calldata vTokens\\n ) external view returns (VTokenUnderlyingPrice[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenUnderlyingPrice[] memory res = new VTokenUnderlyingPrice[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenUnderlyingPrice(vTokens[i]);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Returns the pending rewards for a user for a given pool.\\n * @param account The user account.\\n * @param comptrollerAddress address\\n * @return Pending rewards array\\n */\\n function getPendingRewards(\\n address account,\\n address comptrollerAddress\\n ) external view returns (RewardSummary[] memory) {\\n VToken[] memory markets = _getMarkets(ComptrollerInterface(comptrollerAddress));\\n RewardsDistributor[] memory rewardsDistributors = ComptrollerViewInterface(comptrollerAddress)\\n .getRewardDistributors();\\n RewardSummary[] memory rewardSummary = new RewardSummary[](rewardsDistributors.length);\\n for (uint256 i; i < rewardsDistributors.length; ++i) {\\n RewardSummary memory reward;\\n reward.distributorAddress = address(rewardsDistributors[i]);\\n reward.rewardTokenAddress = address(rewardsDistributors[i].rewardToken());\\n reward.totalRewards = rewardsDistributors[i].rewardTokenAccrued(account);\\n reward.pendingRewards = _calculateNotDistributedAwards(account, markets, rewardsDistributors[i]);\\n rewardSummary[i] = reward;\\n }\\n return rewardSummary;\\n }\\n\\n /**\\n * @notice Returns a summary of a pool's bad debt broken down by market\\n *\\n * @param comptrollerAddress Address of the comptroller\\n *\\n * @return badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and\\n * a break down of bad debt by market\\n */\\n function getPoolBadDebt(address comptrollerAddress) external view returns (BadDebtSummary memory) {\\n uint256 totalBadDebtUsd;\\n\\n // Get every listed market in the pool\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\\n VToken[] memory markets = _getMarkets(ComptrollerInterface(comptrollerAddress));\\n ResilientOracleInterface priceOracle = comptroller.oracle();\\n\\n BadDebt[] memory badDebts = new BadDebt[](markets.length);\\n\\n BadDebtSummary memory badDebtSummary;\\n badDebtSummary.comptroller = comptrollerAddress;\\n badDebtSummary.badDebts = badDebts;\\n\\n // // Calculate the bad debt is USD per market\\n for (uint256 i; i < markets.length; ++i) {\\n BadDebt memory badDebt;\\n badDebt.vTokenAddress = address(markets[i]);\\n badDebt.badDebtUsd =\\n (VToken(address(markets[i])).badDebt() * priceOracle.getUnderlyingPrice(address(markets[i]))) /\\n EXP_SCALE;\\n badDebtSummary.badDebts[i] = badDebt;\\n totalBadDebtUsd = totalBadDebtUsd + badDebt.badDebtUsd;\\n }\\n\\n badDebtSummary.totalBadDebtUsd = totalBadDebtUsd;\\n\\n return badDebtSummary;\\n }\\n\\n /**\\n * @notice Queries the user's supply/borrow balances in the specified vToken\\n * @param vToken vToken address\\n * @param account The user Account\\n * @return A struct containing the balances data\\n */\\n function vTokenBalances(VToken vToken, address account) public returns (VTokenBalances memory) {\\n uint256 balanceOf = vToken.balanceOf(account);\\n uint256 borrowBalanceCurrent = vToken.borrowBalanceCurrent(account);\\n uint256 balanceOfUnderlying = vToken.balanceOfUnderlying(account);\\n uint256 tokenBalance;\\n uint256 tokenAllowance;\\n\\n IERC20 underlying = IERC20(vToken.underlying());\\n tokenBalance = underlying.balanceOf(account);\\n tokenAllowance = underlying.allowance(account, address(vToken));\\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 Queries additional information for the pool\\n * @param poolRegistryAddress Address of the PoolRegistry\\n * @param venusPool The VenusPool Object from PoolRegistry\\n * @return Enriched PoolData\\n */\\n function getPoolDataFromVenusPool(\\n address poolRegistryAddress,\\n PoolRegistry.VenusPool memory venusPool\\n ) public view returns (PoolData memory) {\\n // Get tokens in the Pool\\n ComptrollerInterface comptrollerInstance = ComptrollerInterface(venusPool.comptroller);\\n\\n VToken[] memory vTokens = _getMarkets(comptrollerInstance);\\n\\n VTokenMetadata[] memory vTokenMetadataItems = vTokenMetadataAll(vTokens);\\n\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n\\n PoolRegistry.VenusPoolMetaData memory venusPoolMetaData = poolRegistryInterface.getVenusPoolMetadata(\\n venusPool.comptroller\\n );\\n\\n ComptrollerViewInterface comptrollerViewInstance = ComptrollerViewInterface(venusPool.comptroller);\\n\\n PoolData memory poolData = PoolData({\\n name: venusPool.name,\\n creator: venusPool.creator,\\n comptroller: venusPool.comptroller,\\n blockPosted: venusPool.blockPosted,\\n timestampPosted: venusPool.timestampPosted,\\n category: venusPoolMetaData.category,\\n logoURL: venusPoolMetaData.logoURL,\\n description: venusPoolMetaData.description,\\n vTokens: vTokenMetadataItems,\\n priceOracle: address(comptrollerViewInstance.oracle()),\\n closeFactor: comptrollerViewInstance.closeFactorMantissa(),\\n liquidationIncentive: comptrollerViewInstance.liquidationIncentiveMantissa(),\\n minLiquidatableCollateral: comptrollerViewInstance.minLiquidatableCollateral()\\n });\\n\\n return poolData;\\n }\\n\\n /**\\n * @notice Returns the metadata of VToken\\n * @param vToken The address of vToken\\n * @return VTokenMetadata struct\\n */\\n function vTokenMetadata(VToken vToken) public view returns (VTokenMetadata memory) {\\n uint256 exchangeRateCurrent = vToken.exchangeRateStored();\\n address comptrollerAddress = address(vToken.comptroller());\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\\n (bool isListed, uint256 collateralFactorMantissa) = comptroller.markets(address(vToken));\\n\\n address underlyingAssetAddress = vToken.underlying();\\n uint256 underlyingDecimals = IERC20Metadata(underlyingAssetAddress).decimals();\\n\\n uint256 pausedActions;\\n for (uint8 i; i <= uint8(type(Action).max); ++i) {\\n uint256 paused = ComptrollerInterface(comptrollerAddress).actionPaused(address(vToken), Action(i)) ? 1 : 0;\\n pausedActions |= paused << i;\\n }\\n\\n uint256 supplyRatePerBlock;\\n\\n if (vToken.totalSupply() > 0) {\\n supplyRatePerBlock = vToken.supplyRatePerBlock();\\n }\\n\\n return\\n VTokenMetadata({\\n vToken: address(vToken),\\n exchangeRateCurrent: exchangeRateCurrent,\\n supplyRatePerBlockOrTimestamp: supplyRatePerBlock,\\n borrowRatePerBlockOrTimestamp: vToken.borrowRatePerBlock(),\\n reserveFactorMantissa: vToken.reserveFactorMantissa(),\\n supplyCaps: comptroller.supplyCaps(address(vToken)),\\n borrowCaps: comptroller.borrowCaps(address(vToken)),\\n totalBorrows: vToken.totalBorrows(),\\n totalReserves: vToken.totalReserves(),\\n totalSupply: vToken.totalSupply(),\\n totalCash: vToken.getCash(),\\n isListed: isListed,\\n collateralFactorMantissa: collateralFactorMantissa,\\n underlyingAssetAddress: underlyingAssetAddress,\\n vTokenDecimals: vToken.decimals(),\\n underlyingDecimals: underlyingDecimals,\\n pausedActions: pausedActions\\n });\\n }\\n\\n /**\\n * @notice Returns the metadata of all VTokens\\n * @param vTokens The list of vToken addresses\\n * @return An array of VTokenMetadata structs\\n */\\n function vTokenMetadataAll(VToken[] memory vTokens) public view returns (VTokenMetadata[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenMetadata[] memory res = new VTokenMetadata[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenMetadata(vTokens[i]);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Returns the price data for the underlying asset of the specified vToken\\n * @param vToken vToken address\\n * @return The price data for each asset\\n */\\n function vTokenUnderlyingPrice(VToken vToken) public view returns (VTokenUnderlyingPrice memory) {\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(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 Returns markets from a comptroller. For the core pool, all markets are returned.\\n * For other pools, markets with zero internalCash are filtered.\\n * @param comptroller The comptroller to query\\n * @return An array of VToken addresses\\n */\\n function _getMarkets(ComptrollerInterface comptroller) internal view returns (VToken[] memory) {\\n VToken[] memory allMarkets = comptroller.getAllMarkets();\\n\\n if (address(comptroller) == corePoolComptroller) {\\n return allMarkets;\\n }\\n\\n // Single-loop filter: pack active markets to the front of allMarkets\\n uint256 count;\\n uint256 len = allMarkets.length;\\n for (uint256 i; i < len; ++i) {\\n if (allMarkets[i].internalCash() > 0) {\\n allMarkets[count] = allMarkets[i];\\n ++count;\\n }\\n }\\n\\n // Trim the array to the active count\\n assembly {\\n mstore(allMarkets, count)\\n }\\n\\n return allMarkets;\\n }\\n\\n function _calculateNotDistributedAwards(\\n address account,\\n VToken[] memory markets,\\n RewardsDistributor rewardsDistributor\\n ) internal view returns (PendingReward[] memory) {\\n PendingReward[] memory pendingRewards = new PendingReward[](markets.length);\\n\\n for (uint256 i; i < markets.length; ++i) {\\n // Market borrow and supply state we will modify update in-memory, in order to not modify storage\\n RewardTokenState memory borrowState;\\n RewardTokenState memory supplyState;\\n\\n if (isTimeBased) {\\n (\\n borrowState.index,\\n borrowState.blockOrTimestamp,\\n borrowState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenBorrowStateTimeBased(address(markets[i]));\\n (\\n supplyState.index,\\n supplyState.blockOrTimestamp,\\n supplyState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenSupplyStateTimeBased(address(markets[i]));\\n } else {\\n (\\n borrowState.index,\\n borrowState.blockOrTimestamp,\\n borrowState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenBorrowState(address(markets[i]));\\n (\\n supplyState.index,\\n supplyState.blockOrTimestamp,\\n supplyState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenSupplyState(address(markets[i]));\\n }\\n\\n Exp memory marketBorrowIndex = Exp({ mantissa: markets[i].borrowIndex() });\\n\\n // Update market supply and borrow index in-memory\\n updateMarketBorrowIndex(address(markets[i]), rewardsDistributor, borrowState, marketBorrowIndex);\\n updateMarketSupplyIndex(address(markets[i]), rewardsDistributor, supplyState);\\n\\n // Calculate pending rewards\\n uint256 borrowReward = calculateBorrowerReward(\\n address(markets[i]),\\n rewardsDistributor,\\n account,\\n borrowState,\\n marketBorrowIndex\\n );\\n uint256 supplyReward = calculateSupplierReward(\\n address(markets[i]),\\n rewardsDistributor,\\n account,\\n supplyState\\n );\\n\\n PendingReward memory pendingReward;\\n pendingReward.vTokenAddress = address(markets[i]);\\n pendingReward.amount = borrowReward + supplyReward;\\n pendingRewards[i] = pendingReward;\\n }\\n return pendingRewards;\\n }\\n\\n function updateMarketBorrowIndex(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n RewardTokenState memory borrowState,\\n Exp memory marketBorrowIndex\\n ) internal view {\\n uint256 borrowSpeed = rewardsDistributor.rewardTokenBorrowSpeeds(vToken);\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (\\n borrowState.lastRewardingBlockOrTimestamp > 0 &&\\n blockNumberOrTimestamp > borrowState.lastRewardingBlockOrTimestamp\\n ) {\\n blockNumberOrTimestamp = borrowState.lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, borrowState.blockOrTimestamp);\\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\\n // Remove the total earned interest rate since the opening of the market from total borrows\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, borrowSpeed);\\n Double memory ratio = borrowAmount > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\\n } else if (deltaBlocksOrTimestamp > 0) {\\n borrowState.blockOrTimestamp = blockNumberOrTimestamp;\\n }\\n }\\n\\n function updateMarketSupplyIndex(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n RewardTokenState memory supplyState\\n ) internal view {\\n uint256 supplySpeed = rewardsDistributor.rewardTokenSupplySpeeds(vToken);\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (\\n supplyState.lastRewardingBlockOrTimestamp > 0 &&\\n blockNumberOrTimestamp > supplyState.lastRewardingBlockOrTimestamp\\n ) {\\n blockNumberOrTimestamp = supplyState.lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, supplyState.blockOrTimestamp);\\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, supplySpeed);\\n Double memory ratio = supplyTokens > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\\n } else if (deltaBlocksOrTimestamp > 0) {\\n supplyState.blockOrTimestamp = blockNumberOrTimestamp;\\n }\\n }\\n\\n function calculateBorrowerReward(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n address borrower,\\n RewardTokenState memory borrowState,\\n Exp memory marketBorrowIndex\\n ) internal view returns (uint256) {\\n Double memory borrowIndex = Double({ mantissa: borrowState.index });\\n Double memory borrowerIndex = Double({\\n mantissa: rewardsDistributor.rewardTokenBorrowerIndex(vToken, borrower)\\n });\\n if (borrowerIndex.mantissa == 0 && borrowIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set\\n borrowerIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\\n }\\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n return borrowerDelta;\\n }\\n\\n function calculateSupplierReward(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n address supplier,\\n RewardTokenState memory supplyState\\n ) internal view returns (uint256) {\\n Double memory supplyIndex = Double({ mantissa: supplyState.index });\\n Double memory supplierIndex = Double({\\n mantissa: rewardsDistributor.rewardTokenSupplierIndex(vToken, supplier)\\n });\\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\\n // Covers the case where users supplied tokens before the market's supply state index was set\\n supplierIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\\n }\\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n return supplierDelta;\\n }\\n}\\n\",\"keccak256\":\"0xfe3f00ebb7f0b5c98ee03cf1cfa1a013a56984cf6879373c70a74b3d9d0db399\",\"license\":\"BSD-3-Clause\"},\"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\",\"keccak256\":\"0x4c25e30635485d162177effa384eee51768b0141a567a0da16ff6ad673274166\",\"license\":\"BSD-3-Clause\"},\"contracts/Pool/PoolRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\nimport { PoolRegistryInterface } from \\\"./PoolRegistryInterface.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"../lib/validators.sol\\\";\\n\\n/**\\n * @title PoolRegistry\\n * @author Venus\\n * @notice The Isolated Pools architecture centers around the `PoolRegistry` contract. The `PoolRegistry` maintains a directory of isolated lending\\n * pools and can perform actions like creating and registering new pools, adding new markets to existing pools, setting and updating the pool's required\\n * metadata, and providing the getter methods to get information on the pools.\\n *\\n * Isolated lending has three main components: PoolRegistry, pools, and markets. The PoolRegistry is responsible for managing pools.\\n * It can create new pools, update pool metadata and manage markets within pools. PoolRegistry contains getter methods to get the details of\\n * any existing pool like `getVTokenForAsset` and `getPoolsSupportedByAsset`. It also contains methods for updating pool metadata (`updatePoolMetadata`)\\n * and setting pool name (`setPoolName`).\\n *\\n * The directory of pools is managed through two mappings: `_poolByComptroller` which is a hashmap with the comptroller address as the key and `VenusPool` as\\n * the value and `_poolsByID` which is an array of comptroller addresses. Individual pools can be accessed by calling `getPoolByComptroller` with the pool's\\n * comptroller address. `_poolsByID` is used to iterate through all of the pools.\\n *\\n * PoolRegistry also contains a map of asset addresses called `_supportedPools` that maps to an array of assets suppored by each pool. This array of pools by\\n * asset is retrieved by calling `getPoolsSupportedByAsset`.\\n *\\n * PoolRegistry registers new isolated pools in the directory with the `createRegistryPool` method. Isolated pools are composed of independent markets with\\n * specific assets and custom risk management configurations according to their markets.\\n */\\ncontract PoolRegistry is Ownable2StepUpgradeable, AccessControlledV8, PoolRegistryInterface {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n struct AddMarketInput {\\n VToken vToken;\\n uint256 collateralFactor;\\n uint256 liquidationThreshold;\\n uint256 initialSupply;\\n address vTokenReceiver;\\n uint256 supplyCap;\\n uint256 borrowCap;\\n }\\n\\n uint256 internal constant MAX_POOL_NAME_LENGTH = 100;\\n\\n /**\\n * @notice Maps pool's comptroller address to metadata.\\n */\\n mapping(address => VenusPoolMetaData) public metadata;\\n\\n /**\\n * @dev Maps pool ID to pool's comptroller address\\n */\\n mapping(uint256 => address) private _poolsByID;\\n\\n /**\\n * @dev Total number of pools created.\\n */\\n uint256 private _numberOfPools;\\n\\n /**\\n * @dev Maps comptroller address to Venus pool Index.\\n */\\n mapping(address => VenusPool) private _poolByComptroller;\\n\\n /**\\n * @dev Maps pool's comptroller address to asset to vToken.\\n */\\n mapping(address => mapping(address => address)) private _vTokens;\\n\\n /**\\n * @dev Maps asset to list of supported pools.\\n */\\n mapping(address => address[]) private _supportedPools;\\n\\n /**\\n * @notice Emitted when a new Venus pool is added to the directory.\\n */\\n event PoolRegistered(address indexed comptroller, VenusPool pool);\\n\\n /**\\n * @notice Emitted when a pool name is set.\\n */\\n event PoolNameSet(address indexed comptroller, string oldName, string newName);\\n\\n /**\\n * @notice Emitted when a pool metadata is updated.\\n */\\n event PoolMetadataUpdated(\\n address indexed comptroller,\\n VenusPoolMetaData oldMetadata,\\n VenusPoolMetaData newMetadata\\n );\\n\\n /**\\n * @notice Emitted when a Market is added to the pool.\\n */\\n event MarketAdded(address indexed comptroller, address indexed vTokenAddress);\\n\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor() {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializes the deployer to owner\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(address accessControlManager_) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n /**\\n * @notice Adds a new Venus pool to the directory\\n * @dev Price oracle must be configured before adding a pool\\n * @param name The name of the pool\\n * @param comptroller Pool's Comptroller contract\\n * @param closeFactor The pool's close factor (scaled by 1e18)\\n * @param liquidationIncentive The pool's liquidation incentive (scaled by 1e18)\\n * @param minLiquidatableCollateral Minimal collateral for regular (non-batch) liquidations flow\\n * @return index The index of the registered Venus pool\\n * @custom:error ZeroAddressNotAllowed is thrown when Comptroller address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\\n */\\n function addPool(\\n string calldata name,\\n Comptroller comptroller,\\n uint256 closeFactor,\\n uint256 liquidationIncentive,\\n uint256 minLiquidatableCollateral\\n ) external virtual returns (uint256 index) {\\n _checkAccessAllowed(\\\"addPool(string,address,uint256,uint256,uint256)\\\");\\n // Input validation\\n ensureNonzeroAddress(address(comptroller));\\n ensureNonzeroAddress(address(comptroller.oracle()));\\n\\n uint256 poolId = _registerPool(name, address(comptroller));\\n\\n // Set Venus pool parameters\\n comptroller.setCloseFactor(closeFactor);\\n comptroller.setLiquidationIncentive(liquidationIncentive);\\n comptroller.setMinLiquidatableCollateral(minLiquidatableCollateral);\\n\\n return poolId;\\n }\\n\\n /**\\n * @notice Add a market to an existing pool and then mint to provide initial supply\\n * @param input The structure describing the parameters for adding a market to a pool\\n * @custom:error ZeroAddressNotAllowed is thrown when vToken address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when vTokenReceiver address is zero\\n */\\n function addMarket(AddMarketInput memory input) external {\\n _checkAccessAllowed(\\\"addMarket(AddMarketInput)\\\");\\n ensureNonzeroAddress(address(input.vToken));\\n ensureNonzeroAddress(input.vTokenReceiver);\\n require(input.initialSupply > 0, \\\"PoolRegistry: initialSupply is zero\\\");\\n\\n VToken vToken = input.vToken;\\n address vTokenAddress = address(vToken);\\n address comptrollerAddress = address(vToken.comptroller());\\n Comptroller comptroller = Comptroller(comptrollerAddress);\\n address underlyingAddress = vToken.underlying();\\n IERC20Upgradeable underlying = IERC20Upgradeable(underlyingAddress);\\n\\n require(_poolByComptroller[comptrollerAddress].creator != address(0), \\\"PoolRegistry: Pool not registered\\\");\\n // solhint-disable-next-line reason-string\\n require(\\n _vTokens[comptrollerAddress][underlyingAddress] == address(0),\\n \\\"PoolRegistry: Market already added for asset comptroller combination\\\"\\n );\\n\\n comptroller.supportMarket(vToken);\\n comptroller.setCollateralFactor(vToken, input.collateralFactor, input.liquidationThreshold);\\n\\n uint256[] memory newSupplyCaps = new uint256[](1);\\n uint256[] memory newBorrowCaps = new uint256[](1);\\n VToken[] memory vTokens = new VToken[](1);\\n\\n newSupplyCaps[0] = input.supplyCap;\\n newBorrowCaps[0] = input.borrowCap;\\n vTokens[0] = vToken;\\n\\n comptroller.setMarketSupplyCaps(vTokens, newSupplyCaps);\\n comptroller.setMarketBorrowCaps(vTokens, newBorrowCaps);\\n\\n _vTokens[comptrollerAddress][underlyingAddress] = vTokenAddress;\\n _supportedPools[underlyingAddress].push(comptrollerAddress);\\n\\n uint256 amountToSupply = _transferIn(underlying, msg.sender, input.initialSupply);\\n underlying.forceApprove(vTokenAddress, 0);\\n underlying.forceApprove(vTokenAddress, amountToSupply);\\n vToken.mintBehalf(input.vTokenReceiver, amountToSupply);\\n\\n emit MarketAdded(comptrollerAddress, vTokenAddress);\\n }\\n\\n /**\\n * @notice Modify existing Venus pool name\\n * @param comptroller Pool's Comptroller\\n * @param name New pool name\\n */\\n function setPoolName(address comptroller, string calldata name) external {\\n _checkAccessAllowed(\\\"setPoolName(address,string)\\\");\\n _ensureValidName(name);\\n VenusPool storage pool = _poolByComptroller[comptroller];\\n string memory oldName = pool.name;\\n pool.name = name;\\n emit PoolNameSet(comptroller, oldName, name);\\n }\\n\\n /**\\n * @notice Update metadata of an existing pool\\n * @param comptroller Pool's Comptroller\\n * @param metadata_ New pool metadata\\n */\\n function updatePoolMetadata(address comptroller, VenusPoolMetaData calldata metadata_) external {\\n _checkAccessAllowed(\\\"updatePoolMetadata(address,VenusPoolMetaData)\\\");\\n VenusPoolMetaData memory oldMetadata = metadata[comptroller];\\n metadata[comptroller] = metadata_;\\n emit PoolMetadataUpdated(comptroller, oldMetadata, metadata_);\\n }\\n\\n /**\\n * @notice Returns arrays of all Venus pools' data\\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\\n * @return A list of all pools within PoolRegistry, with details for each pool\\n */\\n function getAllPools() external view override returns (VenusPool[] memory) {\\n uint256 numberOfPools_ = _numberOfPools; // storage load to save gas\\n VenusPool[] memory _pools = new VenusPool[](numberOfPools_);\\n for (uint256 i = 1; i <= numberOfPools_; ++i) {\\n address comptroller = _poolsByID[i];\\n _pools[i - 1] = (_poolByComptroller[comptroller]);\\n }\\n return _pools;\\n }\\n\\n /**\\n * @param comptroller The comptroller proxy address associated to the pool\\n * @return Returns Venus pool\\n */\\n function getPoolByComptroller(address comptroller) external view override returns (VenusPool memory) {\\n return _poolByComptroller[comptroller];\\n }\\n\\n /**\\n * @param comptroller comptroller of Venus pool\\n * @return Returns Metadata of Venus pool\\n */\\n function getVenusPoolMetadata(address comptroller) external view override returns (VenusPoolMetaData memory) {\\n return metadata[comptroller];\\n }\\n\\n function getVTokenForAsset(address comptroller, address asset) external view override returns (address) {\\n return _vTokens[comptroller][asset];\\n }\\n\\n function getPoolsSupportedByAsset(address asset) external view override returns (address[] memory) {\\n return _supportedPools[asset];\\n }\\n\\n /**\\n * @dev Adds a new Venus pool to the directory (without checking msg.sender).\\n * @param name The name of the pool\\n * @param comptroller The pool's Comptroller proxy contract address\\n * @return The index of the registered Venus pool\\n */\\n function _registerPool(string calldata name, address comptroller) internal returns (uint256) {\\n VenusPool storage storedPool = _poolByComptroller[comptroller];\\n\\n require(storedPool.creator == address(0), \\\"PoolRegistry: Pool already exists in the directory.\\\");\\n _ensureValidName(name);\\n\\n ++_numberOfPools;\\n uint256 numberOfPools_ = _numberOfPools; // cache on stack to save storage read gas\\n\\n VenusPool memory pool = VenusPool(name, msg.sender, comptroller, block.number, block.timestamp);\\n\\n _poolsByID[numberOfPools_] = comptroller;\\n _poolByComptroller[comptroller] = pool;\\n\\n emit PoolRegistered(comptroller, pool);\\n return numberOfPools_;\\n }\\n\\n function _transferIn(IERC20Upgradeable token, address from, uint256 amount) internal returns (uint256) {\\n uint256 balanceBefore = token.balanceOf(address(this));\\n token.safeTransferFrom(from, address(this), amount);\\n uint256 balanceAfter = token.balanceOf(address(this));\\n return balanceAfter - balanceBefore;\\n }\\n\\n function _ensureValidName(string calldata name) internal pure {\\n require(bytes(name).length <= MAX_POOL_NAME_LENGTH, \\\"Pool's name is too large\\\");\\n }\\n}\\n\",\"keccak256\":\"0xafbb871f7b4db3ef439d846baa5f18a136192f9b43ea695c81262a77b06c4b25\",\"license\":\"BSD-3-Clause\"},\"contracts/Pool/PoolRegistryInterface.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 /**\\n * @notice Struct for a Venus interest rate pool metadata.\\n */\\n struct VenusPoolMetaData {\\n string category;\\n string logoURL;\\n string description;\\n }\\n\\n /// @notice Get all pools in PoolRegistry\\n function getAllPools() external view returns (VenusPool[] memory);\\n\\n /// @notice Get a pool by comptroller address\\n function getPoolByComptroller(address comptroller) external view returns (VenusPool memory);\\n\\n /// @notice Get the address of the VToken contract in the Pool where the underlying token is the provided 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 /// @notice Get the metadata of a Pool by comptroller address\\n function getVenusPoolMetadata(address comptroller) external view returns (VenusPoolMetaData memory);\\n}\\n\",\"keccak256\":\"0x7b39cda3b372a686501ce3c2aad288c6af410148110318249d75d4516729c92c\",\"license\":\"BSD-3-Clause\"},\"contracts/Rewards/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\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 { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"../MaxLoopsLimitHelper.sol\\\";\\nimport { RewardsDistributorStorage } from \\\"./RewardsDistributorStorage.sol\\\";\\n\\n/**\\n * @title `RewardsDistributor`\\n * @author Venus\\n * @notice Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol.\\n * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward\\n * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool.\\n * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward\\n * token to be released each slot (block or second) for borrowers and suppliers, which is distributed based on a user\\u2019s percentage of the borrows or supplies\\n * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting\\n * their contributor reward token speed, which similarly allocates a fixed amount of reward token per slot (block or second).\\n *\\n * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed\\n * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized\\n * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\\n */\\ncontract RewardsDistributor is\\n ExponentialNoError,\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n MaxLoopsLimitHelper,\\n RewardsDistributorStorage,\\n TimeManagerV8\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice The initial REWARD TOKEN index for a market\\n uint224 public constant INITIAL_INDEX = 1e36;\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a supplier\\n event DistributedSupplierRewardToken(\\n VToken indexed vToken,\\n address indexed supplier,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenSupplyIndex\\n );\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a borrower\\n event DistributedBorrowerRewardToken(\\n VToken indexed vToken,\\n address indexed borrower,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenBorrowIndex\\n );\\n\\n /// @notice Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when REWARD TOKEN is granted by admin\\n event RewardTokenGranted(address indexed recipient, uint256 amount);\\n\\n /// @notice Emitted when a new REWARD TOKEN speed is set for a contributor\\n event ContributorRewardTokenSpeedUpdated(address indexed contributor, uint256 newSpeed);\\n\\n /// @notice Emitted when a market is initialized\\n event MarketInitialized(address indexed vToken);\\n\\n /// @notice Emitted when a reward token supply index is updated\\n event RewardTokenSupplyIndexUpdated(address indexed vToken);\\n\\n /// @notice Emitted when a reward token borrow index is updated\\n event RewardTokenBorrowIndexUpdated(address indexed vToken, Exp marketBorrowIndex);\\n\\n /// @notice Emitted when a reward for contributor is updated\\n event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued);\\n\\n /// @notice Emitted when a reward token last rewarding block for supply is updated\\n event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding block for borrow is updated\\n event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding timestamp for supply is updated\\n event SupplyLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\\n\\n /// @notice Emitted when a reward token last rewarding timestamp for borrow is updated\\n event BorrowLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\\n\\n modifier onlyComptroller() {\\n require(address(comptroller) == msg.sender, \\\"Only comptroller can call this function\\\");\\n _;\\n }\\n\\n /**\\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice RewardsDistributor initializer\\n * @dev Initializes the deployer to owner\\n * @param comptroller_ Comptroller to attach the reward distributor to\\n * @param rewardToken_ Reward token to distribute\\n * @param loopsLimit_ Maximum number of iterations for the loops in this contract\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(\\n Comptroller comptroller_,\\n IERC20Upgradeable rewardToken_,\\n uint256 loopsLimit_,\\n address accessControlManager_\\n ) external initializer {\\n comptroller = comptroller_;\\n rewardToken = rewardToken_;\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n\\n _setMaxLoopsLimit(loopsLimit_);\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken\\n * @param vToken The address of the vToken to be initialized\\n * @custom:event MarketInitialized emits on success\\n * @custom:access Only Comptroller\\n */\\n function initializeMarket(address vToken) external onlyComptroller {\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n isTimeBased\\n ? _initializeMarketTimestampBased(vToken, blockNumberOrTimestamp)\\n : _initializeMarketBlockBased(vToken, safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\"));\\n\\n emit MarketInitialized(vToken);\\n }\\n\\n /*** Reward Token Distribution ***/\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them\\n * Borrowers will begin to accrue after the first interaction with the protocol.\\n * @dev This function should only be called when the user has a borrow position in the market\\n * (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook)\\n * We avoid an external call to check if they are in the market to save gas because this function is called in many places\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function distributeBorrowerRewardToken(\\n address vToken,\\n address borrower,\\n Exp memory marketBorrowIndex\\n ) external onlyComptroller {\\n _distributeBorrowerRewardToken(vToken, borrower, marketBorrowIndex);\\n }\\n\\n function updateRewardTokenSupplyIndex(address vToken) external onlyComptroller {\\n _updateRewardTokenSupplyIndex(vToken);\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the recipient\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\\n * @param recipient The address of the recipient to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n */\\n function grantRewardToken(address recipient, uint256 amount) external onlyOwner {\\n uint256 amountLeft = _grantRewardToken(recipient, amount);\\n require(amountLeft == 0, \\\"insufficient rewardToken for grant\\\");\\n emit RewardTokenGranted(recipient, amount);\\n }\\n\\n function updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) external onlyComptroller {\\n _updateRewardTokenBorrowIndex(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN borrow and supply speeds for the specified markets\\n * @param vTokens The markets whose REWARD TOKEN speed to update\\n * @param supplySpeeds New supply-side REWARD TOKEN speed for the corresponding market\\n * @param borrowSpeeds New borrow-side REWARD TOKEN speed for the corresponding market\\n */\\n function setRewardTokenSpeeds(\\n VToken[] memory vTokens,\\n uint256[] memory supplySpeeds,\\n uint256[] memory borrowSpeeds\\n ) external {\\n _checkAccessAllowed(\\\"setRewardTokenSpeeds(address[],uint256[],uint256[])\\\");\\n uint256 numTokens = vTokens.length;\\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \\\"invalid setRewardTokenSpeeds\\\");\\n\\n for (uint256 i; i < numTokens; ++i) {\\n _setRewardTokenSpeed(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for the specified markets, used when contract is block based\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market\\n * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market\\n */\\n function setLastRewardingBlocks(\\n VToken[] calldata vTokens,\\n uint32[] calldata supplyLastRewardingBlocks,\\n uint32[] calldata borrowLastRewardingBlocks\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlocks(address[],uint32[],uint32[])\\\");\\n require(!isTimeBased, \\\"Block-based operation only\\\");\\n\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length,\\n \\\"RewardsDistributor::setLastRewardingBlocks invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlock(vTokens[i], supplyLastRewardingBlocks[i], borrowLastRewardingBlocks[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block timestamp for the specified markets, used when contract is time based\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlockTimestamps New supply-side REWARD TOKEN last rewarding block timestamp for the corresponding market\\n * @param borrowLastRewardingBlockTimestamps New borrow-side REWARD TOKEN last rewarding block timestamp for the corresponding market\\n */\\n function setLastRewardingBlockTimestamps(\\n VToken[] calldata vTokens,\\n uint256[] calldata supplyLastRewardingBlockTimestamps,\\n uint256[] calldata borrowLastRewardingBlockTimestamps\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlockTimestamps(address[],uint256[],uint256[])\\\");\\n require(isTimeBased, \\\"Time-based operation only\\\");\\n\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlockTimestamps.length &&\\n numTokens == borrowLastRewardingBlockTimestamps.length,\\n \\\"RewardsDistributor::setLastRewardingBlockTimestamps invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlockTimestamp(\\n vTokens[i],\\n supplyLastRewardingBlockTimestamps[i],\\n borrowLastRewardingBlockTimestamps[i]\\n );\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single contributor\\n * @param contributor The contributor whose REWARD TOKEN speed to update\\n * @param rewardTokenSpeed New REWARD TOKEN speed for contributor\\n */\\n function setContributorRewardTokenSpeed(address contributor, uint256 rewardTokenSpeed) external onlyOwner {\\n // note that REWARD TOKEN speed could be set to 0 to halt liquidity rewards for a contributor\\n updateContributorRewards(contributor);\\n if (rewardTokenSpeed == 0) {\\n // release storage\\n delete lastContributorBlock[contributor];\\n } else {\\n lastContributorBlock[contributor] = getBlockNumberOrTimestamp();\\n }\\n rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed;\\n\\n emit ContributorRewardTokenSpeedUpdated(contributor, rewardTokenSpeed);\\n }\\n\\n function distributeSupplierRewardToken(address vToken, address supplier) external onlyComptroller {\\n _distributeSupplierRewardToken(vToken, supplier);\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in all markets\\n * @param holder The address to claim REWARD TOKEN for\\n */\\n function claimRewardToken(address holder) external {\\n return claimRewardToken(holder, comptroller.getAllMarkets());\\n }\\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) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Calculate additional accrued REWARD TOKEN for a contributor since last accrual\\n * @param contributor The address to calculate contributor rewards for\\n */\\n function updateContributorRewards(address contributor) public {\\n uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, lastContributorBlock[contributor]);\\n if (deltaBlocksOrTimestamp > 0 && rewardTokenSpeed > 0) {\\n uint256 newAccrued = mul_(deltaBlocksOrTimestamp, rewardTokenSpeed);\\n uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued);\\n\\n rewardTokenAccrued[contributor] = contributorAccrued;\\n lastContributorBlock[contributor] = blockNumberOrTimestamp;\\n\\n emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]);\\n }\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in the specified markets\\n * @param holder The address to claim REWARD TOKEN for\\n * @param vTokens The list of markets to claim REWARD TOKEN in\\n */\\n function claimRewardToken(address holder, VToken[] memory vTokens) public {\\n uint256 vTokensCount = vTokens.length;\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n VToken vToken = vTokens[i];\\n require(comptroller.isMarketListed(vToken), \\\"market must be listed\\\");\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n _distributeBorrowerRewardToken(address(vToken), holder, borrowIndex);\\n _updateRewardTokenSupplyIndex(address(vToken));\\n _distributeSupplierRewardToken(address(vToken), holder);\\n }\\n rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for a single market.\\n * @param vToken market's whose reward token last rewarding block to be updated\\n * @param supplyLastRewardingBlock New supply-side REWARD TOKEN last rewarding block for market\\n * @param borrowLastRewardingBlock New borrow-side REWARD TOKEN last rewarding block for market\\n */\\n function _setLastRewardingBlock(\\n VToken vToken,\\n uint32 supplyLastRewardingBlock,\\n uint32 borrowLastRewardingBlock\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockNumber = getBlockNumberOrTimestamp();\\n\\n require(supplyLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n require(borrowLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n\\n uint32 currentSupplyLastRewardingBlock = rewardTokenSupplyState[address(vToken)].lastRewardingBlock;\\n uint32 currentBorrowLastRewardingBlock = rewardTokenBorrowState[address(vToken)].lastRewardingBlock;\\n\\n require(\\n currentSupplyLastRewardingBlock == 0 || currentSupplyLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlock == 0 || currentBorrowLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlock != supplyLastRewardingBlock) {\\n rewardTokenSupplyState[address(vToken)].lastRewardingBlock = supplyLastRewardingBlock;\\n emit SupplyLastRewardingBlockUpdated(address(vToken), supplyLastRewardingBlock);\\n }\\n\\n if (currentBorrowLastRewardingBlock != borrowLastRewardingBlock) {\\n rewardTokenBorrowState[address(vToken)].lastRewardingBlock = borrowLastRewardingBlock;\\n emit BorrowLastRewardingBlockUpdated(address(vToken), borrowLastRewardingBlock);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding timestamp for a single market.\\n * @param vToken market's whose reward token last rewarding timestamp to be updated\\n * @param supplyLastRewardingBlockTimestamp New supply-side REWARD TOKEN last rewarding timestamp for market\\n * @param borrowLastRewardingBlockTimestamp New borrow-side REWARD TOKEN last rewarding timestamp for market\\n */\\n function _setLastRewardingBlockTimestamp(\\n VToken vToken,\\n uint256 supplyLastRewardingBlockTimestamp,\\n uint256 borrowLastRewardingBlockTimestamp\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockTimestamp = getBlockNumberOrTimestamp();\\n\\n require(\\n supplyLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"setting last rewarding timestamp in the past is not allowed\\\"\\n );\\n require(\\n borrowLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"setting last rewarding timestamp in the past is not allowed\\\"\\n );\\n\\n uint256 currentSupplyLastRewardingBlockTimestamp = rewardTokenSupplyStateTimeBased[address(vToken)]\\n .lastRewardingTimestamp;\\n uint256 currentBorrowLastRewardingBlockTimestamp = rewardTokenBorrowStateTimeBased[address(vToken)]\\n .lastRewardingTimestamp;\\n\\n require(\\n currentSupplyLastRewardingBlockTimestamp == 0 || currentSupplyLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlockTimestamp == 0 || currentBorrowLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlockTimestamp != supplyLastRewardingBlockTimestamp) {\\n rewardTokenSupplyStateTimeBased[address(vToken)].lastRewardingTimestamp = supplyLastRewardingBlockTimestamp;\\n emit SupplyLastRewardingBlockTimestampUpdated(address(vToken), supplyLastRewardingBlockTimestamp);\\n }\\n\\n if (currentBorrowLastRewardingBlockTimestamp != borrowLastRewardingBlockTimestamp) {\\n rewardTokenBorrowStateTimeBased[address(vToken)].lastRewardingTimestamp = borrowLastRewardingBlockTimestamp;\\n emit BorrowLastRewardingBlockTimestampUpdated(address(vToken), borrowLastRewardingBlockTimestamp);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single market.\\n * @param vToken market's whose reward token rate to be updated\\n * @param supplySpeed New supply-side REWARD TOKEN speed for market\\n * @param borrowSpeed New borrow-side REWARD TOKEN speed for market\\n */\\n function _setRewardTokenSpeed(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n if (rewardTokenSupplySpeeds[address(vToken)] != supplySpeed) {\\n // Supply speed updated so let's update supply state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n _updateRewardTokenSupplyIndex(address(vToken));\\n\\n // Update speed and emit event\\n rewardTokenSupplySpeeds[address(vToken)] = supplySpeed;\\n emit RewardTokenSupplySpeedUpdated(vToken, supplySpeed);\\n }\\n\\n if (rewardTokenBorrowSpeeds[address(vToken)] != borrowSpeed) {\\n // Borrow speed updated so let's update borrow state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n\\n // Update speed and emit event\\n rewardTokenBorrowSpeeds[address(vToken)] = borrowSpeed;\\n emit RewardTokenBorrowSpeedUpdated(vToken, borrowSpeed);\\n }\\n }\\n\\n /**\\n * @notice Calculate REWARD TOKEN 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 REWARD TOKEN to\\n */\\n function _distributeSupplierRewardToken(address vToken, address supplier) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\\n\\n uint256 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\\n uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier];\\n\\n // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenSupplierIndex[vToken][supplier] = supplyIndex;\\n\\n if (supplierIndex == 0 && supplyIndex >= INITIAL_INDEX) {\\n // Covers the case where users supplied tokens before the market's supply state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when supplier rewards were first\\n // set for the market.\\n supplierIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per vToken accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\\n\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerVToken\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n\\n uint256 supplierAccrued = add_(rewardTokenAccrued[supplier], supplierDelta);\\n rewardTokenAccrued[supplier] = supplierAccrued;\\n\\n emit DistributedSupplierRewardToken(VToken(vToken), supplier, supplierDelta, supplierAccrued, supplyIndex);\\n }\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them.\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function _distributeBorrowerRewardToken(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\\n\\n uint256 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\\n uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower];\\n\\n // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenBorrowerIndex[vToken][borrower] = borrowIndex;\\n\\n if (borrowerIndex == 0 && borrowIndex >= INITIAL_INDEX) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when borrower rewards were first\\n // set for the market.\\n borrowerIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per borrowed unit accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\\n\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerBorrowedUnit\\n if (borrowerAmount != 0) {\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n\\n uint256 borrowerAccrued = add_(rewardTokenAccrued[borrower], borrowerDelta);\\n rewardTokenAccrued[borrower] = borrowerAccrued;\\n\\n emit DistributedBorrowerRewardToken(VToken(vToken), borrower, borrowerDelta, borrowerAccrued, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the user.\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all.\\n * @param user The address of the user to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n * @return The amount of REWARD TOKEN which was NOT transferred to the user\\n */\\n function _grantRewardToken(address user, uint256 amount) internal returns (uint256) {\\n uint256 rewardTokenRemaining = rewardToken.balanceOf(address(this));\\n if (amount > 0 && amount <= rewardTokenRemaining) {\\n rewardToken.safeTransfer(user, amount);\\n return 0;\\n }\\n return amount;\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the supply index\\n * @param vToken The market whose supply index to update\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenSupplyIndex(address vToken) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\\n\\n uint256 supplySpeed = rewardTokenSupplySpeeds[vToken];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (!isTimeBased) {\\n safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\");\\n }\\n\\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\\n ? supplyStateTimeBased.lastRewardingTimestamp\\n : uint256(supplyState.lastRewardingBlock);\\n\\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(\\n blockNumberOrTimestamp,\\n (isTimeBased ? supplyStateTimeBased.timestamp : uint256(supplyState.block))\\n );\\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, supplySpeed);\\n Double memory ratio = supplyTokens > 0\\n ? fraction(accruedSinceUpdate, supplyTokens)\\n : Double({ mantissa: 0 });\\n uint224 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\\n uint224 index = safe224(\\n add_(Double({ mantissa: supplyIndex }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n\\n if (isTimeBased) {\\n supplyStateTimeBased.index = index;\\n supplyStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n supplyState.index = index;\\n supplyState.block = uint32(blockNumberOrTimestamp);\\n }\\n } else if (deltaBlocksOrTimestamp > 0) {\\n isTimeBased ? supplyStateTimeBased.timestamp = blockNumberOrTimestamp : supplyState.block = uint32(\\n blockNumberOrTimestamp\\n );\\n }\\n\\n emit RewardTokenSupplyIndexUpdated(vToken);\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the borrow index\\n * @param vToken The market whose borrow index to update\\n * @param marketBorrowIndex The current global borrow index of vToken\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\\n\\n uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (!isTimeBased) {\\n safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\");\\n }\\n\\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\\n ? borrowStateTimeBased.lastRewardingTimestamp\\n : uint256(borrowState.lastRewardingBlock);\\n\\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(\\n blockNumberOrTimestamp,\\n (isTimeBased ? borrowStateTimeBased.timestamp : uint256(borrowState.block))\\n );\\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, borrowSpeed);\\n Double memory ratio = borrowAmount > 0\\n ? fraction(accruedSinceUpdate, borrowAmount)\\n : Double({ mantissa: 0 });\\n uint224 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\\n uint224 index = safe224(\\n add_(Double({ mantissa: borrowIndex }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n\\n if (isTimeBased) {\\n borrowStateTimeBased.index = index;\\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n borrowState.index = index;\\n borrowState.block = uint32(blockNumberOrTimestamp);\\n }\\n } else if (deltaBlocksOrTimestamp > 0) {\\n if (isTimeBased) {\\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n borrowState.block = uint32(blockNumberOrTimestamp);\\n }\\n }\\n\\n emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken called when contract is block-based\\n * @param vToken The address of the vToken to be initialized\\n * @param blockNumber current block number\\n */\\n function _initializeMarketBlockBased(address vToken, uint32 blockNumber) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n RewardToken storage borrowState = rewardTokenBorrowState[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 = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block numbers\\n */\\n supplyState.block = borrowState.block = blockNumber;\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken called when contract is time-based\\n * @param vToken The address of the vToken to be initialized\\n * @param blockTimestamp current block timestamp\\n */\\n function _initializeMarketTimestampBased(address vToken, uint256 blockTimestamp) internal {\\n TimeBasedRewardToken storage supplyState = rewardTokenSupplyStateTimeBased[vToken];\\n TimeBasedRewardToken storage borrowState = rewardTokenBorrowStateTimeBased[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 = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block timestamp\\n */\\n supplyState.timestamp = borrowState.timestamp = blockTimestamp;\\n }\\n}\\n\",\"keccak256\":\"0x3cc824e59c923cfe25c4f1a875959b7e9410cde8e73cd405de13f301298c697f\",\"license\":\"BSD-3-Clause\"},\"contracts/Rewards/RewardsDistributorStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\n\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\n\\n/**\\n * @title RewardsDistributorStorage\\n * @author Venus\\n * @dev Storage for RewardsDistributor\\n */\\ncontract RewardsDistributorStorage {\\n struct RewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number the index was last updated at\\n uint32 block;\\n // The block number at which to stop rewards\\n uint32 lastRewardingBlock;\\n }\\n\\n struct TimeBasedRewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block timestamp the index was last updated at\\n uint256 timestamp;\\n // The block timestamp at which to stop rewards\\n uint256 lastRewardingTimestamp;\\n }\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => RewardToken) public rewardTokenSupplyState;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex;\\n\\n /// @notice The REWARD TOKEN accrued but not yet transferred to each user\\n mapping(address => uint256) public rewardTokenAccrued;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding borrow market per slot (block or second)\\n mapping(address => uint256) public rewardTokenBorrowSpeeds;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding supply market per slot (block or second)\\n mapping(address => uint256) public rewardTokenSupplySpeeds;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => RewardToken) public rewardTokenBorrowState;\\n\\n /// @notice The portion of REWARD TOKEN that each contributor receives per slot (block or second)\\n mapping(address => uint256) public rewardTokenContributorSpeeds;\\n\\n /// @notice Last slot (block or second) at which a contributor's REWARD TOKEN rewards have been allocated\\n mapping(address => uint256) public lastContributorBlock;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex;\\n\\n Comptroller internal comptroller;\\n\\n IERC20Upgradeable public rewardToken;\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => TimeBasedRewardToken) public rewardTokenSupplyStateTimeBased;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => TimeBasedRewardToken) public rewardTokenBorrowStateTimeBased;\\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[37] private __gap;\\n}\\n\",\"keccak256\":\"0x70e5015a78a2acf95277949c8b4796e10b9ac194130be006d5e5217e158070c0\",\"license\":\"BSD-3-Clause\"},\"contracts/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\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 { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"@venusprotocol/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\\\";\\n\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { ComptrollerInterface, ComptrollerViewInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"./ErrorReporter.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title VToken\\n * @author Venus\\n * @notice Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview,\\n * each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of\\n * the pool. The main actions a user regularly interacts with in a market are:\\n\\n- mint/redeem of vTokens;\\n- transfer of vTokens;\\n- borrow/repay a loan on an underlying asset;\\n- liquidate a borrow or liquidate/heal an account.\\n\\n * A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`.\\n * The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted\\n * `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken`\\n * as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that\\n * a user may borrow up to a portion of their collateral determined by the market\\u2019s collateral factor. However, if their borrowed amount exceeds an amount\\n * calculated using the market\\u2019s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also\\n * pay off interest accrued on the borrow.\\n * \\n * The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller`\\n * and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a\\n * total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`.\\n * Both functions settle all of an account\\u2019s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of\\n * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\\n */\\ncontract VToken is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n VTokenInterface,\\n ExponentialNoError,\\n TokenErrorReporter,\\n TimeManagerV8\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5%\\n\\n // Maximum fraction of interest that can be set aside for reserves\\n uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18;\\n\\n // Maximum borrow rate that can ever be applied per slot(block or second)\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n uint256 internal immutable MAX_BORROW_RATE_MANTISSA;\\n\\n /**\\n * Reentrancy Guard **\\n */\\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 * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @param maxBorrowRateMantissa_ The maximum value of borrowing rate mantissa\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(\\n bool timeBased_,\\n uint256 blocksPerYear_,\\n uint256 maxBorrowRateMantissa_\\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n require(maxBorrowRateMantissa_ <= 1e18, \\\"Max borrow rate must be <= 1e18\\\");\\n\\n MAX_BORROW_RATE_MANTISSA = maxBorrowRateMantissa_;\\n _disableInitializers();\\n }\\n\\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_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n */\\n function initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) external initializer {\\n ensureNonzeroAddress(admin_);\\n\\n // Initialize the market\\n _initialize(\\n underlying_,\\n comptroller_,\\n interestRateModel_,\\n initialExchangeRateMantissa_,\\n name_,\\n symbol_,\\n decimals_,\\n admin_,\\n accessControlManager_,\\n riskManagement,\\n reserveFactorMantissa_\\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 * @return success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, msg.sender, dst, amount);\\n return true;\\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 success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, src, dst, amount);\\n return true;\\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 (uint256.max means infinite)\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Increase approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param addedValue The number of additional tokens spender can transfer\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function increaseAllowance(address spender, uint256 addedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 newAllowance = transferAllowances[src][spender];\\n newAllowance += addedValue;\\n transferAllowances[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n return true;\\n }\\n\\n /**\\n * @notice Decreases approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param subtractedValue The number of tokens to remove from total approval\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 currentAllowance = transferAllowances[src][spender];\\n require(currentAllowance >= subtractedValue, \\\"decreased allowance below zero\\\");\\n unchecked {\\n currentAllowance -= subtractedValue;\\n }\\n\\n transferAllowances[src][spender] = currentAllowance;\\n\\n emit Approval(src, spender, currentAllowance);\\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 amount The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint256) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return totalBorrows The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\\n accrueInterest();\\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 borrowBalance The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n return _borrowBalanceStored(account);\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function mint(uint256 mintAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _mintFresh(msg.sender, msg.sender, mintAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param minter User whom the supply will be attributed to\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when minter address is zero\\n */\\n function mintBehalf(address minter, uint256 mintAmount) external override nonReentrant returns (uint256) {\\n ensureNonzeroAddress(minter);\\n\\n accrueInterest();\\n\\n _mintFresh(msg.sender, minter, mintAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function redeem(uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _redeemFresh(msg.sender, msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function redeemBehalf(address redeemer, uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n _ensureSenderIsDelegateOf(redeemer);\\n\\n accrueInterest();\\n\\n _redeemFresh(redeemer, msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\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 receive from redeeming vTokens\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n */\\n function redeemUnderlying(uint256 redeemAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _redeemFresh(msg.sender, msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function redeemUnderlyingBehalf(\\n address redeemer,\\n uint256 redeemAmount\\n ) external override nonReentrant returns (uint256) {\\n _ensureSenderIsDelegateOf(redeemer);\\n\\n accrueInterest();\\n\\n _redeemFresh(redeemer, msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function borrow(uint256 borrowAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _borrowFresh(msg.sender, msg.sender, borrowAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error DelegateNotApproved is thrown if caller is not approved delegate\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function borrowBehalf(address borrower, uint256 borrowAmount) external override returns (uint256) {\\n _ensureSenderIsDelegateOf(borrower);\\n accrueInterest();\\n\\n _borrowFresh(borrower, msg.sender, borrowAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrow(uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n return NO_ERROR;\\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, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _repayBorrowFresh(msg.sender, borrower, repayAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Not restricted\\n */\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external override returns (uint256) {\\n _liquidateBorrow(msg.sender, borrower, repayAmount, vTokenCollateral, false);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice sets protocol share accumulated from liquidations\\n * @dev must be equal or less than liquidation incentive - 1\\n * @param newProtocolSeizeShareMantissa_ new protocol share mantissa\\n * @custom:event Emits NewProtocolSeizeShare event on success\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error ProtocolSeizeShareTooBig is thrown when the new seize share is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa_) external {\\n _checkAccessAllowed(\\\"setProtocolSeizeShare(uint256)\\\");\\n uint256 liquidationIncentive = ComptrollerViewInterface(address(comptroller)).liquidationIncentiveMantissa();\\n if (newProtocolSeizeShareMantissa_ + MANTISSA_ONE > liquidationIncentive) {\\n revert ProtocolSeizeShareTooBig();\\n }\\n\\n uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\\n protocolSeizeShareMantissa = newProtocolSeizeShareMantissa_;\\n emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa_);\\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 * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n * @custom:event Emits NewReserveFactor event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant {\\n _checkAccessAllowed(\\\"setReserveFactor(uint256)\\\");\\n\\n accrueInterest();\\n _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to the protocol reserve contract\\n * @dev Gracefully return if reserves already reduced in accrueInterest\\n * @param reduceAmount Amount of reduction to reserves\\n * @custom:event Emits ReservesReduced event; may emit AccrueInterest\\n * @custom:error ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash\\n * @custom:error ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\\n * @custom:access Not restricted\\n */\\n function reduceReserves(uint256 reduceAmount) external override nonReentrant {\\n accrueInterest();\\n if (reduceReservesBlockNumber == getBlockNumberOrTimestamp()) return;\\n _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice The sender adds to reserves.\\n * @param addAmount The amount of underlying token to add as reserves\\n * @custom:event Emits ReservesAdded event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function addReserves(uint256 addAmount) external override nonReentrant {\\n accrueInterest();\\n _addReservesFresh(addAmount);\\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 * @custom:event Emits NewMarketInterestRateModel event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external override {\\n _checkAccessAllowed(\\\"setInterestRateModel(address)\\\");\\n\\n accrueInterest();\\n _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially\\n * \\\"forgiving\\\" the borrower. Healing is a situation that should rarely happen. However, some pools\\n * may list risky assets or be configured improperly \\u2013 we want to still handle such cases gracefully.\\n * We assume that Comptroller does the seizing, so this function is only available to Comptroller.\\n * @dev This function does not call any Comptroller hooks (like \\\"healAllowed\\\"), because we assume\\n * the Comptroller does all the necessary checks before calling this function.\\n * @param payer account who repays the debt\\n * @param borrower account to heal\\n * @param repayAmount amount to repay\\n * @custom:event Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\\n * @custom:error HealBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:access Only Comptroller\\n */\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external override nonReentrant {\\n if (repayAmount != 0) {\\n comptroller.preRepayHook(address(this), borrower);\\n }\\n\\n if (msg.sender != address(comptroller)) {\\n revert HealBorrowUnauthorized();\\n }\\n\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 totalBorrowsNew = totalBorrows;\\n\\n uint256 actualRepayAmount;\\n if (repayAmount != 0) {\\n // _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // We violate checks-effects-interactions here to account for tokens that take transfer fees\\n actualRepayAmount = _doTransferIn(payer, repayAmount);\\n totalBorrowsNew = totalBorrowsNew - actualRepayAmount;\\n emit RepayBorrow(\\n payer,\\n borrower,\\n actualRepayAmount,\\n accountBorrowsPrev - actualRepayAmount,\\n totalBorrowsNew\\n );\\n }\\n\\n // The transaction will fail if trying to repay too much\\n uint256 badDebtDelta = accountBorrowsPrev - actualRepayAmount;\\n if (badDebtDelta != 0) {\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld + badDebtDelta;\\n totalBorrowsNew = totalBorrowsNew - badDebtDelta;\\n badDebt = badDebtNew;\\n\\n // We treat healing as \\\"repayment\\\", where vToken is the payer\\n emit RepayBorrow(address(this), borrower, badDebtDelta, 0, totalBorrowsNew);\\n emit BadDebtIncreased(borrower, badDebtDelta, badDebtOld, badDebtNew);\\n }\\n\\n accountBorrows[borrower].principal = 0;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n emit HealBorrow(payer, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice The extended version of liquidations, callable only by Comptroller. May skip\\n * the close factor check. The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Only Comptroller\\n */\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) external override {\\n if (msg.sender != address(comptroller)) {\\n revert ForceLiquidateBorrowUnauthorized();\\n }\\n _liquidateBorrow(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\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 * @custom:event Emits Transfer, ReservesAdded events\\n * @custom:error LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:access Not restricted\\n */\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external override nonReentrant {\\n _seize(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Updates bad debt\\n * @dev Called only when bad debt is recovered from auction. Updates internal cash balance.\\n * @param recoveredAmount_ The amount of bad debt recovered\\n * @custom:event Emits BadDebtRecovered event\\n * @custom:access Only Shortfall contract\\n */\\n function badDebtRecovered(uint256 recoveredAmount_) external {\\n require(msg.sender == shortfall, \\\"only shortfall contract can update bad debt\\\");\\n require(recoveredAmount_ <= badDebt, \\\"more than bad debt recovered from auction\\\");\\n\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld - recoveredAmount_;\\n badDebt = badDebtNew;\\n internalCash += recoveredAmount_;\\n\\n emit BadDebtRecovered(badDebtOld, badDebtNew);\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protocolShareReserve_ The address of the protocol share reserve contract\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n * @custom:access Only Governance\\n */\\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\\n _setProtocolShareReserve(protocolShareReserve_);\\n }\\n\\n /**\\n * @notice Sets shortfall contract address\\n * @param shortfall_ The address of the shortfall contract\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:access Only Governance\\n */\\n function setShortfallContract(address shortfall_) external onlyOwner {\\n _setShortfallContract(shortfall_);\\n }\\n\\n /**\\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\\n * @param token The address of the ERC-20 token to sweep\\n * @custom:access Only Governance\\n */\\n function sweepToken(IERC20Upgradeable token) external override {\\n require(msg.sender == owner(), \\\"VToken::sweepToken: only admin can sweep tokens\\\");\\n require(address(token) != underlying, \\\"VToken::sweepToken: can not sweep underlying token\\\");\\n uint256 balance = token.balanceOf(address(this));\\n token.safeTransfer(owner(), balance);\\n\\n emit SweepToken(address(token));\\n }\\n\\n /**\\n * @notice Sync internalCash with the actual underlying token balance\\n * @dev Used for one-time migration after upgrade to initialize internalCash\\n * @custom:event Emits CashSynced\\n * @custom:access Controlled by AccessControlManager\\n */\\n function syncCash() external override nonReentrant {\\n _checkAccessAllowed(\\\"syncCash()\\\");\\n uint256 oldInternalCash = internalCash;\\n uint256 actualCash = IERC20Upgradeable(underlying).balanceOf(address(this));\\n internalCash = actualCash;\\n emit CashSynced(oldInternalCash, actualCash);\\n }\\n\\n /**\\n * @notice A public function to set new threshold of slot(block or second) difference after which funds will be sent to the protocol share reserve\\n * @param _newReduceReservesBlockOrTimestampDelta slot(block or second) difference value\\n * @custom:access Only Governance\\n */\\n function setReduceReservesBlockDelta(uint256 _newReduceReservesBlockOrTimestampDelta) external {\\n _checkAccessAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n require(_newReduceReservesBlockOrTimestampDelta > 0, \\\"Invalid Input\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, _newReduceReservesBlockOrTimestampDelta);\\n reduceReservesBlockDelta = _newReduceReservesBlockOrTimestampDelta;\\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 amount 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 amount 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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return vTokenBalance User's balance of vTokens\\n * @return borrowBalance Amount owed in terms of underlying\\n * @return exchangeRate Stored exchange rate\\n */\\n function getAccountSnapshot(\\n address account\\n )\\n external\\n view\\n override\\n returns (uint256 error, uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRate)\\n {\\n return (NO_ERROR, accountTokens[account], _borrowBalanceStored(account), _exchangeRateStored());\\n }\\n\\n /**\\n * @notice Get the internally tracked cash balance of this vToken in the underlying asset\\n * @return cash The quantity of underlying asset tracked internally by this contract\\n */\\n function getCash() external view override returns (uint256) {\\n return _getCashPrior();\\n }\\n\\n /**\\n * @notice Returns the current per slot(block or second) borrow interest rate for this vToken\\n * @return rate The borrow interest rate per slot(block or second), scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint256) {\\n return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt);\\n }\\n\\n /**\\n * @notice Returns the current per-slot(block or second) supply interest rate for this v\\n * @return rate The supply interest rate per slot(block or second), scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint256) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPrior(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa,\\n badDebt\\n );\\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 borrowBalance The calculated balance\\n */\\n function borrowBalanceStored(address account) external view override returns (uint256) {\\n return _borrowBalanceStored(account);\\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 exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() external view override returns (uint256) {\\n return _exchangeRateStored();\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\\n accrueInterest();\\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 slot(block or second)\\n * up to the current slot(block or second) and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentSlot - reduceReservesBlockNumber >= slotDelta\\n * @return Always NO_ERROR\\n * @custom:event Emits AccrueInterest event on success\\n * @custom:access Not restricted\\n */\\n function accrueInterest() public virtual override returns (uint256) {\\n /* Remember the initial block number or timestamp */\\n uint256 currentSlotNumber = getBlockNumberOrTimestamp();\\n uint256 accrualSlotNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualSlotNumberPrior == currentSlotNumber) {\\n return NO_ERROR;\\n }\\n\\n /* Read the previous values out of storage */\\n uint256 cashPrior = _getCashPrior();\\n uint256 borrowsPrior = totalBorrows;\\n uint256 reservesPrior = totalReserves;\\n uint256 borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt);\\n require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of slots elapsed since the last accrual */\\n uint256 slotDelta = currentSlotNumber - accrualSlotNumberPrior;\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * slotDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), slotDelta);\\n uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\\n uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;\\n uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentSlotNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n if (currentSlotNumber - reduceReservesBlockNumber >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentSlotNumber;\\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 NO_ERROR;\\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 or timestamp\\n * @param payer The address of the account which is sending the assets for supply\\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 */\\n function _mintFresh(address payer, address minter, uint256 mintAmount) internal {\\n /* Fail if mint not allowed */\\n comptroller.preMintHook(address(this), minter, mintAmount);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert MintFreshnessCheck();\\n }\\n\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\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 * `_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 uint256 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 uint256 mintTokens = div_(actualMintAmount, exchangeRate);\\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 * And write them into storage\\n */\\n totalSupply = totalSupply + mintTokens;\\n uint256 balanceAfter = accountTokens[minter] + mintTokens;\\n accountTokens[minter] = balanceAfter;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, actualMintAmount, mintTokens, balanceAfter);\\n emit Transfer(address(0), minter, mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, actualMintAmount, mintTokens);\\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 Comptroller.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current slot(block or second)\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the underlying 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 */\\n function _redeemFresh(address redeemer, address receiver, uint256 redeemTokensIn, uint256 redeemAmountIn) internal {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert RedeemFreshnessCheck();\\n }\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n\\n uint256 redeemTokens;\\n uint256 redeemAmount;\\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 */\\n redeemTokens = redeemTokensIn;\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n */\\n redeemTokens = div_(redeemAmountIn, exchangeRate);\\n\\n uint256 _redeemAmount = mul_(redeemTokens, exchangeRate);\\n if (_redeemAmount != 0 && _redeemAmount != redeemAmountIn) redeemTokens++; // round up\\n }\\n\\n // redeemAmount = exchangeRate * redeemTokens\\n redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokens);\\n\\n // Revert if amount is zero\\n if (redeemAmount == 0) {\\n revert(\\\"redeemAmount is zero\\\");\\n }\\n\\n /* Fail if redeem not allowed */\\n comptroller.preRedeemHook(address(this), redeemer, redeemTokens);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (_getCashPrior() - totalReserves < redeemAmount) {\\n revert RedeemTransferOutNotPossible();\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\\n */\\n totalSupply = totalSupply - redeemTokens;\\n uint256 balanceAfter = accountTokens[redeemer] - redeemTokens;\\n accountTokens[redeemer] = balanceAfter;\\n\\n /*\\n * We invoke _doTransferOut for the receiver and the redeemAmount.\\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 _doTransferOut(receiver, redeemAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), redeemTokens);\\n emit Redeem(redeemer, redeemAmount, redeemTokens, balanceAfter);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, redeemAmount, redeemTokens);\\n }\\n\\n /**\\n * @notice Users or their delegates borrow assets from the protocol\\n * @param borrower User who borrows the assets\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param borrowAmount The amount of the underlying asset to borrow\\n */\\n function _borrowFresh(address borrower, address receiver, uint256 borrowAmount) internal {\\n /* Fail if borrow not allowed */\\n comptroller.preBorrowHook(address(this), borrower, borrowAmount);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert BorrowFreshnessCheck();\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (_getCashPrior() - totalReserves < borrowAmount) {\\n revert BorrowCashNotAvailable();\\n }\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowNew = accountBorrow + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;\\n uint256 totalBorrowsNew = totalBorrows + borrowAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\\n `*/\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /*\\n * We invoke _doTransferOut for the receiver and the borrowAmount.\\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, accountBorrowsNew, totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\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 underlying tokens being returned, or type(uint256).max for the full outstanding amount\\n * @return (uint) the actual repayment amount.\\n */\\n function _repayBorrowFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256) {\\n /* Fail if repayBorrow not allowed */\\n comptroller.preRepayHook(address(this), borrower);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert RepayBorrowFreshnessCheck();\\n }\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n\\n uint256 repayAmountFinal = repayAmount >= accountBorrowsPrev ? accountBorrowsPrev : 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 * 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 uint256 actualRepayAmount = _doTransferIn(payer, repayAmountFinal);\\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 uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\\n uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, actualRepayAmount, borrowIndex);\\n\\n return actualRepayAmount;\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal nonReentrant {\\n accrueInterest();\\n\\n uint256 error = vTokenCollateral.accrueInterest();\\n if (error != NO_ERROR) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n revert LiquidateAccrueCollateralInterestFailed(error);\\n }\\n\\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal {\\n /* Fail if liquidate not allowed */\\n comptroller.preLiquidateHook(\\n address(this),\\n address(vTokenCollateral),\\n borrower,\\n repayAmount,\\n skipLiquidityCheck\\n );\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert LiquidateFreshnessCheck();\\n }\\n\\n /* Verify vTokenCollateral market's slot(block or second) number equals current slot(block or second) number */\\n if (vTokenCollateral.accrualBlockNumber() != getBlockNumberOrTimestamp()) {\\n revert LiquidateCollateralFreshnessCheck();\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateLiquidatorIsBorrower();\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n revert LiquidateCloseAmountIsZero();\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n revert LiquidateCloseAmountIsUintMax();\\n }\\n\\n /* Fail if repayBorrow fails */\\n uint256 actualRepayAmount = _repayBorrowFresh(liquidator, borrower, repayAmount);\\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.liquidateCalculateSeizeTokens(\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n require(amountSeizeError == 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, call _seize internally to avoid re-entrancy, otherwise make an external call\\n if (address(vTokenCollateral) == address(this)) {\\n _seize(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\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\\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 * It's absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerContract The contract seizing the collateral (either borrowed vToken or Comptroller)\\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 */\\n function _seize(address seizerContract, address liquidator, address borrower, uint256 seizeTokens) internal {\\n /* Fail if seize not allowed */\\n comptroller.preSeizeHook(address(this), seizerContract, liquidator, borrower);\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateSeizeLiquidatorIsBorrower();\\n }\\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 uint256 liquidationIncentiveMantissa = ComptrollerViewInterface(address(comptroller))\\n .liquidationIncentiveMantissa();\\n uint256 numerator = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));\\n uint256 protocolSeizeTokens = div_(numerator, Exp({ mantissa: liquidationIncentiveMantissa }));\\n uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n uint256 protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the calculated values into storage */\\n totalSupply = totalSupply - protocolSeizeTokens;\\n accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\\n accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\\n\\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, protocolSeizeAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.LIQUIDATION\\n );\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\\n emit ProtocolSeize(borrower, protocolShareReserve, protocolSeizeAmount);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerContract, liquidator, borrower, seizeTokens);\\n }\\n\\n function _setComptroller(ComptrollerInterface newComptroller) internal {\\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\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n */\\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal {\\n // Verify market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert SetReserveFactorFreshCheck();\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > MAX_RESERVE_FACTOR_MANTISSA) {\\n revert SetReserveFactorBoundsCheck();\\n }\\n\\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\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 actualAddAmount The actual amount added, excluding the potential token fees\\n */\\n function _addReservesFresh(uint256 addAmount) internal returns (uint256) {\\n // totalReserves + actualAddAmount\\n uint256 totalReservesNew;\\n uint256 actualAddAmount;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert AddReservesFactorFreshCheck(actualAddAmount);\\n }\\n\\n actualAddAmount = _doTransferIn(msg.sender, addAmount);\\n totalReservesNew = totalReserves + actualAddAmount;\\n totalReserves = totalReservesNew;\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n return actualAddAmount;\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to the protocol reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n */\\n function _reduceReservesFresh(uint256 reduceAmount) internal {\\n if (reduceAmount == 0) {\\n return;\\n }\\n // totalReserves - reduceAmount\\n uint256 totalReservesNew;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert ReduceReservesFreshCheck();\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (_getCashPrior() < reduceAmount) {\\n revert ReduceReservesCashNotAvailable();\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n revert ReduceReservesCashValidation();\\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 // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, reduceAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit SpreadReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal {\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert SetInterestRateModelFreshCheck();\\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\\n /**\\n * Safe Token **\\n */\\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 returns (uint256) {\\n IERC20Upgradeable token = IERC20Upgradeable(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 * @param to Receiver of the underlying tokens\\n * @param amount Amount of underlying to transfer\\n */\\n function _doTransferOut(address to, uint256 amount) internal virtual {\\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\\n internalCash -= amount;\\n token.safeTransfer(to, amount);\\n }\\n\\n /**\\n * @notice Transfer `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 */\\n function _transferTokens(address spender, address src, address dst, uint256 tokens) internal {\\n /* Fail if transfer not allowed */\\n comptroller.preTransferHook(address(this), src, dst, tokens);\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n revert TransferNotAllowed();\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint256 startingAllowance;\\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 uint256 allowanceNew = startingAllowance - tokens;\\n uint256 srcTokensNew = accountTokens[src] - tokens;\\n uint256 dstTokensNew = accountTokens[dst] + tokens;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n\\n accountTokens[src] = srcTokensNew;\\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\\n /**\\n * @notice Initialize the 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_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n */\\n function _initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\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 _setComptroller(comptroller_);\\n\\n // Initialize slot(block or second) number and borrow index (slot(block or second) number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumberOrTimestamp();\\n borrowIndex = MANTISSA_ONE;\\n\\n // Set the interest rate model (depends on slot(block or second) number / borrow index)\\n _setInterestRateModelFresh(interestRateModel_);\\n\\n _setReserveFactorFresh(reserveFactorMantissa_);\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n _setShortfallContract(riskManagement.shortfall);\\n _setProtocolShareReserve(riskManagement.protocolShareReserve);\\n protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA;\\n\\n // Set underlying and sanity check it\\n underlying = underlying_;\\n IERC20Upgradeable(underlying).totalSupply();\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n _transferOwnership(admin_);\\n }\\n\\n function _setShortfallContract(address shortfall_) internal {\\n ensureNonzeroAddress(shortfall_);\\n address oldShortfall = shortfall;\\n shortfall = shortfall_;\\n emit NewShortfallContract(oldShortfall, shortfall_);\\n }\\n\\n function _setProtocolShareReserve(address payable protocolShareReserve_) internal {\\n ensureNonzeroAddress(protocolShareReserve_);\\n address oldProtocolShareReserve = address(protocolShareReserve);\\n protocolShareReserve = protocolShareReserve_;\\n emit NewProtocolShareReserve(oldProtocolShareReserve, address(protocolShareReserve_));\\n }\\n\\n function _ensureSenderIsDelegateOf(address user) internal view {\\n if (!ComptrollerViewInterface(address(comptroller)).approvedDelegates(user, msg.sender)) {\\n revert DelegateNotApproved();\\n }\\n }\\n\\n /**\\n * @notice Gets the internally tracked cash balance of this market\\n * @dev Returns the internalCash state variable, which is updated on transfers in/out\\n * @return The quantity of underlying tokens tracked internally by this contract\\n */\\n function _getCashPrior() internal view virtual returns (uint256) {\\n return internalCash;\\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 borrowBalance the calculated balance\\n */\\n function _borrowBalanceStored(address account) internal view returns (uint256) {\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot memory 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 0;\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;\\n\\n return principalTimesIndex / borrowSnapshot.interestIndex;\\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 exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function _exchangeRateStored() internal view virtual returns (uint256) {\\n uint256 _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return initialExchangeRateMantissa;\\n }\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply\\n */\\n uint256 totalCash = _getCashPrior();\\n uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;\\n uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply;\\n\\n return exchangeRate;\\n }\\n}\\n\",\"keccak256\":\"0x7267f5337062ad01a5011f7725a86cc2ad0351cca0aaceadc167341f168cdef2\",\"license\":\"BSD-3-Clause\"},\"contracts/VTokenInterfaces.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\\nimport { ComptrollerInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title VTokenStorage\\n * @author Venus\\n * @notice Storage layout used by the `VToken` contract\\n */\\n// solhint-disable-next-line max-states-count\\ncontract VTokenStorage {\\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 uint256 principal;\\n uint256 interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\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 Protocol share Reserve contract address\\n */\\n address payable public protocolShareReserve;\\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 InterestRateModel public interestRateModel;\\n\\n // Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n uint256 internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint256 public reserveFactorMantissa;\\n\\n /**\\n * @notice Slot(block or second) number that interest was last accrued at\\n */\\n uint256 public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint256 public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint256 public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint256 public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint256 public totalSupply;\\n\\n /**\\n * @notice Total bad debt of the market\\n */\\n uint256 public badDebt;\\n\\n // Official record of token balances for each account\\n mapping(address => uint256) internal accountTokens;\\n\\n // Approved token transfer amounts on behalf of others\\n mapping(address => mapping(address => uint256)) internal transferAllowances;\\n\\n // Mapping of account addresses to outstanding borrow balances\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint256 public protocolSeizeShareMantissa;\\n\\n /**\\n * @notice Storage of Shortfall contract address\\n */\\n address public shortfall;\\n\\n /**\\n * @notice delta slot (block or second) after which reserves will be reduced\\n */\\n uint256 public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last slot (block or second) number at which reserves were reduced\\n */\\n uint256 public reduceReservesBlockNumber;\\n\\n /**\\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\\n * @dev Updated via _doTransferIn(), _doTransferOut(), syncCash(), and badDebtRecovered(). Must be initialized via syncCash() 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[47] private __gap;\\n}\\n\\n/**\\n * @title VTokenInterface\\n * @author Venus\\n * @notice Interface implemented by the `VToken` contract\\n */\\nabstract contract VTokenInterface is VTokenStorage {\\n struct RiskManagementInit {\\n address shortfall;\\n address payable protocolShareReserve;\\n }\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address indexed minter, uint256 mintAmount, uint256 mintTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address indexed borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(\\n address indexed payer,\\n address indexed borrower,\\n uint256 repayAmount,\\n uint256 accountBorrows,\\n uint256 totalBorrows\\n );\\n\\n /**\\n * @notice Event emitted when bad debt is accumulated on a market\\n * @param borrower borrower to \\\"forgive\\\"\\n * @param badDebtDelta amount of new bad debt recorded\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtIncreased(address indexed borrower, uint256 badDebtDelta, uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when bad debt is recovered via an auction\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtRecovered(uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address indexed liquidator,\\n address indexed borrower,\\n uint256 repayAmount,\\n address indexed vTokenCollateral,\\n uint256 seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface indexed oldComptroller, ComptrollerInterface indexed newComptroller);\\n\\n /**\\n * @notice Event emitted when shortfall contract address is changed\\n */\\n event NewShortfallContract(address indexed oldShortfall, address indexed newShortfall);\\n\\n /**\\n * @notice Event emitted when protocol share reserve contract address is changed\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModel indexed oldInterestRateModel,\\n InterestRateModel indexed newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when protocol seize share is changed\\n */\\n event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address indexed benefactor, uint256 addAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the spread reserves are reduced\\n */\\n event SpreadReservesReduced(address indexed protocolShareReserve, uint256 reduceAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /**\\n * @notice Event emitted when healing the borrow\\n */\\n event HealBorrow(address indexed payer, address indexed borrower, uint256 repayAmount);\\n\\n /**\\n * @notice Event emitted when tokens are swept\\n */\\n event SweepToken(address indexed token);\\n\\n /**\\n * @notice Event emitted when reduce reserves slot (block or second) delta is changed\\n */\\n event NewReduceReservesBlockDelta(\\n uint256 oldReduceReservesBlockOrTimestampDelta,\\n uint256 newReduceReservesBlockOrTimestampDelta\\n );\\n\\n /**\\n * @notice Event emitted when liquidation reserves are reduced\\n */\\n event ProtocolSeize(address indexed from, address indexed to, uint256 amount);\\n\\n /**\\n * @notice Event emitted when internalCash is synced with actual token balance\\n */\\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\\n\\n /*** User Interface ***/\\n\\n function mint(uint256 mintAmount) external virtual returns (uint256);\\n\\n function mintBehalf(address minter, uint256 mintAllowed) external virtual returns (uint256);\\n\\n function redeem(uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemBehalf(address redeemer, uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);\\n\\n function redeemUnderlyingBehalf(address redeemer, uint256 redeemAmount) external virtual returns (uint256);\\n\\n function borrow(uint256 borrowAmount) external virtual returns (uint256);\\n\\n function borrowBehalf(address borrwwer, uint256 borrowAmount) external virtual returns (uint256);\\n\\n function repayBorrow(uint256 repayAmount) external virtual returns (uint256);\\n\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external virtual returns (uint256);\\n\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external virtual;\\n\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipCloseFactorCheck\\n ) external virtual;\\n\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external virtual;\\n\\n function transfer(address dst, uint256 amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint256 amount) external virtual returns (bool);\\n\\n function accrueInterest() external virtual returns (uint256);\\n\\n function sweepToken(IERC20Upgradeable token) external virtual;\\n\\n /*** Admin Functions ***/\\n\\n function setReserveFactor(uint256 newReserveFactorMantissa) external virtual;\\n\\n function reduceReserves(uint256 reduceAmount) external virtual;\\n\\n function exchangeRateCurrent() external virtual returns (uint256);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint256);\\n\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external virtual;\\n\\n function addReserves(uint256 addAmount) external virtual;\\n\\n function syncCash() external virtual;\\n\\n function totalBorrowsCurrent() external virtual returns (uint256);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint256);\\n\\n function approve(address spender, uint256 amount) external virtual returns (bool);\\n\\n function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool);\\n\\n function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint256);\\n\\n function balanceOf(address owner) external view virtual returns (uint256);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint256, uint256, uint256, uint256);\\n\\n function borrowRatePerBlock() external view virtual returns (uint256);\\n\\n function supplyRatePerBlock() external view virtual returns (uint256);\\n\\n function borrowBalanceStored(address account) external view virtual returns (uint256);\\n\\n function exchangeRateStored() external view virtual returns (uint256);\\n\\n function getCash() external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is a VToken contract (for inspection)\\n * @return Always true\\n */\\n function isVToken() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x155684e9cb12cdd8be63d2314c9452b68ee44ff98a00e0d65cd1fd7d0bdd4391\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\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\",\"keccak256\":\"0x54ab3a6f3bc87569ed12370f3470a1ec84cea9796d4d0ccf3d07dd4280c044aa\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/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 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\",\"keccak256\":\"0x93bdd5cfb100f0f9a1d446857e23c3633df6ab12c266333c978428edd96b1367\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x61010060405234801561001157600080fd5b50604051614176380380614176833981016040819052610030916100e9565b82828115801561003e575080155b1561005c576040516302723dfb60e21b815260040160405180910390fd5b81801561006857508015155b156100865760405163ae0fcab360e01b815260040160405180910390fd5b81151560a05281610097578061009d565b6301e133805b608052816100b4576100e160201b611d0c176100bf565b6100e560201b611d10175b6001600160401b031660c05250506001600160a01b031660e0525061013d9050565b4390565b4290565b6000806000606084860312156100fe57600080fd5b8351801515811461010e57600080fd5b6020850151604086015191945092506001600160a01b038116811461013257600080fd5b809150509250925092565b60805160a05160c05160e051613ff2610184600039600081816102e80152611d8201526000611ce00152600081816102b10152611f80015260006101dc0152613ff26000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c80637c51b642116100a2578063c7ad089511610071578063c7ad0895146102ac578063d26998e9146102e3578063d77ebf961461030a578063e0a67f111461032a578063e1d146fb1461034a57600080fd5b80637c51b6421461022c5780637c84e3b31461024c578063aa5dbd231461026c578063b31242391461028c57600080fd5b806347d86a81116100de57806347d86a811461019957806355dd9515146101ac5780636857249c146101d75780637a27db571461020c57600080fd5b80630d3ae318146101105780631f884fdf14610139578063345954dc146101595780633e3e399c14610179575b600080fd5b61012361011e366004612ff0565b610352565b604051610130919061335d565b60405180910390f35b61014c6101473660046133bb565b610626565b60405161013091906133fc565b61016c61016736600461345c565b6106ee565b6040516101309190613479565b61018c61018736600461345c565b610821565b60405161013091906134dd565b6101236101a7366004613567565b610b30565b6101bf6101ba3660046135a0565b610bb7565b6040516001600160a01b039091168152602001610130565b6101fe7f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610130565b61021f61021a366004613567565b610c37565b60405161013091906135eb565b61023f61023a3660046136c7565b610ee7565b6040516101309190613752565b61025f61025a36600461345c565b610fa0565b60405161013091906137a0565b61027f61027a36600461345c565b61110a565b60405161013091906137c0565b61029f61029a366004613567565b6118ca565b60405161013091906137cf565b6102d37f000000000000000000000000000000000000000000000000000000000000000081565b6040519015158152602001610130565b6101bf7f000000000000000000000000000000000000000000000000000000000000000081565b61031d610318366004613567565b611bb1565b60405161013091906137dd565b61033d610338366004613841565b611c24565b60405161013091906138da565b6101fe611cd9565b61035a612db7565b6040820151600061036a82611d14565b9050600061037782611c24565b60408681015190516328ebbe8b60e21b81526001600160a01b039182166004820152919250879160009183169063a3aefa2c90602401600060405180830381865afa1580156103ca573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526103f29190810190613962565b90506000876040015190506000604051806101a001604052808a6000015181526020018a602001516001600160a01b031681526020018a604001516001600160a01b031681526020018a6060015181526020018a608001518152602001846000015181526020018460200151815260200184604001518152602001836001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104cf9190613a16565b6001600160a01b03168152602001836001600160a01b031663e87554466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561051b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053f9190613a33565b8152602001836001600160a01b0316634ada90af6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610582573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105a69190613a33565b8152602001836001600160a01b031663db5c65de6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060d9190613a33565b8152602001959095525092955050505050505b92915050565b6060816000816001600160401b0381111561064357610643612f39565b60405190808252806020026020018201604052801561068857816020015b60408051808201909152600080825260208201528152602001906001900390816106615790505b50905060005b828110156106e5576106c08686838181106106ab576106ab613a4c565b905060200201602081019061025a919061345c565b8282815181106106d2576106d2613a4c565b602090810291909101015260010161068e565b50949350505050565b606060008290506000816001600160a01b031663d88ff1f46040518163ffffffff1660e01b8152600401600060405180830381865afa158015610735573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261075d9190810190613ae5565b80519091506000816001600160401b0381111561077c5761077c612f39565b6040519080825280602002602001820160405280156107b557816020015b6107a2612db7565b81526020019060019003908161079a5790505b50905060005b828110156108175760008482815181106107d7576107d7613a4c565b6020026020010151905060006107ed8983610352565b90508084848151811061080257610802613a4c565b602090810291909101015250506001016107bb565b5095945050505050565b60408051606080820183526000808352602083018190529282015290828161084882611d14565b90506000826001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561088a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ae9190613a16565b9050600082516001600160401b038111156108cb576108cb612f39565b60405190808252806020026020018201604052801561091057816020015b60408051808201909152600080825260208201528152602001906001900390816108e95790505b509050610940604051806060016040528060006001600160a01b0316815260200160008152602001606081525090565b6001600160a01b03881681526040810182905260005b8451811015610b1c57604080518082019091526000808252602082015285828151811061098557610985613a4c565b602002602001015181600001906001600160a01b031690816001600160a01b031681525050670de0b6b3a7640000856001600160a01b031663fc57d4df8885815181106109d4576109d4613a4c565b60200260200101516040518263ffffffff1660e01b8152600401610a0791906001600160a01b0391909116815260200190565b602060405180830381865afa158015610a24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a489190613a33565b878481518110610a5a57610a5a613a4c565b60200260200101516001600160a01b031663bbcac5576040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac39190613a33565b610acd9190613bab565b610ad79190613bc2565b60208201526040830151805182919084908110610af657610af6613a4c565b6020026020010181905250806020015188610b119190613be4565b975050600101610956565b506020810195909552509295945050505050565b610b38612db7565b604051637aee632d60e01b81526001600160a01b0383811660048301528491610baf91839190821690637aee632d90602401600060405180830381865afa158015610b87573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261011e9190810190613bf7565b949350505050565b60405163266e0a7f60e01b81526001600160a01b0383811660048301528281166024830152600091859182169063266e0a7f90604401602060405180830381865afa158015610c0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2e9190613a16565b95945050505050565b60606000610c4483611d14565b90506000836001600160a01b03166361252fd16040518163ffffffff1660e01b8152600401600060405180830381865afa158015610c86573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cae9190810190613c2b565b9050600081516001600160401b03811115610ccb57610ccb612f39565b604051908082528060200260200182016040528015610d1c57816020015b6040805160808101825260008082526020808301829052928201526060808201528252600019909201910181610ce95790505b50905060005b8251811015610817576040805160808101825260008082526020820181905291810191909152606080820152838281518110610d6057610d60613a4c565b60209081029190910101516001600160a01b031681528351849083908110610d8a57610d8a613a4c565b60200260200101516001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dcf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df39190613a16565b6001600160a01b031660208201528351849083908110610e1557610e15613a4c565b6020908102919091010151604051631627ee8960e01b81526001600160a01b038a8116600483015290911690631627ee8990602401602060405180830381865afa158015610e67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8b9190613a33565b816040018181525050610eb88886868581518110610eab57610eab613a4c565b6020026020010151611eb3565b816060018190525080838381518110610ed357610ed3613a4c565b602090810291909101015250600101610d22565b6060826000816001600160401b03811115610f0457610f04612f39565b604051908082528060200260200182016040528015610f3d57816020015b610f2a612e3a565b815260200190600190039081610f225790505b50905060005b8281101561081757610f7b878783818110610f6057610f60613a4c565b9050602002016020810190610f75919061345c565b866118ca565b828281518110610f8d57610f8d613a4c565b6020908102919091010152600101610f43565b60408051808201909152600080825260208201526000826001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ff4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110189190613a16565b90506000816001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561105a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061107e9190613a16565b6040805180820182526001600160a01b03808816808352925163fc57d4df60e01b815260048101939093529293509160208301919084169063fc57d4df90602401602060405180830381865afa1580156110dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111009190613a33565b9052949350505050565b611112612e79565b6000826001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611152573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111769190613a33565b90506000836001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111dc9190613a16565b604051638e8f294b60e01b81526001600160a01b03868116600483015291925082916000918291841690638e8f294b906024016040805180830381865afa15801561122b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061124f9190613cc9565b915091506000876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611293573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b79190613a16565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061131d9190613cf5565b60ff1690506000805b600860ff8216116113e3576000886001600160a01b031663e85a29608d8460ff16600881111561135857611358613d18565b6040518363ffffffff1660e01b8152600401611375929190613d2e565b602060405180830381865afa158015611392573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b69190613d69565b6113c15760006113c4565b60015b60ff9081169083161b9290921791506113dc81613d84565b9050611326565b506000808b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611425573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114499190613a33565b11156114b4578a6001600160a01b031663ae9d70b06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561148d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114b19190613a33565b90505b6040518061022001604052808c6001600160a01b031681526020018a81526020018281526020018c6001600160a01b031663f8f9da286040518163ffffffff1660e01b8152600401602060405180830381865afa158015611519573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153d9190613a33565b81526020018c6001600160a01b031663173b99046040518163ffffffff1660e01b8152600401602060405180830381865afa158015611580573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a49190613a33565b81526040516302c3bcbb60e01b81526001600160a01b038e811660048301526020909201918a16906302c3bcbb90602401602060405180830381865afa1580156115f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116169190613a33565b815260405163252c221960e11b81526001600160a01b038e811660048301526020909201918a1690634a58443290602401602060405180830381865afa158015611664573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116889190613a33565b81526020018c6001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ef9190613a33565b81526020018c6001600160a01b0316638f840ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611732573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117569190613a33565b81526020018c6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611799573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117bd9190613a33565b81526020018c6001600160a01b0316633b1d21a26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611800573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118249190613a33565b81526020018715158152602001868152602001856001600160a01b031681526020018c6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611884573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118a89190613cf5565b60ff168152602001848152602001838152509950505050505050505050919050565b6118d2612e3a565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908516906370a0823190602401602060405180830381865afa15801561191c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119409190613a33565b6040516305eff7ef60e21b81526001600160a01b0385811660048301529192506000918616906317bfdfbc906024016020604051808303816000875af115801561198e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b29190613a33565b604051633af9e66960e01b81526001600160a01b038681166004830152919250600091871690633af9e669906024016020604051808303816000875af1158015611a00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a249190613a33565b90506000806000886001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a8d9190613a16565b6040516370a0823160e01b81526001600160a01b038a81166004830152919250908216906370a0823190602401602060405180830381865afa158015611ad7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611afb9190613a33565b604051636eb1769f60e11b81526001600160a01b038a811660048301528b811660248301529194509082169063dd62ed3e90604401602060405180830381865afa158015611b4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b719190613a33565b6040805160c0810182526001600160a01b038c168152602081019890985287019590955250506060840191909152608083015260a0820152905092915050565b604051631e6db74760e31b81526001600160a01b038281166004830152606091849182169063f36dba3890602401600060405180830381865afa158015611bfc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610baf9190810190613da3565b80516060906000816001600160401b03811115611c4357611c43612f39565b604051908082528060200260200182016040528015611c7c57816020015b611c69612e79565b815260200190600190039081611c615790505b50905060005b82811015611cd157611cac858281518110611c9f57611c9f613a4c565b602002602001015161110a565b828281518110611cbe57611cbe613a4c565b6020908102919091010152600101611c82565b509392505050565b6000611d077f000000000000000000000000000000000000000000000000000000000000000063ffffffff16565b905090565b4390565b4290565b60606000826001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015611d56573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d7e9190810190613e31565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031603611dbf5792915050565b8051600090815b81811015611ea9576000848281518110611de257611de2613a4c565b60200260200101516001600160a01b03166322abdbf56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e4b9190613a33565b1115611ea157838181518110611e6357611e63613a4c565b6020026020010151848481518110611e7d57611e7d613a4c565b6001600160a01b0390921660209283029190910190910152611e9e83613ebf565b92505b600101611dc6565b5050815292915050565b6060600083516001600160401b03811115611ed057611ed0612f39565b604051908082528060200260200182016040528015611f1557816020015b6040805180820190915260008082526020820152815260200190600190039081611eee5790505b50905060005b84518110156106e557611f51604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b611f7e604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b7f00000000000000000000000000000000000000000000000000000000000000001561210157856001600160a01b0316638f693ec7888581518110611fc557611fc5613a4c565b60200260200101516040518263ffffffff1660e01b8152600401611ff891906001600160a01b0391909116815260200190565b606060405180830381865afa158015612015573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120399190613eef565b604085015260208401526001600160e01b0316825286516001600160a01b0387169063818149459089908690811061207357612073613a4c565b60200260200101516040518263ffffffff1660e01b81526004016120a691906001600160a01b0391909116815260200190565b606060405180830381865afa1580156120c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e79190613eef565b604084015260208301526001600160e01b0316815261226c565b856001600160a01b0316632c427b5788858151811061212257612122613a4c565b60200260200101516040518263ffffffff1660e01b815260040161215591906001600160a01b0391909116815260200190565b606060405180830381865afa158015612172573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121969190613f38565b63ffffffff90811660408601521660208401526001600160e01b0316825286516001600160a01b038716906392a18235908990869081106121d9576121d9613a4c565b60200260200101516040518263ffffffff1660e01b815260040161220c91906001600160a01b0391909116815260200190565b606060405180830381865afa158015612229573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061224d9190613f38565b63ffffffff90811660408501521660208301526001600160e01b031681525b6000604051806020016040528089868151811061228b5761228b613a4c565b60200260200101516001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122f49190613a33565b815250905061231e88858151811061230e5761230e613a4c565b6020026020010151888584612413565b61234288858151811061233357612333613a4c565b60200260200101518884612614565b600061236a89868151811061235957612359613a4c565b6020026020010151898c878661280b565b905060006123938a878151811061238357612383613a4c565b60200260200101518a8d87612a3b565b60408051808201909152600080825260208201529091508a87815181106123bc576123bc613a4c565b60209081029190910101516001600160a01b031681526123dc8284613be4565b6020820152875181908990899081106123f7576123f7613a4c565b6020026020010181905250505050505050806001019050611f1b565b604051637c05a7c560e01b81526001600160a01b03858116600483015260009190851690637c05a7c590602401602060405180830381865afa15801561245d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124819190613a33565b9050600061248d611cd9565b9050600084604001511180156124a65750836040015181115b156124b2575060408301515b60006124c2828660200151612c5f565b90506000811180156124d45750600083115b156125fd576000612546886001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561251c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125409190613a33565b86612c72565b905060006125548386612c90565b90506000808311612574576040518060200160405280600081525061257e565b61257e8284612c9c565b905060006125a760405180602001604052808b600001516001600160e01b031681525083612ce1565b90506125e28160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612d0d565b6001600160e01b03168952505050506020850182905261260b565b801561260b57602085018290525b50505050505050565b604051631d31307360e21b81526001600160a01b038481166004830152600091908416906374c4c1cc90602401602060405180830381865afa15801561265e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126829190613a33565b9050600061268e611cd9565b9050600083604001511180156126a75750826040015181115b156126b3575060408201515b60006126c3828560200151612c5f565b90506000811180156126d55750600083115b156127f5576000866001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561271a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061273e9190613a33565b9050600061274c8386612c90565b9050600080831161276c5760405180602001604052806000815250612776565b6127768284612c9c565b9050600061279f60405180602001604052808a600001516001600160e01b031681525083612ce1565b90506127da8160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612d0d565b6001600160e01b031688525050505060208401829052612803565b801561280357602084018290525b505050505050565b604080516020808201835284516001600160e01b031682528251908101928390526336fe846560e11b9092526001600160a01b0387811660248401528581166044840152600092839181908916636dfd08ca60648301602060405180830381865afa15801561287e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a29190613a33565b905280519091501580156129245750866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129139190613f7b565b6001600160e01b0316826000015110155b1561299757866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061298b9190613f7b565b6001600160e01b031681525b60006129a38383612d49565b6040516395dd919360e01b81526001600160a01b038981166004830152919250600091612a1e91908c16906395dd919390602401602060405180830381865afa1580156129f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a189190613a33565b87612c72565b90506000612a2c8284612d75565b9b9a5050505050505050505050565b604080516020808201835283516001600160e01b0316825282519081019283905263552c097160e01b9092526001600160a01b038681166024840152848116604484015260009283918190881663552c097160648301602060405180830381865afa158015612aae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ad29190613a33565b90528051909150158015612b545750856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b439190613f7b565b6001600160e01b0316826000015110155b15612bc757856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bbb9190613f7b565b6001600160e01b031681525b6000612bd38383612d49565b6040516370a0823160e01b81526001600160a01b0388811660048301529192506000918a16906370a0823190602401602060405180830381865afa158015612c1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c439190613a33565b90506000612c518284612d75565b9a9950505050505050505050565b6000612c6b8284613f96565b9392505050565b6000612c6b612c8984670de0b6b3a7640000612c90565b8351612d9f565b6000612c6b8284613bab565b6040805160208101909152600081526040518060200160405280612cd8612cd2866ec097ce7bc90715b34b9f1000000000612c90565b85612d9f565b90529392505050565b6040805160208101909152600081526040518060200160405280612cd885600001518560000151612dab565b6000816001600160e01b03841115612d415760405162461bcd60e51b8152600401612d389190613fa9565b60405180910390fd5b509192915050565b6040805160208101909152600081526040518060200160405280612cd885600001518560000151612c5f565b60006ec097ce7bc90715b34b9f1000000000612d95848460000151612c90565b612c6b9190613bc2565b6000612c6b8284613bc2565b6000612c6b8284613be4565b604051806101a001604052806060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160608152602001606081526020016060815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001606081525090565b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180610220016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b6001600160a01b0381168114612f2657600080fd5b50565b8035612f3481612f11565b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715612f7157612f71612f39565b60405290565b604051606081016001600160401b0381118282101715612f7157612f71612f39565b604051601f8201601f191681016001600160401b0381118282101715612fc157612fc1612f39565b604052919050565b60006001600160401b03821115612fe257612fe2612f39565b50601f01601f191660200190565b6000806040838503121561300357600080fd5b823561300e81612f11565b91506020838101356001600160401b038082111561302b57600080fd5b9085019060a0828803121561303f57600080fd5b613047612f4f565b82358281111561305657600080fd5b83019150601f8201881361306957600080fd5b813561307c61307782612fc9565b612f99565b818152898683860101111561309057600080fd5b8186850187830137600086838301015280835250506130b0848401612f29565b848201526130c060408401612f29565b60408201526060830135606082015260808301356080820152809450505050509250929050565b60005b838110156131025781810151838201526020016130ea565b50506000910152565b600081518084526131238160208601602086016130e7565b601f01601f19169290920160200192915050565b80516001600160a01b031682526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e0830152610100808201518184015250610120808201518184015250610140808201518184015250610160808201516131c28285018215159052565b505061018081810151908301526101a0808201516001600160a01b0316908301526101c080820151908301526101e0808201519083015261020090810151910152565b60008151808452602080850194506020840160005b838110156132415761322d878351613137565b61022096909601959082019060010161321a565b509495945050505050565b60006101a082518185526132628286018261310b565b915050602083015161327f60208601826001600160a01b03169052565b50604083015161329a60408601826001600160a01b03169052565b50606083015160608501526080830151608085015260a083015184820360a08601526132c6828261310b565b91505060c083015184820360c08601526132e0828261310b565b91505060e083015184820360e08601526132fa828261310b565b91505061010080840151613318828701826001600160a01b03169052565b505061012083810151908501526101408084015190850152610160808401519085015261018080840151858303828701526133538382613205565b9695505050505050565b602081526000612c6b602083018461324c565b60008083601f84011261338257600080fd5b5081356001600160401b0381111561339957600080fd5b6020830191508360208260051b85010111156133b457600080fd5b9250929050565b600080602083850312156133ce57600080fd5b82356001600160401b038111156133e457600080fd5b6133f085828601613370565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b8281101561344f5761343f84835180516001600160a01b03168252602090810151910152565b9284019290850190600101613419565b5091979650505050505050565b60006020828403121561346e57600080fd5b8135612c6b81612f11565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156134d057603f198886030184526134be85835161324c565b945092850192908501906001016134a2565b5092979650505050505050565b602080825282516001600160a01b03168282015282810151604080840191909152808401516060808501528051608085018190526000939291830191849160a08701905b8084101561355b5761354782865180516001600160a01b03168252602090810151910152565b938501936001939093019290820190613521565b50979650505050505050565b6000806040838503121561357a57600080fd5b823561358581612f11565b9150602083013561359581612f11565b809150509250929050565b6000806000606084860312156135b557600080fd5b83356135c081612f11565b925060208401356135d081612f11565b915060408401356135e081612f11565b809150509250925092565b600060208083018184528085518083526040925060408601915060408160051b8701018488016000805b848110156136b857898403603f19018652825180516001600160a01b03908116865289820151168986015287810151888601526060908101516080918601829052805191860182905289019060a086019084905b808210156136a35761368f83855180516001600160a01b03168252602090810151910152565b928b0192918a019160019190910190613669565b50509689019694505091870191600101613615565b50919998505050505050505050565b6000806000604084860312156136dc57600080fd5b83356001600160401b038111156136f257600080fd5b6136fe86828701613370565b90945092505060208401356135e081612f11565b80516001600160a01b031682526020808201519083015260408082015190830152606080820151908301526080808201519083015260a090810151910152565b6020808252825182820181905260009190848201906040850190845b8181101561379457613781838551613712565b9284019260c0929092019160010161376e565b50909695505050505050565b81516001600160a01b031681526020808301519082015260408101610620565b61022081016106208284613137565b60c081016106208284613712565b6020808252825182820181905260009190848201906040850190845b818110156137945783516001600160a01b0316835292840192918401916001016137f9565b60006001600160401b0382111561383757613837612f39565b5060051b60200190565b6000602080838503121561385457600080fd5b82356001600160401b0381111561386a57600080fd5b8301601f8101851361387b57600080fd5b80356138896130778261381e565b81815260059190911b820183019083810190878311156138a857600080fd5b928401925b828410156138cf5783356138c081612f11565b825292840192908401906138ad565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561379457613909838551613137565b9284019261022092909201916001016138f6565b600082601f83011261392e57600080fd5b815161393c61307782612fc9565b81815284602083860101111561395157600080fd5b610baf8260208301602087016130e7565b60006020828403121561397457600080fd5b81516001600160401b038082111561398b57600080fd5b908301906060828603121561399f57600080fd5b6139a7612f77565b8251828111156139b657600080fd5b6139c28782860161391d565b8252506020830151828111156139d757600080fd5b6139e38782860161391d565b6020830152506040830151828111156139fb57600080fd5b613a078782860161391d565b60408301525095945050505050565b600060208284031215613a2857600080fd5b8151612c6b81612f11565b600060208284031215613a4557600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600060a08284031215613a7457600080fd5b613a7c612f4f565b905081516001600160401b03811115613a9457600080fd5b613aa08482850161391d565b8252506020820151613ab181612f11565b60208201526040820151613ac481612f11565b80604083015250606082015160608201526080820151608082015292915050565b60006020808385031215613af857600080fd5b82516001600160401b0380821115613b0f57600080fd5b818501915085601f830112613b2357600080fd5b8151613b316130778261381e565b81815260059190911b83018401908481019088831115613b5057600080fd5b8585015b83811015613b8857805185811115613b6c5760008081fd5b613b7a8b89838a0101613a62565b845250918601918601613b54565b5098975050505050505050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761062057610620613b95565b600082613bdf57634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561062057610620613b95565b600060208284031215613c0957600080fd5b81516001600160401b03811115613c1f57600080fd5b610baf84828501613a62565b60006020808385031215613c3e57600080fd5b82516001600160401b03811115613c5457600080fd5b8301601f81018513613c6557600080fd5b8051613c736130778261381e565b81815260059190911b82018301908381019087831115613c9257600080fd5b928401925b828410156138cf578351613caa81612f11565b82529284019290840190613c97565b80518015158114612f3457600080fd5b60008060408385031215613cdc57600080fd5b613ce583613cb9565b9150602083015190509250929050565b600060208284031215613d0757600080fd5b815160ff81168114612c6b57600080fd5b634e487b7160e01b600052602160045260246000fd5b6001600160a01b03831681526040810160098310613d5c57634e487b7160e01b600052602160045260246000fd5b8260208301529392505050565b600060208284031215613d7b57600080fd5b612c6b82613cb9565b600060ff821660ff8103613d9a57613d9a613b95565b60010192915050565b60006020808385031215613db657600080fd5b82516001600160401b03811115613dcc57600080fd5b8301601f81018513613ddd57600080fd5b8051613deb6130778261381e565b81815260059190911b82018301908381019087831115613e0a57600080fd5b928401925b828410156138cf578351613e2281612f11565b82529284019290840190613e0f565b60006020808385031215613e4457600080fd5b82516001600160401b03811115613e5a57600080fd5b8301601f81018513613e6b57600080fd5b8051613e796130778261381e565b81815260059190911b82018301908381019087831115613e9857600080fd5b928401925b828410156138cf578351613eb081612f11565b82529284019290840190613e9d565b600060018201613ed157613ed1613b95565b5060010190565b80516001600160e01b0381168114612f3457600080fd5b600080600060608486031215613f0457600080fd5b613f0d84613ed8565b925060208401519150604084015190509250925092565b805163ffffffff81168114612f3457600080fd5b600080600060608486031215613f4d57600080fd5b613f5684613ed8565b9250613f6460208501613f24565b9150613f7260408501613f24565b90509250925092565b600060208284031215613f8d57600080fd5b612c6b82613ed8565b8181038181111561062057610620613b95565b602081526000612c6b602083018461310b56fea264697066735822122096dca9ef030f65331631c7305d4d9405c1d0b56d48eb3787508d19369d85297764736f6c63430008190033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061010b5760003560e01c80637c51b642116100a2578063c7ad089511610071578063c7ad0895146102ac578063d26998e9146102e3578063d77ebf961461030a578063e0a67f111461032a578063e1d146fb1461034a57600080fd5b80637c51b6421461022c5780637c84e3b31461024c578063aa5dbd231461026c578063b31242391461028c57600080fd5b806347d86a81116100de57806347d86a811461019957806355dd9515146101ac5780636857249c146101d75780637a27db571461020c57600080fd5b80630d3ae318146101105780631f884fdf14610139578063345954dc146101595780633e3e399c14610179575b600080fd5b61012361011e366004612ff0565b610352565b604051610130919061335d565b60405180910390f35b61014c6101473660046133bb565b610626565b60405161013091906133fc565b61016c61016736600461345c565b6106ee565b6040516101309190613479565b61018c61018736600461345c565b610821565b60405161013091906134dd565b6101236101a7366004613567565b610b30565b6101bf6101ba3660046135a0565b610bb7565b6040516001600160a01b039091168152602001610130565b6101fe7f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610130565b61021f61021a366004613567565b610c37565b60405161013091906135eb565b61023f61023a3660046136c7565b610ee7565b6040516101309190613752565b61025f61025a36600461345c565b610fa0565b60405161013091906137a0565b61027f61027a36600461345c565b61110a565b60405161013091906137c0565b61029f61029a366004613567565b6118ca565b60405161013091906137cf565b6102d37f000000000000000000000000000000000000000000000000000000000000000081565b6040519015158152602001610130565b6101bf7f000000000000000000000000000000000000000000000000000000000000000081565b61031d610318366004613567565b611bb1565b60405161013091906137dd565b61033d610338366004613841565b611c24565b60405161013091906138da565b6101fe611cd9565b61035a612db7565b6040820151600061036a82611d14565b9050600061037782611c24565b60408681015190516328ebbe8b60e21b81526001600160a01b039182166004820152919250879160009183169063a3aefa2c90602401600060405180830381865afa1580156103ca573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526103f29190810190613962565b90506000876040015190506000604051806101a001604052808a6000015181526020018a602001516001600160a01b031681526020018a604001516001600160a01b031681526020018a6060015181526020018a608001518152602001846000015181526020018460200151815260200184604001518152602001836001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104cf9190613a16565b6001600160a01b03168152602001836001600160a01b031663e87554466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561051b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053f9190613a33565b8152602001836001600160a01b0316634ada90af6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610582573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105a69190613a33565b8152602001836001600160a01b031663db5c65de6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060d9190613a33565b8152602001959095525092955050505050505b92915050565b6060816000816001600160401b0381111561064357610643612f39565b60405190808252806020026020018201604052801561068857816020015b60408051808201909152600080825260208201528152602001906001900390816106615790505b50905060005b828110156106e5576106c08686838181106106ab576106ab613a4c565b905060200201602081019061025a919061345c565b8282815181106106d2576106d2613a4c565b602090810291909101015260010161068e565b50949350505050565b606060008290506000816001600160a01b031663d88ff1f46040518163ffffffff1660e01b8152600401600060405180830381865afa158015610735573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261075d9190810190613ae5565b80519091506000816001600160401b0381111561077c5761077c612f39565b6040519080825280602002602001820160405280156107b557816020015b6107a2612db7565b81526020019060019003908161079a5790505b50905060005b828110156108175760008482815181106107d7576107d7613a4c565b6020026020010151905060006107ed8983610352565b90508084848151811061080257610802613a4c565b602090810291909101015250506001016107bb565b5095945050505050565b60408051606080820183526000808352602083018190529282015290828161084882611d14565b90506000826001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561088a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ae9190613a16565b9050600082516001600160401b038111156108cb576108cb612f39565b60405190808252806020026020018201604052801561091057816020015b60408051808201909152600080825260208201528152602001906001900390816108e95790505b509050610940604051806060016040528060006001600160a01b0316815260200160008152602001606081525090565b6001600160a01b03881681526040810182905260005b8451811015610b1c57604080518082019091526000808252602082015285828151811061098557610985613a4c565b602002602001015181600001906001600160a01b031690816001600160a01b031681525050670de0b6b3a7640000856001600160a01b031663fc57d4df8885815181106109d4576109d4613a4c565b60200260200101516040518263ffffffff1660e01b8152600401610a0791906001600160a01b0391909116815260200190565b602060405180830381865afa158015610a24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a489190613a33565b878481518110610a5a57610a5a613a4c565b60200260200101516001600160a01b031663bbcac5576040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac39190613a33565b610acd9190613bab565b610ad79190613bc2565b60208201526040830151805182919084908110610af657610af6613a4c565b6020026020010181905250806020015188610b119190613be4565b975050600101610956565b506020810195909552509295945050505050565b610b38612db7565b604051637aee632d60e01b81526001600160a01b0383811660048301528491610baf91839190821690637aee632d90602401600060405180830381865afa158015610b87573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261011e9190810190613bf7565b949350505050565b60405163266e0a7f60e01b81526001600160a01b0383811660048301528281166024830152600091859182169063266e0a7f90604401602060405180830381865afa158015610c0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2e9190613a16565b95945050505050565b60606000610c4483611d14565b90506000836001600160a01b03166361252fd16040518163ffffffff1660e01b8152600401600060405180830381865afa158015610c86573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cae9190810190613c2b565b9050600081516001600160401b03811115610ccb57610ccb612f39565b604051908082528060200260200182016040528015610d1c57816020015b6040805160808101825260008082526020808301829052928201526060808201528252600019909201910181610ce95790505b50905060005b8251811015610817576040805160808101825260008082526020820181905291810191909152606080820152838281518110610d6057610d60613a4c565b60209081029190910101516001600160a01b031681528351849083908110610d8a57610d8a613a4c565b60200260200101516001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dcf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df39190613a16565b6001600160a01b031660208201528351849083908110610e1557610e15613a4c565b6020908102919091010151604051631627ee8960e01b81526001600160a01b038a8116600483015290911690631627ee8990602401602060405180830381865afa158015610e67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8b9190613a33565b816040018181525050610eb88886868581518110610eab57610eab613a4c565b6020026020010151611eb3565b816060018190525080838381518110610ed357610ed3613a4c565b602090810291909101015250600101610d22565b6060826000816001600160401b03811115610f0457610f04612f39565b604051908082528060200260200182016040528015610f3d57816020015b610f2a612e3a565b815260200190600190039081610f225790505b50905060005b8281101561081757610f7b878783818110610f6057610f60613a4c565b9050602002016020810190610f75919061345c565b866118ca565b828281518110610f8d57610f8d613a4c565b6020908102919091010152600101610f43565b60408051808201909152600080825260208201526000826001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ff4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110189190613a16565b90506000816001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561105a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061107e9190613a16565b6040805180820182526001600160a01b03808816808352925163fc57d4df60e01b815260048101939093529293509160208301919084169063fc57d4df90602401602060405180830381865afa1580156110dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111009190613a33565b9052949350505050565b611112612e79565b6000826001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611152573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111769190613a33565b90506000836001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111dc9190613a16565b604051638e8f294b60e01b81526001600160a01b03868116600483015291925082916000918291841690638e8f294b906024016040805180830381865afa15801561122b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061124f9190613cc9565b915091506000876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611293573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b79190613a16565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061131d9190613cf5565b60ff1690506000805b600860ff8216116113e3576000886001600160a01b031663e85a29608d8460ff16600881111561135857611358613d18565b6040518363ffffffff1660e01b8152600401611375929190613d2e565b602060405180830381865afa158015611392573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b69190613d69565b6113c15760006113c4565b60015b60ff9081169083161b9290921791506113dc81613d84565b9050611326565b506000808b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611425573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114499190613a33565b11156114b4578a6001600160a01b031663ae9d70b06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561148d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114b19190613a33565b90505b6040518061022001604052808c6001600160a01b031681526020018a81526020018281526020018c6001600160a01b031663f8f9da286040518163ffffffff1660e01b8152600401602060405180830381865afa158015611519573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153d9190613a33565b81526020018c6001600160a01b031663173b99046040518163ffffffff1660e01b8152600401602060405180830381865afa158015611580573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a49190613a33565b81526040516302c3bcbb60e01b81526001600160a01b038e811660048301526020909201918a16906302c3bcbb90602401602060405180830381865afa1580156115f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116169190613a33565b815260405163252c221960e11b81526001600160a01b038e811660048301526020909201918a1690634a58443290602401602060405180830381865afa158015611664573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116889190613a33565b81526020018c6001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ef9190613a33565b81526020018c6001600160a01b0316638f840ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611732573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117569190613a33565b81526020018c6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611799573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117bd9190613a33565b81526020018c6001600160a01b0316633b1d21a26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611800573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118249190613a33565b81526020018715158152602001868152602001856001600160a01b031681526020018c6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611884573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118a89190613cf5565b60ff168152602001848152602001838152509950505050505050505050919050565b6118d2612e3a565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908516906370a0823190602401602060405180830381865afa15801561191c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119409190613a33565b6040516305eff7ef60e21b81526001600160a01b0385811660048301529192506000918616906317bfdfbc906024016020604051808303816000875af115801561198e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b29190613a33565b604051633af9e66960e01b81526001600160a01b038681166004830152919250600091871690633af9e669906024016020604051808303816000875af1158015611a00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a249190613a33565b90506000806000886001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a8d9190613a16565b6040516370a0823160e01b81526001600160a01b038a81166004830152919250908216906370a0823190602401602060405180830381865afa158015611ad7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611afb9190613a33565b604051636eb1769f60e11b81526001600160a01b038a811660048301528b811660248301529194509082169063dd62ed3e90604401602060405180830381865afa158015611b4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b719190613a33565b6040805160c0810182526001600160a01b038c168152602081019890985287019590955250506060840191909152608083015260a0820152905092915050565b604051631e6db74760e31b81526001600160a01b038281166004830152606091849182169063f36dba3890602401600060405180830381865afa158015611bfc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610baf9190810190613da3565b80516060906000816001600160401b03811115611c4357611c43612f39565b604051908082528060200260200182016040528015611c7c57816020015b611c69612e79565b815260200190600190039081611c615790505b50905060005b82811015611cd157611cac858281518110611c9f57611c9f613a4c565b602002602001015161110a565b828281518110611cbe57611cbe613a4c565b6020908102919091010152600101611c82565b509392505050565b6000611d077f000000000000000000000000000000000000000000000000000000000000000063ffffffff16565b905090565b4390565b4290565b60606000826001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015611d56573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d7e9190810190613e31565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031603611dbf5792915050565b8051600090815b81811015611ea9576000848281518110611de257611de2613a4c565b60200260200101516001600160a01b03166322abdbf56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e4b9190613a33565b1115611ea157838181518110611e6357611e63613a4c565b6020026020010151848481518110611e7d57611e7d613a4c565b6001600160a01b0390921660209283029190910190910152611e9e83613ebf565b92505b600101611dc6565b5050815292915050565b6060600083516001600160401b03811115611ed057611ed0612f39565b604051908082528060200260200182016040528015611f1557816020015b6040805180820190915260008082526020820152815260200190600190039081611eee5790505b50905060005b84518110156106e557611f51604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b611f7e604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b7f00000000000000000000000000000000000000000000000000000000000000001561210157856001600160a01b0316638f693ec7888581518110611fc557611fc5613a4c565b60200260200101516040518263ffffffff1660e01b8152600401611ff891906001600160a01b0391909116815260200190565b606060405180830381865afa158015612015573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120399190613eef565b604085015260208401526001600160e01b0316825286516001600160a01b0387169063818149459089908690811061207357612073613a4c565b60200260200101516040518263ffffffff1660e01b81526004016120a691906001600160a01b0391909116815260200190565b606060405180830381865afa1580156120c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e79190613eef565b604084015260208301526001600160e01b0316815261226c565b856001600160a01b0316632c427b5788858151811061212257612122613a4c565b60200260200101516040518263ffffffff1660e01b815260040161215591906001600160a01b0391909116815260200190565b606060405180830381865afa158015612172573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121969190613f38565b63ffffffff90811660408601521660208401526001600160e01b0316825286516001600160a01b038716906392a18235908990869081106121d9576121d9613a4c565b60200260200101516040518263ffffffff1660e01b815260040161220c91906001600160a01b0391909116815260200190565b606060405180830381865afa158015612229573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061224d9190613f38565b63ffffffff90811660408501521660208301526001600160e01b031681525b6000604051806020016040528089868151811061228b5761228b613a4c565b60200260200101516001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122f49190613a33565b815250905061231e88858151811061230e5761230e613a4c565b6020026020010151888584612413565b61234288858151811061233357612333613a4c565b60200260200101518884612614565b600061236a89868151811061235957612359613a4c565b6020026020010151898c878661280b565b905060006123938a878151811061238357612383613a4c565b60200260200101518a8d87612a3b565b60408051808201909152600080825260208201529091508a87815181106123bc576123bc613a4c565b60209081029190910101516001600160a01b031681526123dc8284613be4565b6020820152875181908990899081106123f7576123f7613a4c565b6020026020010181905250505050505050806001019050611f1b565b604051637c05a7c560e01b81526001600160a01b03858116600483015260009190851690637c05a7c590602401602060405180830381865afa15801561245d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124819190613a33565b9050600061248d611cd9565b9050600084604001511180156124a65750836040015181115b156124b2575060408301515b60006124c2828660200151612c5f565b90506000811180156124d45750600083115b156125fd576000612546886001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561251c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125409190613a33565b86612c72565b905060006125548386612c90565b90506000808311612574576040518060200160405280600081525061257e565b61257e8284612c9c565b905060006125a760405180602001604052808b600001516001600160e01b031681525083612ce1565b90506125e28160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612d0d565b6001600160e01b03168952505050506020850182905261260b565b801561260b57602085018290525b50505050505050565b604051631d31307360e21b81526001600160a01b038481166004830152600091908416906374c4c1cc90602401602060405180830381865afa15801561265e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126829190613a33565b9050600061268e611cd9565b9050600083604001511180156126a75750826040015181115b156126b3575060408201515b60006126c3828560200151612c5f565b90506000811180156126d55750600083115b156127f5576000866001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561271a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061273e9190613a33565b9050600061274c8386612c90565b9050600080831161276c5760405180602001604052806000815250612776565b6127768284612c9c565b9050600061279f60405180602001604052808a600001516001600160e01b031681525083612ce1565b90506127da8160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612d0d565b6001600160e01b031688525050505060208401829052612803565b801561280357602084018290525b505050505050565b604080516020808201835284516001600160e01b031682528251908101928390526336fe846560e11b9092526001600160a01b0387811660248401528581166044840152600092839181908916636dfd08ca60648301602060405180830381865afa15801561287e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a29190613a33565b905280519091501580156129245750866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129139190613f7b565b6001600160e01b0316826000015110155b1561299757866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061298b9190613f7b565b6001600160e01b031681525b60006129a38383612d49565b6040516395dd919360e01b81526001600160a01b038981166004830152919250600091612a1e91908c16906395dd919390602401602060405180830381865afa1580156129f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a189190613a33565b87612c72565b90506000612a2c8284612d75565b9b9a5050505050505050505050565b604080516020808201835283516001600160e01b0316825282519081019283905263552c097160e01b9092526001600160a01b038681166024840152848116604484015260009283918190881663552c097160648301602060405180830381865afa158015612aae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ad29190613a33565b90528051909150158015612b545750856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b439190613f7b565b6001600160e01b0316826000015110155b15612bc757856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bbb9190613f7b565b6001600160e01b031681525b6000612bd38383612d49565b6040516370a0823160e01b81526001600160a01b0388811660048301529192506000918a16906370a0823190602401602060405180830381865afa158015612c1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c439190613a33565b90506000612c518284612d75565b9a9950505050505050505050565b6000612c6b8284613f96565b9392505050565b6000612c6b612c8984670de0b6b3a7640000612c90565b8351612d9f565b6000612c6b8284613bab565b6040805160208101909152600081526040518060200160405280612cd8612cd2866ec097ce7bc90715b34b9f1000000000612c90565b85612d9f565b90529392505050565b6040805160208101909152600081526040518060200160405280612cd885600001518560000151612dab565b6000816001600160e01b03841115612d415760405162461bcd60e51b8152600401612d389190613fa9565b60405180910390fd5b509192915050565b6040805160208101909152600081526040518060200160405280612cd885600001518560000151612c5f565b60006ec097ce7bc90715b34b9f1000000000612d95848460000151612c90565b612c6b9190613bc2565b6000612c6b8284613bc2565b6000612c6b8284613be4565b604051806101a001604052806060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160608152602001606081526020016060815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001606081525090565b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180610220016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b6001600160a01b0381168114612f2657600080fd5b50565b8035612f3481612f11565b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715612f7157612f71612f39565b60405290565b604051606081016001600160401b0381118282101715612f7157612f71612f39565b604051601f8201601f191681016001600160401b0381118282101715612fc157612fc1612f39565b604052919050565b60006001600160401b03821115612fe257612fe2612f39565b50601f01601f191660200190565b6000806040838503121561300357600080fd5b823561300e81612f11565b91506020838101356001600160401b038082111561302b57600080fd5b9085019060a0828803121561303f57600080fd5b613047612f4f565b82358281111561305657600080fd5b83019150601f8201881361306957600080fd5b813561307c61307782612fc9565b612f99565b818152898683860101111561309057600080fd5b8186850187830137600086838301015280835250506130b0848401612f29565b848201526130c060408401612f29565b60408201526060830135606082015260808301356080820152809450505050509250929050565b60005b838110156131025781810151838201526020016130ea565b50506000910152565b600081518084526131238160208601602086016130e7565b601f01601f19169290920160200192915050565b80516001600160a01b031682526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e0830152610100808201518184015250610120808201518184015250610140808201518184015250610160808201516131c28285018215159052565b505061018081810151908301526101a0808201516001600160a01b0316908301526101c080820151908301526101e0808201519083015261020090810151910152565b60008151808452602080850194506020840160005b838110156132415761322d878351613137565b61022096909601959082019060010161321a565b509495945050505050565b60006101a082518185526132628286018261310b565b915050602083015161327f60208601826001600160a01b03169052565b50604083015161329a60408601826001600160a01b03169052565b50606083015160608501526080830151608085015260a083015184820360a08601526132c6828261310b565b91505060c083015184820360c08601526132e0828261310b565b91505060e083015184820360e08601526132fa828261310b565b91505061010080840151613318828701826001600160a01b03169052565b505061012083810151908501526101408084015190850152610160808401519085015261018080840151858303828701526133538382613205565b9695505050505050565b602081526000612c6b602083018461324c565b60008083601f84011261338257600080fd5b5081356001600160401b0381111561339957600080fd5b6020830191508360208260051b85010111156133b457600080fd5b9250929050565b600080602083850312156133ce57600080fd5b82356001600160401b038111156133e457600080fd5b6133f085828601613370565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b8281101561344f5761343f84835180516001600160a01b03168252602090810151910152565b9284019290850190600101613419565b5091979650505050505050565b60006020828403121561346e57600080fd5b8135612c6b81612f11565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156134d057603f198886030184526134be85835161324c565b945092850192908501906001016134a2565b5092979650505050505050565b602080825282516001600160a01b03168282015282810151604080840191909152808401516060808501528051608085018190526000939291830191849160a08701905b8084101561355b5761354782865180516001600160a01b03168252602090810151910152565b938501936001939093019290820190613521565b50979650505050505050565b6000806040838503121561357a57600080fd5b823561358581612f11565b9150602083013561359581612f11565b809150509250929050565b6000806000606084860312156135b557600080fd5b83356135c081612f11565b925060208401356135d081612f11565b915060408401356135e081612f11565b809150509250925092565b600060208083018184528085518083526040925060408601915060408160051b8701018488016000805b848110156136b857898403603f19018652825180516001600160a01b03908116865289820151168986015287810151888601526060908101516080918601829052805191860182905289019060a086019084905b808210156136a35761368f83855180516001600160a01b03168252602090810151910152565b928b0192918a019160019190910190613669565b50509689019694505091870191600101613615565b50919998505050505050505050565b6000806000604084860312156136dc57600080fd5b83356001600160401b038111156136f257600080fd5b6136fe86828701613370565b90945092505060208401356135e081612f11565b80516001600160a01b031682526020808201519083015260408082015190830152606080820151908301526080808201519083015260a090810151910152565b6020808252825182820181905260009190848201906040850190845b8181101561379457613781838551613712565b9284019260c0929092019160010161376e565b50909695505050505050565b81516001600160a01b031681526020808301519082015260408101610620565b61022081016106208284613137565b60c081016106208284613712565b6020808252825182820181905260009190848201906040850190845b818110156137945783516001600160a01b0316835292840192918401916001016137f9565b60006001600160401b0382111561383757613837612f39565b5060051b60200190565b6000602080838503121561385457600080fd5b82356001600160401b0381111561386a57600080fd5b8301601f8101851361387b57600080fd5b80356138896130778261381e565b81815260059190911b820183019083810190878311156138a857600080fd5b928401925b828410156138cf5783356138c081612f11565b825292840192908401906138ad565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561379457613909838551613137565b9284019261022092909201916001016138f6565b600082601f83011261392e57600080fd5b815161393c61307782612fc9565b81815284602083860101111561395157600080fd5b610baf8260208301602087016130e7565b60006020828403121561397457600080fd5b81516001600160401b038082111561398b57600080fd5b908301906060828603121561399f57600080fd5b6139a7612f77565b8251828111156139b657600080fd5b6139c28782860161391d565b8252506020830151828111156139d757600080fd5b6139e38782860161391d565b6020830152506040830151828111156139fb57600080fd5b613a078782860161391d565b60408301525095945050505050565b600060208284031215613a2857600080fd5b8151612c6b81612f11565b600060208284031215613a4557600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600060a08284031215613a7457600080fd5b613a7c612f4f565b905081516001600160401b03811115613a9457600080fd5b613aa08482850161391d565b8252506020820151613ab181612f11565b60208201526040820151613ac481612f11565b80604083015250606082015160608201526080820151608082015292915050565b60006020808385031215613af857600080fd5b82516001600160401b0380821115613b0f57600080fd5b818501915085601f830112613b2357600080fd5b8151613b316130778261381e565b81815260059190911b83018401908481019088831115613b5057600080fd5b8585015b83811015613b8857805185811115613b6c5760008081fd5b613b7a8b89838a0101613a62565b845250918601918601613b54565b5098975050505050505050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761062057610620613b95565b600082613bdf57634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561062057610620613b95565b600060208284031215613c0957600080fd5b81516001600160401b03811115613c1f57600080fd5b610baf84828501613a62565b60006020808385031215613c3e57600080fd5b82516001600160401b03811115613c5457600080fd5b8301601f81018513613c6557600080fd5b8051613c736130778261381e565b81815260059190911b82018301908381019087831115613c9257600080fd5b928401925b828410156138cf578351613caa81612f11565b82529284019290840190613c97565b80518015158114612f3457600080fd5b60008060408385031215613cdc57600080fd5b613ce583613cb9565b9150602083015190509250929050565b600060208284031215613d0757600080fd5b815160ff81168114612c6b57600080fd5b634e487b7160e01b600052602160045260246000fd5b6001600160a01b03831681526040810160098310613d5c57634e487b7160e01b600052602160045260246000fd5b8260208301529392505050565b600060208284031215613d7b57600080fd5b612c6b82613cb9565b600060ff821660ff8103613d9a57613d9a613b95565b60010192915050565b60006020808385031215613db657600080fd5b82516001600160401b03811115613dcc57600080fd5b8301601f81018513613ddd57600080fd5b8051613deb6130778261381e565b81815260059190911b82018301908381019087831115613e0a57600080fd5b928401925b828410156138cf578351613e2281612f11565b82529284019290840190613e0f565b60006020808385031215613e4457600080fd5b82516001600160401b03811115613e5a57600080fd5b8301601f81018513613e6b57600080fd5b8051613e796130778261381e565b81815260059190911b82018301908381019087831115613e9857600080fd5b928401925b828410156138cf578351613eb081612f11565b82529284019290840190613e9d565b600060018201613ed157613ed1613b95565b5060010190565b80516001600160e01b0381168114612f3457600080fd5b600080600060608486031215613f0457600080fd5b613f0d84613ed8565b925060208401519150604084015190509250925092565b805163ffffffff81168114612f3457600080fd5b600080600060608486031215613f4d57600080fd5b613f5684613ed8565b9250613f6460208501613f24565b9150613f7260408501613f24565b90509250925092565b600060208284031215613f8d57600080fd5b612c6b82613ed8565b8181038181111561062057610620613b95565b602081526000612c6b602083018461310b56fea264697066735822122096dca9ef030f65331631c7305d4d9405c1d0b56d48eb3787508d19369d85297764736f6c63430008190033", "devdoc": { "author": "Venus", "kind": "dev", @@ -1198,6 +1216,7 @@ "custom:oz-upgrades-unsafe-allow": "constructor", "params": { "blocksPerYear_": "The number of blocks per year", + "corePoolComptroller_": "The address of the core pool comptroller", "timeBased_": "A boolean indicating whether the contract is based on time or block." } }, @@ -1342,6 +1361,9 @@ "blocksOrSecondsPerYear()": { "notice": "Stores blocksPerYear if isTimeBased is true else secondsPerYear is stored" }, + "corePoolComptroller()": { + "notice": "Address of the core pool comptroller (all markets are returned for this pool, including paused ones)" + }, "getAllPools(address)": { "notice": "Queries all pools with addtional details for each of them" }, @@ -1391,7 +1413,7 @@ "storageLayout": { "storage": [ { - "astId": 5815, + "astId": 1737, "contract": "contracts/Lens/PoolLens.sol:PoolLens", "label": "__gap", "offset": 0, diff --git a/deployments/basemainnet/solcInputs/09f8b2889a382752688c03578bc27f8d.json b/deployments/basemainnet/solcInputs/09f8b2889a382752688c03578bc27f8d.json new file mode 100644 index 000000000..b2e4f0f5c --- /dev/null +++ b/deployments/basemainnet/solcInputs/09f8b2889a382752688c03578bc27f8d.json @@ -0,0 +1,139 @@ +{ + "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/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/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/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/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" + }, + "@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/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/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\ninterface IProtocolShareReserve {\n /// @notice it represents the type of vToken income\n enum IncomeType {\n SPREAD,\n LIQUIDATION,\n ERC4626_WRAPPER_REWARDS,\n FLASHLOAN\n }\n\n function updateAssetsState(\n address comptroller,\n address asset,\n IncomeType incomeType\n ) external;\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/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/venus-protocol/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" + }, + "@venusprotocol/venus-protocol/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/Comptroller.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { IPrime } from \"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\";\n\nimport { ComptrollerInterface, Action } from \"./ComptrollerInterface.sol\";\nimport { ComptrollerStorage } from \"./ComptrollerStorage.sol\";\nimport { ExponentialNoError } from \"./ExponentialNoError.sol\";\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.sol\";\nimport { MaxLoopsLimitHelper } from \"./MaxLoopsLimitHelper.sol\";\nimport { ensureNonzeroAddress } from \"./lib/validators.sol\";\n\n/**\n * @title Comptroller\n * @author Venus\n * @notice The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating,\n * and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts\n * with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows\n * or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing\n * liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow,\n * as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the\n * markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market’s corresponding liquidation threshold,\n * the borrow is eligible for liquidation.\n *\n * The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed\n * the `minLiquidatableCollateral` for the `Comptroller`:\n *\n * - `healAccount()`: This function is called to seize all of a given user’s collateral, requiring the `msg.sender` repay a certain percentage\n * of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed\n * 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt\n * and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool.\n * - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation\n * incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic\n * verifying that the repay amount does not exceed the close factor.\n */\ncontract Comptroller is\n Ownable2StepUpgradeable,\n AccessControlledV8,\n ComptrollerStorage,\n ComptrollerInterface,\n ExponentialNoError,\n MaxLoopsLimitHelper\n{\n // PoolRegistry, immutable to save on gas\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable poolRegistry;\n\n /// @notice Emitted when an account enters a market\n event MarketEntered(VToken indexed vToken, address indexed account);\n\n /// @notice Emitted when an account exits a market\n event MarketExited(VToken indexed vToken, address indexed account);\n\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(VToken vToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa);\n\n /// @notice Emitted when liquidation threshold is changed by admin\n event NewLiquidationThreshold(\n VToken vToken,\n uint256 oldLiquidationThresholdMantissa,\n uint256 newLiquidationThresholdMantissa\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 an action is paused on a market\n event ActionPausedMarket(VToken vToken, Action action, bool pauseState);\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 the collateral threshold (in USD) for non-batch liquidations is changed\n event NewMinLiquidatableCollateral(uint256 oldMinLiquidatableCollateral, uint256 newMinLiquidatableCollateral);\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 a rewards distributor is added\n event NewRewardsDistributor(address indexed rewardsDistributor, address indexed rewardToken);\n\n /// @notice Emitted when a market is supported\n event MarketSupported(VToken vToken);\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 a market\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\n\n /// @notice Emitted when a market is unlisted\n event MarketUnlisted(address indexed vToken);\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 Thrown when collateral factor exceeds the upper bound\n error InvalidCollateralFactor();\n\n /// @notice Thrown when liquidation threshold exceeds the collateral factor\n error InvalidLiquidationThreshold();\n\n /// @notice Thrown when the action is only available to specific sender, but the real sender was different\n error UnexpectedSender(address expectedSender, address actualSender);\n\n /// @notice Thrown when the oracle returns an invalid price for some asset\n error PriceError(address vToken);\n\n /// @notice Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\n error SnapshotError(address vToken, address user);\n\n /// @notice Thrown when the market is not listed\n error MarketNotListed(address market);\n\n /// @notice Thrown when a market has an unexpected comptroller\n error ComptrollerMismatch();\n\n /// @notice Thrown when user is not member of market\n error MarketNotCollateral(address vToken, address user);\n\n /// @notice Thrown when borrow action is not paused\n error BorrowActionNotPaused();\n\n /// @notice Thrown when mint action is not paused\n error MintActionNotPaused();\n\n /// @notice Thrown when redeem action is not paused\n error RedeemActionNotPaused();\n\n /// @notice Thrown when repay action is not paused\n error RepayActionNotPaused();\n\n /// @notice Thrown when seize action is not paused\n error SeizeActionNotPaused();\n\n /// @notice Thrown when exit market action is not paused\n error ExitMarketActionNotPaused();\n\n /// @notice Thrown when transfer action is not paused\n error TransferActionNotPaused();\n\n /// @notice Thrown when enter market action is not paused\n error EnterMarketActionNotPaused();\n\n /// @notice Thrown when liquidate action is not paused\n error LiquidateActionNotPaused();\n\n /// @notice Thrown when borrow cap is not zero\n error BorrowCapIsNotZero();\n\n /// @notice Thrown when supply cap is not zero\n error SupplyCapIsNotZero();\n\n /// @notice Thrown when collateral factor is not zero\n error CollateralFactorIsNotZero();\n\n /**\n * @notice Thrown during the liquidation if user's total collateral amount is lower than\n * a predefined threshold. In this case only batch liquidations (either liquidateAccount\n * or healAccount) are available.\n */\n error MinimalCollateralViolated(uint256 expectedGreaterThan, uint256 actual);\n error CollateralExceedsThreshold(uint256 expectedLessThanOrEqualTo, uint256 actual);\n error InsufficientCollateral(uint256 collateralToSeize, uint256 availableCollateral);\n\n /// @notice Thrown when the account doesn't have enough liquidity to redeem or borrow\n error InsufficientLiquidity();\n\n /// @notice Thrown when trying to liquidate a healthy account\n error InsufficientShortfall();\n\n /// @notice Thrown when trying to repay more than allowed by close factor\n error TooMuchRepay();\n\n /// @notice Thrown if the user is trying to exit a market in which they have an outstanding debt\n error NonzeroBorrowBalance();\n\n /// @notice Thrown when trying to perform an action that is paused\n error ActionPaused(address market, Action action);\n\n /// @notice Thrown when trying to add a market that is already listed\n error MarketAlreadyListed(address market);\n\n /// @notice Thrown if the supply cap is exceeded\n error SupplyCapExceeded(address market, uint256 cap);\n\n /// @notice Thrown if the borrow cap is exceeded\n error BorrowCapExceeded(address market, uint256 cap);\n\n /// @notice Thrown if delegate approval status is already set to the requested value\n error DelegationStatusUnchanged();\n\n /// @param poolRegistry_ Pool registry address\n /// @custom:oz-upgrades-unsafe-allow constructor\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n constructor(address poolRegistry_) {\n ensureNonzeroAddress(poolRegistry_);\n\n poolRegistry = poolRegistry_;\n _disableInitializers();\n }\n\n /**\n * @param loopLimit Limit for the loops can iterate to avoid the DOS\n * @param accessControlManager Access control manager contract address\n */\n function initialize(uint256 loopLimit, address accessControlManager) external initializer {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager);\n\n _setMaxLoopsLimit(loopLimit);\n }\n\n /**\n * @notice Add assets to be included in account liquidity calculation; enabling them to be used as collateral\n * @param vTokens The list of addresses of the vToken markets to be enabled\n * @return errors An array of NO_ERROR for compatibility with Venus core tooling\n * @custom:event MarketEntered is emitted for each market on success\n * @custom:error ActionPaused error is thrown if entering any of the markets is paused\n * @custom:error MarketNotListed error is thrown if any of the markets is not listed\n * @custom:access Not restricted\n */\n function enterMarkets(address[] memory vTokens) external override returns (uint256[] memory) {\n uint256 len = vTokens.length;\n\n uint256[] memory results = new uint256[](len);\n for (uint256 i; i < len; ++i) {\n VToken vToken = VToken(vTokens[i]);\n\n _addToMarket(vToken, msg.sender);\n results[i] = NO_ERROR;\n }\n\n return results;\n }\n\n /**\n * @notice Unlist a market by setting isListed to false\n * @dev Checks if all actions are paused, borrow/supply caps is set to 0 and collateral factor is to 0.\n * @param market The address of the market (token) to unlist\n * @return uint256 Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event MarketUnlisted is emitted on success\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error BorrowActionNotPaused error is thrown if borrow action is not paused\n * @custom:error MintActionNotPaused error is thrown if mint action is not paused\n * @custom:error RedeemActionNotPaused error is thrown if redeem action is not paused\n * @custom:error RepayActionNotPaused error is thrown if repay action is not paused\n * @custom:error EnterMarketActionNotPaused error is thrown if enter market action is not paused\n * @custom:error LiquidateActionNotPaused error is thrown if liquidate action is not paused\n * @custom:error BorrowCapIsNotZero error is thrown if borrow cap is not zero\n * @custom:error SupplyCapIsNotZero error is thrown if supply cap is not zero\n * @custom:error CollateralFactorIsNotZero error is thrown if collateral factor is not zero\n */\n function unlistMarket(address market) external returns (uint256) {\n _checkAccessAllowed(\"unlistMarket(address)\");\n\n Market storage _market = markets[market];\n\n if (!_market.isListed) {\n revert MarketNotListed(market);\n }\n\n if (!actionPaused(market, Action.BORROW)) {\n revert BorrowActionNotPaused();\n }\n\n if (!actionPaused(market, Action.MINT)) {\n revert MintActionNotPaused();\n }\n\n if (!actionPaused(market, Action.REDEEM)) {\n revert RedeemActionNotPaused();\n }\n\n if (!actionPaused(market, Action.REPAY)) {\n revert RepayActionNotPaused();\n }\n\n if (!actionPaused(market, Action.SEIZE)) {\n revert SeizeActionNotPaused();\n }\n\n if (!actionPaused(market, Action.ENTER_MARKET)) {\n revert EnterMarketActionNotPaused();\n }\n\n if (!actionPaused(market, Action.LIQUIDATE)) {\n revert LiquidateActionNotPaused();\n }\n\n if (!actionPaused(market, Action.TRANSFER)) {\n revert TransferActionNotPaused();\n }\n\n if (!actionPaused(market, Action.EXIT_MARKET)) {\n revert ExitMarketActionNotPaused();\n }\n\n if (borrowCaps[market] != 0) {\n revert BorrowCapIsNotZero();\n }\n\n if (supplyCaps[market] != 0) {\n revert SupplyCapIsNotZero();\n }\n\n if (_market.collateralFactorMantissa != 0) {\n revert CollateralFactorIsNotZero();\n }\n\n _market.isListed = false;\n emit MarketUnlisted(market);\n\n return NO_ERROR;\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 * @custom:event DelegateUpdated emits on success\n * @custom:error ZeroAddressNotAllowed is thrown when delegate address is zero\n * @custom:error DelegationStatusUnchanged is thrown if approval status is already set to the requested value\n * @custom:access Not restricted\n */\n function updateDelegate(address delegate, bool approved) external {\n ensureNonzeroAddress(delegate);\n if (approvedDelegates[msg.sender][delegate] == approved) {\n revert DelegationStatusUnchanged();\n }\n\n approvedDelegates[msg.sender][delegate] = approved;\n emit DelegateUpdated(msg.sender, delegate, approved);\n }\n\n /**\n * @notice Removes asset from sender's account liquidity calculation; disabling them as collateral\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event MarketExited is emitted on success\n * @custom:error ActionPaused error is thrown if exiting the market is paused\n * @custom:error NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function exitMarket(address vTokenAddress) external override returns (uint256) {\n _checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\n VToken vToken = VToken(vTokenAddress);\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\n (uint256 tokensHeld, uint256 amountOwed, ) = _safeGetAccountSnapshot(vToken, msg.sender);\n\n /* Fail if the sender has a borrow balance */\n if (amountOwed != 0) {\n revert NonzeroBorrowBalance();\n }\n\n /* Fail if the sender is not permitted to redeem all of their tokens */\n _checkRedeemAllowed(vTokenAddress, msg.sender, tokensHeld);\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 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 // load into memory for faster iteration\n VToken[] memory userAssetList = accountAssets[msg.sender];\n uint256 len = userAssetList.length;\n\n uint256 assetIndex = len;\n for (uint256 i; i < len; ++i) {\n if (userAssetList[i] == vToken) {\n assetIndex = i;\n break;\n }\n }\n\n // We *must* have found the asset in the list or our redundant data structure is broken\n assert(assetIndex < len);\n\n // copy last item in list to location of item to be removed, reduce length by 1\n VToken[] storage storedList = accountAssets[msg.sender];\n storedList[assetIndex] = storedList[storedList.length - 1];\n storedList.pop();\n\n emit MarketExited(vToken, msg.sender);\n\n return NO_ERROR;\n }\n\n /*** Policy Hooks ***/\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 * @custom:error ActionPaused error is thrown if supplying to this market is paused\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\n * @custom:access Not restricted\n */\n function preMintHook(address vToken, address minter, uint256 mintAmount) external override {\n _checkActionPauseState(vToken, Action.MINT);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n uint256 supplyCap = supplyCaps[vToken];\n // Skipping the cap check for uncapped coins to save some gas\n if (supplyCap != type(uint256).max) {\n uint256 vTokenSupply = VToken(vToken).totalSupply();\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\n if (nextTotalSupply > supplyCap) {\n revert SupplyCapExceeded(vToken, supplyCap);\n }\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, minter);\n }\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external override {\n _checkActionPauseState(vToken, Action.REDEEM);\n\n _checkRedeemAllowed(vToken, redeemer, redeemTokens);\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, redeemer);\n }\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 if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(redeemer, vToken);\n }\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 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 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 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 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 * @custom:error ActionPaused error is thrown if borrowing is paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if there is not enough collateral to borrow\n * @custom:error BorrowCapExceeded is thrown if the borrow cap will be exceeded should this borrow succeed\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted if vToken is enabled as collateral, otherwise only vToken\n */\n /// disable-eslint\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external override {\n _checkActionPauseState(vToken, Action.BORROW);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n if (!markets[vToken].accountMembership[borrower]) {\n // only vTokens may call borrowAllowed if borrower not in market\n _checkSenderIs(vToken);\n\n // attempt to add borrower to the market or revert\n _addToMarket(VToken(msg.sender), borrower);\n }\n\n // Update the prices of tokens\n updatePrices(borrower);\n\n if (oracle.getUnderlyingPrice(vToken) == 0) {\n revert PriceError(address(vToken));\n }\n\n uint256 borrowCap = borrowCaps[vToken];\n // Skipping the cap check for uncapped coins to save some gas\n if (borrowCap != type(uint256).max) {\n uint256 totalBorrows = VToken(vToken).totalBorrows();\n uint256 badDebt = VToken(vToken).badDebt();\n uint256 nextTotalBorrows = totalBorrows + borrowAmount + badDebt;\n if (nextTotalBorrows > borrowCap) {\n revert BorrowCapExceeded(vToken, borrowCap);\n }\n }\n\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n borrower,\n VToken(vToken),\n 0,\n borrowAmount,\n _getCollateralFactor\n );\n\n if (snapshot.shortfall > 0) {\n revert InsufficientLiquidity();\n }\n\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\n }\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 borrower The account which would borrowed the asset\n * @custom:error ActionPaused error is thrown if repayments are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:access Not restricted\n */\n function preRepayHook(address vToken, address borrower) external override {\n _checkActionPauseState(vToken, Action.REPAY);\n\n oracle.updatePrice(vToken);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\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 borrower The address of the borrower\n * @param repayAmount The amount of underlying being repaid\n * @param skipLiquidityCheck Allows the borrow to be liquidated regardless of the account liquidity\n * @custom:error ActionPaused error is thrown if liquidations are paused in this market\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\n * @custom:error TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor\n * @custom:error MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations\n * @custom:error InsufficientShortfall is thrown when trying to liquidate a healthy account\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n */\n function preLiquidateHook(\n address vTokenBorrowed,\n address vTokenCollateral,\n address borrower,\n uint256 repayAmount,\n bool skipLiquidityCheck\n ) external override {\n // Pause Action.LIQUIDATE on BORROWED TOKEN to prevent liquidating it.\n // If we want to pause liquidating to vTokenCollateral, we should pause\n // Action.SEIZE on it\n _checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\n\n // Update the prices of tokens\n updatePrices(borrower);\n\n if (!markets[vTokenBorrowed].isListed) {\n revert MarketNotListed(address(vTokenBorrowed));\n }\n if (!markets[vTokenCollateral].isListed) {\n revert MarketNotListed(address(vTokenCollateral));\n }\n\n uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\n\n /* Allow accounts to be liquidated if it is a forced liquidation */\n if (skipLiquidityCheck || isForcedLiquidationEnabled[vTokenBorrowed]) {\n if (repayAmount > borrowBalance) {\n revert TooMuchRepay();\n }\n return;\n }\n\n /* The borrower must have shortfall and collateral > threshold in order to be liquidatable */\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral <= minLiquidatableCollateral) {\n /* The liquidator should use either liquidateAccount or healAccount */\n revert MinimalCollateralViolated(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n /* The liquidator may not repay more than what is allowed by the closeFactor */\n uint256 maxClose = mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance);\n if (repayAmount > maxClose) {\n revert TooMuchRepay();\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 seizerContract Contract that tries to seize the asset (either borrowed vToken or Comptroller)\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @custom:error ActionPaused error is thrown if seizing this type of collateral is paused\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\n * @custom:error ComptrollerMismatch error is when seizer contract or seized asset belong to different pools\n * @custom:access Not restricted\n */\n function preSeizeHook(\n address vTokenCollateral,\n address seizerContract,\n address liquidator,\n address borrower\n ) external override {\n // Pause Action.SEIZE on COLLATERAL to prevent seizing it.\n // If we want to pause liquidating vTokenBorrowed, we should pause\n // Action.LIQUIDATE on it\n _checkActionPauseState(vTokenCollateral, Action.SEIZE);\n\n Market storage market = markets[vTokenCollateral];\n\n if (!market.isListed) {\n revert MarketNotListed(vTokenCollateral);\n }\n\n if (seizerContract == address(this)) {\n // If Comptroller is the seizer, just check if collateral's comptroller\n // is equal to the current address\n if (address(VToken(vTokenCollateral).comptroller()) != address(this)) {\n revert ComptrollerMismatch();\n }\n } else {\n // If the seizer is not the Comptroller, check that the seizer is a\n // listed market, and that the markets' comptrollers match\n if (!markets[seizerContract].isListed) {\n revert MarketNotListed(seizerContract);\n }\n if (VToken(vTokenCollateral).comptroller() != VToken(seizerContract).comptroller()) {\n revert ComptrollerMismatch();\n }\n }\n\n if (!market.accountMembership[borrower]) {\n revert MarketNotCollateral(vTokenCollateral, borrower);\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vTokenCollateral);\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, borrower);\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, liquidator);\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external override {\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 _checkRedeemAllowed(vToken, src, transferTokens);\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, src);\n rewardsDistributor.distributeSupplierRewardToken(vToken, dst);\n }\n }\n\n /*** Pool-level operations ***/\n\n /**\n * @notice Seizes all the remaining collateral, makes msg.sender repay the existing\n * borrows, and treats the rest of the debt as bad debt (for each market).\n * The sender has to repay a certain percentage of the debt, computed as\n * collateral / (borrows * liquidationIncentive).\n * @param user account to heal\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for healing\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function healAccount(address user) external {\n VToken[] memory userAssets = getAssetsIn(user);\n uint256 userAssetsCount = userAssets.length;\n\n address liquidator = msg.sender;\n {\n ResilientOracleInterface oracle_ = oracle;\n // We need all user's markets to be fresh for the computations to be correct\n for (uint256 i; i < userAssetsCount; ++i) {\n userAssets[i].accrueInterest();\n oracle_.updatePrice(address(userAssets[i]));\n }\n }\n\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(user, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n // percentage = collateral / (borrows * liquidation incentive)\n Exp memory collateral = Exp({ mantissa: snapshot.totalCollateral });\n Exp memory scaledBorrows = mul_(\n Exp({ mantissa: snapshot.borrows }),\n Exp({ mantissa: liquidationIncentiveMantissa })\n );\n\n Exp memory percentage = div_(collateral, scaledBorrows);\n if (lessThanExp(Exp({ mantissa: MANTISSA_ONE }), percentage)) {\n revert CollateralExceedsThreshold(scaledBorrows.mantissa, collateral.mantissa);\n }\n\n for (uint256 i; i < userAssetsCount; ++i) {\n VToken market = userAssets[i];\n\n (uint256 tokens, uint256 borrowBalance, ) = _safeGetAccountSnapshot(market, user);\n uint256 repaymentAmount = mul_ScalarTruncate(percentage, borrowBalance);\n\n // Seize the entire collateral\n if (tokens != 0) {\n market.seize(liquidator, user, tokens);\n }\n // Repay a certain percentage of the borrow, forgive the rest\n if (borrowBalance != 0) {\n market.healBorrow(liquidator, user, repaymentAmount);\n }\n }\n }\n\n /**\n * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than\n * a predefined threshold, and the account collateral can be seized to cover all borrows. If\n * the collateral is higher than the threshold, use regular liquidations. If the collateral is\n * below the threshold, and the account is insolvent, use healAccount.\n * @param borrower the borrower address\n * @param orders an array of liquidation orders\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation\n * @custom:error InsufficientCollateral error is thrown when there is not enough collateral to cover the debt\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function liquidateAccount(address borrower, LiquidationOrder[] calldata orders) external {\n // We will accrue interest and update the oracle prices later during the liquidation\n\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\n // You should use the regular vToken.liquidateBorrow(...) call\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n uint256 collateralToSeize = mul_ScalarTruncate(\n Exp({ mantissa: liquidationIncentiveMantissa }),\n snapshot.borrows\n );\n if (collateralToSeize >= snapshot.totalCollateral) {\n // There is not enough collateral to seize. Use healBorrow to repay some part of the borrow\n // and record bad debt.\n revert InsufficientCollateral(collateralToSeize, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n uint256 ordersCount = orders.length;\n\n _ensureMaxLoops(ordersCount / 2);\n\n for (uint256 i; i < ordersCount; ++i) {\n if (!markets[address(orders[i].vTokenBorrowed)].isListed) {\n revert MarketNotListed(address(orders[i].vTokenBorrowed));\n }\n if (!markets[address(orders[i].vTokenCollateral)].isListed) {\n revert MarketNotListed(address(orders[i].vTokenCollateral));\n }\n\n LiquidationOrder calldata order = orders[i];\n order.vTokenBorrowed.forceLiquidateBorrow(\n msg.sender,\n borrower,\n order.repayAmount,\n order.vTokenCollateral,\n true\n );\n }\n\n VToken[] memory borrowMarkets = getAssetsIn(borrower);\n uint256 marketsCount = borrowMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower);\n require(borrowBalance == 0, \"Nonzero borrow balance after liquidation\");\n }\n }\n\n /**\n * @notice Sets the closeFactor to use when liquidating borrows\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\n * @custom:event Emits NewCloseFactor on success\n * @custom:access Controlled by AccessControlManager\n */\n function setCloseFactor(uint256 newCloseFactorMantissa) external {\n _checkAccessAllowed(\"setCloseFactor(uint256)\");\n require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, \"Close factor greater than maximum close factor\");\n require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, \"Close factor smaller than minimum close factor\");\n\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\n closeFactorMantissa = newCloseFactorMantissa;\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\n }\n\n /**\n * @notice Sets the collateralFactor for a market\n * @dev This function is restricted by the AccessControlManager\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 * @custom:event Emits NewCollateralFactor when collateral factor is updated\n * and NewLiquidationThreshold when liquidation threshold is updated\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InvalidCollateralFactor error is thrown when collateral factor is too high\n * @custom:error InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor\n * @custom:error PriceError is thrown when the oracle returns an invalid price for the asset\n * @custom:access Controlled by AccessControlManager\n */\n function setCollateralFactor(\n VToken vToken,\n uint256 newCollateralFactorMantissa,\n uint256 newLiquidationThresholdMantissa\n ) external {\n _checkAccessAllowed(\"setCollateralFactor(address,uint256,uint256)\");\n\n // Verify market is listed\n Market storage market = markets[address(vToken)];\n if (!market.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n // Check collateral factor <= 0.9\n if (newCollateralFactorMantissa > MAX_COLLATERAL_FACTOR_MANTISSA) {\n revert InvalidCollateralFactor();\n }\n\n // Ensure that liquidation threshold <= 1\n if (newLiquidationThresholdMantissa > MANTISSA_ONE) {\n revert InvalidLiquidationThreshold();\n }\n\n // Ensure that liquidation threshold >= CF\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\n revert InvalidLiquidationThreshold();\n }\n\n // If collateral factor != 0, fail if price == 0\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\n revert PriceError(address(vToken));\n }\n\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\n market.collateralFactorMantissa = newCollateralFactorMantissa;\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\n }\n\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\n emit NewLiquidationThreshold(vToken, oldLiquidationThresholdMantissa, newLiquidationThresholdMantissa);\n }\n }\n\n /**\n * @notice Sets liquidationIncentive\n * @dev This function is restricted by the AccessControlManager\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\n * @custom:event Emits NewLiquidationIncentive on success\n * @custom:access Controlled by AccessControlManager\n */\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external {\n require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, \"liquidation incentive should be greater than 1e18\");\n\n _checkAccessAllowed(\"setLiquidationIncentive(uint256)\");\n\n // Save current value for use in log\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\n\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\n /**\n * @notice Add the market to the markets mapping and set it as listed\n * @dev Only callable by the PoolRegistry\n * @param vToken The address of the market (token) to list\n * @custom:error MarketAlreadyListed is thrown if the market is already listed in this pool\n * @custom:access Only PoolRegistry\n */\n function supportMarket(VToken vToken) external {\n _checkSenderIs(poolRegistry);\n\n if (markets[address(vToken)].isListed) {\n revert MarketAlreadyListed(address(vToken));\n }\n\n require(vToken.isVToken(), \"Comptroller: Invalid vToken\"); // Sanity check to make sure its really a VToken\n\n Market storage newMarket = markets[address(vToken)];\n newMarket.isListed = true;\n newMarket.collateralFactorMantissa = 0;\n newMarket.liquidationThresholdMantissa = 0;\n\n _addMarket(address(vToken));\n\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n rewardsDistributors[i].initializeMarket(address(vToken));\n }\n\n emit MarketSupported(vToken);\n }\n\n /**\n * @notice Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\n * @dev This function is restricted by the AccessControlManager\n * @dev A borrow cap of type(uint256).max corresponds to unlimited borrowing.\n * @dev Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed\n until the total borrows amount goes below the new borrow cap\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 type(uint256).max corresponds to unlimited borrowing.\n * @custom:access Controlled by AccessControlManager\n */\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\n _checkAccessAllowed(\"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 _ensureMaxLoops(numMarkets);\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 * @notice Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\n * @dev This function is restricted by the AccessControlManager\n * @dev A supply cap of type(uint256).max corresponds to unlimited supply.\n * @dev Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed\n until the total supplies amount goes below the new supply cap\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 type(uint256).max corresponds to unlimited supply.\n * @custom:access Controlled by AccessControlManager\n */\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\n _checkAccessAllowed(\"setMarketSupplyCaps(address[],uint256[])\");\n uint256 vTokensCount = vTokens.length;\n\n require(vTokensCount != 0, \"invalid number of markets\");\n require(vTokensCount == newSupplyCaps.length, \"invalid number of markets\");\n\n _ensureMaxLoops(vTokensCount);\n\n for (uint256 i; i < vTokensCount; ++i) {\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\n }\n }\n\n /**\n * @notice Pause/unpause specified actions\n * @dev This function is restricted by the AccessControlManager\n * @param marketsList Markets to pause/unpause the actions on\n * @param actionsList List of action ids to pause/unpause\n * @param paused The new paused state (true=paused, false=unpaused)\n * @custom:access Controlled by AccessControlManager\n */\n function setActionsPaused(VToken[] calldata marketsList, Action[] calldata actionsList, bool paused) external {\n _checkAccessAllowed(\"setActionsPaused(address[],uint256[],bool)\");\n\n uint256 marketsCount = marketsList.length;\n uint256 actionsCount = actionsList.length;\n\n _ensureMaxLoops(marketsCount * actionsCount);\n\n for (uint256 marketIdx; marketIdx < marketsCount; ++marketIdx) {\n for (uint256 actionIdx; actionIdx < actionsCount; ++actionIdx) {\n _setActionPaused(address(marketsList[marketIdx]), actionsList[actionIdx], paused);\n }\n }\n }\n\n /**\n * @notice Set the given collateral threshold for non-batch liquidations. Regular liquidations\n * will fail if the collateral amount is less than this threshold. Liquidators should use batch\n * operations like liquidateAccount or healAccount.\n * @dev This function is restricted by the AccessControlManager\n * @param newMinLiquidatableCollateral The new min liquidatable collateral (in USD).\n * @custom:access Controlled by AccessControlManager\n */\n function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external {\n _checkAccessAllowed(\"setMinLiquidatableCollateral(uint256)\");\n\n uint256 oldMinLiquidatableCollateral = minLiquidatableCollateral;\n minLiquidatableCollateral = newMinLiquidatableCollateral;\n emit NewMinLiquidatableCollateral(oldMinLiquidatableCollateral, newMinLiquidatableCollateral);\n }\n\n /**\n * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor\n * contracts with the same rewardToken, and there could be overlaping among them considering the last reward slot (block or second)\n * @dev Only callable by the admin\n * @param _rewardsDistributor Address of the RewardDistributor contract to add\n * @custom:access Only Governance\n * @custom:event Emits NewRewardsDistributor with distributor address\n */\n function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner {\n require(!rewardsDistributorExists[address(_rewardsDistributor)], \"already exists\");\n\n uint256 rewardsDistributorsLen = rewardsDistributors.length;\n _ensureMaxLoops(rewardsDistributorsLen + 1);\n\n rewardsDistributors.push(_rewardsDistributor);\n rewardsDistributorExists[address(_rewardsDistributor)] = true;\n\n uint256 marketsCount = allMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n _rewardsDistributor.initializeMarket(address(allMarkets[i]));\n }\n\n emit NewRewardsDistributor(address(_rewardsDistributor), address(_rewardsDistributor.rewardToken()));\n }\n\n /**\n * @notice Sets a new price oracle for the Comptroller\n * @dev Only callable by the admin\n * @param newOracle Address of the new price oracle to set\n * @custom:event Emits NewPriceOracle on success\n * @custom:error ZeroAddressNotAllowed is thrown when the new oracle address is zero\n */\n function setPriceOracle(ResilientOracleInterface newOracle) external onlyOwner {\n ensureNonzeroAddress(address(newOracle));\n\n ResilientOracleInterface oldOracle = oracle;\n oracle = newOracle;\n emit NewPriceOracle(oldOracle, newOracle);\n }\n\n /**\n * @notice Set the for loop iteration limit to avoid DOS\n * @param limit Limit for the max loops can execute at a time\n */\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\n _setMaxLoopsLimit(limit);\n }\n\n /**\n * @notice Sets the prime token contract for the comptroller\n * @param _prime Address of the Prime contract\n */\n function setPrimeToken(IPrime _prime) external onlyOwner {\n ensureNonzeroAddress(address(_prime));\n\n emit NewPrimeToken(prime, _prime);\n prime = _prime;\n }\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 * @param vTokenBorrowed Borrowed vToken\n * @param enable Whether to enable forced liquidations\n */\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\n _checkAccessAllowed(\"setForcedLiquidation(address,bool)\");\n ensureNonzeroAddress(vTokenBorrowed);\n\n if (!markets[vTokenBorrowed].isListed) {\n revert MarketNotListed(vTokenBorrowed);\n }\n\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\n }\n\n /**\n * @notice Determine the current account liquidity with respect to liquidation threshold requirements\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\n * @param account The account get liquidity for\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Account liquidity in excess of liquidation threshold requirements,\n * @return shortfall Account shortfall below liquidation threshold requirements\n */\n function getAccountLiquidity(\n address account\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getLiquidationThreshold);\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\n }\n\n /**\n * @notice Determine the current account liquidity with respect to collateral requirements\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\n * @param account The account get liquidity for\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Account liquidity in excess of collateral requirements,\n * @return shortfall Account shortfall below collateral requirements\n */\n function getBorrowingPower(\n address account\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getCollateralFactor);\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\n }\n\n /**\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Hypothetical account liquidity in excess of collateral requirements,\n * @return shortfall 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 error, uint256 liquidity, uint256 shortfall) {\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n account,\n VToken(vTokenModify),\n redeemTokens,\n borrowAmount,\n _getCollateralFactor\n );\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\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 markets The list of market addresses\n */\n function getAllMarkets() external view override returns (VToken[] memory) {\n return allMarkets;\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 /*** Assets You Are In ***/\n\n /**\n * @notice Returns whether the given account is entered in a given market\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 market specified, 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 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 error Always NO_ERROR for compatibility with Venus core tooling\n * @return tokensToSeize Number of vTokenCollateral tokens to be seized in a liquidation\n * @custom:error PriceError if the oracle returns an invalid price\n */\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view override returns (uint256 error, uint256 tokensToSeize) {\n /* Read oracle prices for borrowed and collateral markets */\n uint256 priceBorrowedMantissa = _safeGetUnderlyingPrice(VToken(vTokenBorrowed));\n uint256 priceCollateralMantissa = _safeGetUnderlyingPrice(VToken(vTokenCollateral));\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 uint256 exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\n uint256 seizeTokens;\n Exp memory numerator;\n Exp memory denominator;\n Exp memory ratio;\n\n numerator = mul_(Exp({ mantissa: liquidationIncentiveMantissa }), Exp({ mantissa: priceBorrowedMantissa }));\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\n ratio = div_(numerator, denominator);\n\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\n\n return (NO_ERROR, seizeTokens);\n }\n\n /**\n * @notice Returns reward speed given a vToken\n * @param vToken The vToken to get the reward speeds for\n * @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors\n */\n function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {\n uint256 rewardsDistributorsLength = rewardsDistributors.length;\n rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);\n for (uint256 i; i < rewardsDistributorsLength; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n address rewardToken = address(rewardsDistributor.rewardToken());\n rewardSpeeds[i] = RewardSpeeds({\n rewardToken: rewardToken,\n supplySpeed: rewardsDistributor.rewardTokenSupplySpeeds(vToken),\n borrowSpeed: rewardsDistributor.rewardTokenBorrowSpeeds(vToken)\n });\n }\n return rewardSpeeds;\n }\n\n /**\n * @notice Return all reward distributors for this pool\n * @return Array of RewardDistributor addresses\n */\n function getRewardDistributors() external view returns (RewardsDistributor[] memory) {\n return rewardsDistributors;\n }\n\n /**\n * @notice A marker method that returns true for a valid Comptroller contract\n * @return Always true\n */\n function isComptroller() external pure override returns (bool) {\n return true;\n }\n\n /**\n * @notice Update the prices of all the tokens associated with the provided account\n * @param account Address of the account to get associated tokens with\n */\n function updatePrices(address account) public {\n VToken[] memory vTokens = getAssetsIn(account);\n uint256 vTokensCount = vTokens.length;\n\n ResilientOracleInterface oracle_ = oracle;\n\n for (uint256 i; i < vTokensCount; ++i) {\n oracle_.updatePrice(address(vTokens[i]));\n }\n }\n\n /**\n * @notice Checks if a certain action is paused on a market\n * @param market vToken address\n * @param action Action to check\n * @return paused True if the action is paused otherwise false\n */\n function actionPaused(address market, Action action) public view returns (bool) {\n return _actionPaused[market][action];\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 list with the assets the account has entered\n */\n function getAssetsIn(address account) public 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 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 */\n function _addToMarket(VToken vToken, address borrower) internal {\n _checkActionPauseState(address(vToken), Action.ENTER_MARKET);\n Market storage marketToJoin = markets[address(vToken)];\n\n if (!marketToJoin.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n if (marketToJoin.accountMembership[borrower]) {\n // already joined\n return;\n }\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\n /**\n * @notice Internal function to validate that a market hasn't already been added\n * and if it hasn't adds it\n * @param vToken The market to support\n */\n function _addMarket(address vToken) internal {\n uint256 marketsCount = allMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n if (allMarkets[i] == VToken(vToken)) {\n revert MarketAlreadyListed(vToken);\n }\n }\n allMarkets.push(VToken(vToken));\n marketsCount = allMarkets.length;\n _ensureMaxLoops(marketsCount);\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 _setActionPaused(address market, Action action, bool paused) internal {\n require(markets[market].isListed, \"cannot pause a market that is not listed\");\n _actionPaused[market][action] = paused;\n emit ActionPausedMarket(VToken(market), action, paused);\n }\n\n /**\n * @dev Internal function to check that vTokens can be safely redeemed for the underlying asset.\n * @param vToken Address of the vTokens to redeem\n * @param redeemer Account redeeming the tokens\n * @param redeemTokens The number of tokens to redeem\n */\n function _checkRedeemAllowed(address vToken, address redeemer, uint256 redeemTokens) internal {\n Market storage market = markets[vToken];\n\n if (!market.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\n if (!market.accountMembership[redeemer]) {\n return;\n }\n\n // Update the prices of tokens\n updatePrices(redeemer);\n\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n redeemer,\n VToken(vToken),\n redeemTokens,\n 0,\n _getCollateralFactor\n );\n if (snapshot.shortfall > 0) {\n revert InsufficientLiquidity();\n }\n }\n\n /**\n * @notice Get the total collateral, weighted collateral, borrow balance, liquidity, shortfall\n * @param account The account to get the snapshot for\n * @param weight The function to compute the weight of the collateral – either collateral factor or\n * liquidation threshold. Accepts the address of the vToken and returns the weight as Exp.\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\n * without calculating accumulated interest.\n * @return snapshot Account liquidity snapshot\n */\n function _getCurrentLiquiditySnapshot(\n address account,\n function(VToken) internal view returns (Exp memory) weight\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\n return _getHypotheticalLiquiditySnapshot(account, VToken(address(0)), 0, 0, weight);\n }\n\n /**\n * @notice Determine what the supply/borrow balances 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 weight The function to compute the weight of the collateral – either collateral factor or\n liquidation threshold. Accepts the address of the VToken and returns the weight\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\n * without calculating accumulated interest.\n * @return snapshot Account liquidity snapshot\n */\n function _getHypotheticalLiquiditySnapshot(\n address account,\n VToken vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount,\n function(VToken) internal view returns (Exp memory) weight\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\n // For each asset the account is in\n VToken[] memory assets = getAssetsIn(account);\n uint256 assetsCount = assets.length;\n\n for (uint256 i; i < assetsCount; ++i) {\n VToken asset = assets[i];\n\n // Read the balances and exchange rate from the vToken\n (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) = _safeGetAccountSnapshot(\n asset,\n account\n );\n\n // Get the normalized price of the asset\n Exp memory oraclePrice = Exp({ mantissa: _safeGetUnderlyingPrice(asset) });\n\n // Pre-compute conversion factors from vTokens -> usd\n Exp memory vTokenPrice = mul_(Exp({ mantissa: exchangeRateMantissa }), oraclePrice);\n Exp memory weightedVTokenPrice = mul_(weight(asset), vTokenPrice);\n\n // weightedCollateral += weightedVTokenPrice * vTokenBalance\n snapshot.weightedCollateral = mul_ScalarTruncateAddUInt(\n weightedVTokenPrice,\n vTokenBalance,\n snapshot.weightedCollateral\n );\n\n // totalCollateral += vTokenPrice * vTokenBalance\n snapshot.totalCollateral = mul_ScalarTruncateAddUInt(vTokenPrice, vTokenBalance, snapshot.totalCollateral);\n\n // borrows += oraclePrice * borrowBalance\n snapshot.borrows = mul_ScalarTruncateAddUInt(oraclePrice, borrowBalance, snapshot.borrows);\n\n // Calculate effects of interacting with vTokenModify\n if (asset == vTokenModify) {\n // redeem effect\n // effects += tokensToDenom * redeemTokens\n snapshot.effects = mul_ScalarTruncateAddUInt(weightedVTokenPrice, redeemTokens, snapshot.effects);\n\n // borrow effect\n // effects += oraclePrice * borrowAmount\n snapshot.effects = mul_ScalarTruncateAddUInt(oraclePrice, borrowAmount, snapshot.effects);\n }\n }\n\n uint256 borrowPlusEffects = snapshot.borrows + snapshot.effects;\n // These are safe, as the underflow condition is checked first\n unchecked {\n if (snapshot.weightedCollateral > borrowPlusEffects) {\n snapshot.liquidity = snapshot.weightedCollateral - borrowPlusEffects;\n snapshot.shortfall = 0;\n } else {\n snapshot.liquidity = 0;\n snapshot.shortfall = borrowPlusEffects - snapshot.weightedCollateral;\n }\n }\n\n return snapshot;\n }\n\n /**\n * @dev Retrieves price from oracle for an asset and checks it is nonzero\n * @param asset Address for asset to query price\n * @return Underlying price\n */\n function _safeGetUnderlyingPrice(VToken asset) internal view returns (uint256) {\n uint256 oraclePriceMantissa = oracle.getUnderlyingPrice(address(asset));\n if (oraclePriceMantissa == 0) {\n revert PriceError(address(asset));\n }\n return oraclePriceMantissa;\n }\n\n /**\n * @dev Return collateral factor for a market\n * @param asset Address for asset\n * @return Collateral factor as exponential\n */\n function _getCollateralFactor(VToken asset) internal view returns (Exp memory) {\n return Exp({ mantissa: markets[address(asset)].collateralFactorMantissa });\n }\n\n /**\n * @dev Retrieves liquidation threshold for a market as an exponential\n * @param asset Address for asset to liquidation threshold\n * @return Liquidation threshold as exponential\n */\n function _getLiquidationThreshold(VToken asset) internal view returns (Exp memory) {\n return Exp({ mantissa: markets[address(asset)].liquidationThresholdMantissa });\n }\n\n /**\n * @dev Returns supply and borrow balances of user in vToken, reverts on failure\n * @param vToken Market to query\n * @param user Account address\n * @return vTokenBalance Balance of vTokens, the same as vToken.balanceOf(user)\n * @return borrowBalance Borrowed amount, including the interest\n * @return exchangeRateMantissa Stored exchange rate\n */\n function _safeGetAccountSnapshot(\n VToken vToken,\n address user\n ) internal view returns (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) {\n uint256 err;\n (err, vTokenBalance, borrowBalance, exchangeRateMantissa) = vToken.getAccountSnapshot(user);\n if (err != 0) {\n revert SnapshotError(address(vToken), user);\n }\n return (vTokenBalance, borrowBalance, exchangeRateMantissa);\n }\n\n /// @notice Reverts if the call is not from expectedSender\n /// @param expectedSender Expected transaction sender\n function _checkSenderIs(address expectedSender) internal view {\n if (msg.sender != expectedSender) {\n revert UnexpectedSender(expectedSender, msg.sender);\n }\n }\n\n /// @notice Reverts if a certain action is paused on a market\n /// @param market Market to check\n /// @param action Action to check\n function _checkActionPauseState(address market, Action action) private view {\n if (actionPaused(market, action)) {\n revert ActionPaused(market, action);\n }\n }\n}\n" + }, + "contracts/ComptrollerInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.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\n/**\n * @title ComptrollerInterface\n * @author Venus\n * @notice Interface implemented by the `Comptroller` contract.\n */\ninterface ComptrollerInterface {\n /*** Assets You Are In ***/\n\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\n\n function exitMarket(address vToken) external returns (uint256);\n\n /*** Policy Hooks ***/\n\n function preMintHook(address vToken, address minter, uint256 mintAmount) external;\n\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external;\n\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external;\n\n function preRepayHook(address vToken, address borrower) external;\n\n function preLiquidateHook(\n address vTokenBorrowed,\n address vTokenCollateral,\n address borrower,\n uint256 repayAmount,\n bool skipLiquidityCheck\n ) external;\n\n function preSeizeHook(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower\n ) external;\n\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\n\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\n\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\n\n function repayBorrowVerify(\n address vToken,\n address payer,\n address borrower,\n uint repayAmount,\n uint borrowerIndex\n ) external;\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 seizeVerify(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint seizeTokens\n ) external;\n\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\n\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external;\n\n function isComptroller() external view returns (bool);\n\n /*** Liquidity/Liquidation Calculations ***/\n\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 repayAmount\n ) external view returns (uint256, uint256);\n\n function getAllMarkets() external view returns (VToken[] memory);\n\n function actionPaused(address market, Action action) external view returns (bool);\n}\n\n/**\n * @title ComptrollerViewInterface\n * @author Venus\n * @notice Interface implemented by the `Comptroller` contract, including only some util view functions.\n */\ninterface ComptrollerViewInterface {\n function markets(address) external view returns (bool, uint256);\n\n function oracle() external view returns (ResilientOracleInterface);\n\n function getAssetsIn(address) external view returns (VToken[] memory);\n\n function closeFactorMantissa() external view returns (uint256);\n\n function liquidationIncentiveMantissa() external view returns (uint256);\n\n function minLiquidatableCollateral() external view returns (uint256);\n\n function getRewardDistributors() external view returns (RewardsDistributor[] memory);\n\n function getAllMarkets() external view returns (VToken[] memory);\n\n function borrowCaps(address) external view returns (uint256);\n\n function supplyCaps(address) external view returns (uint256);\n\n function approvedDelegates(address user, address delegate) external view returns (bool);\n}\n" + }, + "contracts/ComptrollerStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.sol\";\nimport { IPrime } from \"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\";\nimport { Action } from \"./ComptrollerInterface.sol\";\n\n/**\n * @title ComptrollerStorage\n * @author Venus\n * @notice Storage layout for the `Comptroller` contract.\n */\ncontract ComptrollerStorage {\n struct LiquidationOrder {\n VToken vTokenCollateral;\n VToken vTokenBorrowed;\n uint256 repayAmount;\n }\n\n struct AccountLiquiditySnapshot {\n uint256 totalCollateral;\n uint256 weightedCollateral;\n uint256 borrows;\n uint256 effects;\n uint256 liquidity;\n uint256 shortfall;\n }\n\n struct RewardSpeeds {\n address rewardToken;\n uint256 supplySpeed;\n uint256 borrowSpeed;\n }\n\n struct Market {\n // Whether or not this market is listed\n bool isListed;\n // 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 uint256 collateralFactorMantissa;\n // 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 uint256 liquidationThresholdMantissa;\n // Per-market mapping of \"accounts in this asset\"\n mapping(address => bool) accountMembership;\n }\n\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 Per-account mapping of \"assets you are in\"\n */\n mapping(address => VToken[]) public accountAssets;\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 /// @notice A list of all markets\n VToken[] public allMarkets;\n\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\n mapping(address => uint256) public borrowCaps;\n\n /// @notice Minimal collateral required for regular (non-batch) liquidations\n uint256 public minLiquidatableCollateral;\n\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\n mapping(address => uint256) public supplyCaps;\n\n /// @notice True if a certain action is paused on a certain market\n mapping(address => mapping(Action => bool)) internal _actionPaused;\n\n // List of Reward Distributors added\n RewardsDistributor[] internal rewardsDistributors;\n\n // Used to check if rewards distributor is added\n mapping(address => bool) internal rewardsDistributorExists;\n\n /// @notice Flag indicating whether forced liquidation enabled for a market\n mapping(address => bool) public isForcedLiquidationEnabled;\n\n uint256 internal constant NO_ERROR = 0;\n\n // closeFactorMantissa must be strictly greater than this value\n uint256 internal constant MIN_CLOSE_FACTOR_MANTISSA = 0.05e18; // 0.05\n\n // closeFactorMantissa must not exceed this value\n uint256 internal constant MAX_CLOSE_FACTOR_MANTISSA = 0.9e18; // 0.9\n\n // No collateralFactorMantissa may exceed this value\n uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.95e18; // 0.95\n\n /// Prime token address\n IPrime public prime;\n\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 /**\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[47] private __gap;\n}\n" + }, + "contracts/ErrorReporter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n/**\n * @title TokenErrorReporter\n * @author Venus\n * @notice Errors that can be thrown by the `VToken` contract.\n */\ncontract TokenErrorReporter {\n uint256 public constant NO_ERROR = 0; // support legacy return codes\n\n error TransferNotAllowed();\n\n error MintFreshnessCheck();\n\n error RedeemFreshnessCheck();\n error RedeemTransferOutNotPossible();\n\n error BorrowFreshnessCheck();\n error BorrowCashNotAvailable();\n error DelegateNotApproved();\n\n error RepayBorrowFreshnessCheck();\n\n error HealBorrowUnauthorized();\n error ForceLiquidateBorrowUnauthorized();\n\n error LiquidateFreshnessCheck();\n error LiquidateCollateralFreshnessCheck();\n error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\n error LiquidateLiquidatorIsBorrower();\n error LiquidateCloseAmountIsZero();\n error LiquidateCloseAmountIsUintMax();\n\n error LiquidateSeizeLiquidatorIsBorrower();\n\n error ProtocolSeizeShareTooBig();\n\n error SetReserveFactorFreshCheck();\n error SetReserveFactorBoundsCheck();\n\n error AddReservesFactorFreshCheck(uint256 actualAddAmount);\n\n error ReduceReservesFreshCheck();\n error ReduceReservesCashNotAvailable();\n error ReduceReservesCashValidation();\n\n error SetInterestRateModelFreshCheck();\n}\n" + }, + "contracts/ExponentialNoError.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from \"./lib/constants.sol\";\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 struct Exp {\n uint256 mantissa;\n }\n\n struct Double {\n uint256 mantissa;\n }\n\n uint256 internal constant EXP_SCALE = EXP_SCALE_;\n uint256 internal constant DOUBLE_SCALE = 1e36;\n uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;\n uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;\n\n /**\n * @dev Truncates the given exp to a whole number value.\n * For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15\n */\n function truncate(Exp memory exp) internal pure returns (uint256) {\n // Note: We are not using careful math here as we're performing a division that cannot fail\n return exp.mantissa / EXP_SCALE;\n }\n\n /**\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\n */\n // solhint-disable-next-line func-name-mixedcase\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\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 // solhint-disable-next-line func-name-mixedcase\n function mul_ScalarTruncateAddUInt(Exp memory a, uint256 scalar, uint256 addend) internal pure returns (uint256) {\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 function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\n require(n <= type(uint224).max, errorMessage);\n return uint224(n);\n }\n\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\n require(n <= type(uint32).max, 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_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a + b;\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_(uint256 a, uint256 b) internal pure returns (uint256) {\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) / EXP_SCALE });\n }\n\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\n return Exp({ mantissa: mul_(a.mantissa, b) });\n }\n\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\n return mul_(a, b.mantissa) / EXP_SCALE;\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) / DOUBLE_SCALE });\n }\n\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: mul_(a.mantissa, b) });\n }\n\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\n return mul_(a, b.mantissa) / DOUBLE_SCALE;\n }\n\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a * b;\n }\n\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });\n }\n\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\n return Exp({ mantissa: div_(a.mantissa, b) });\n }\n\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\n return div_(mul_(a, EXP_SCALE), 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, DOUBLE_SCALE), b.mantissa) });\n }\n\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(a.mantissa, b) });\n }\n\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\n return div_(mul_(a, DOUBLE_SCALE), b.mantissa);\n }\n\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a / b;\n }\n\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });\n }\n}\n" + }, + "contracts/InterestRateModel.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n/**\n * @title Compound's InterestRateModel Interface\n * @author Compound\n */\nabstract contract InterestRateModel {\n /**\n * @notice Calculates the current borrow interest rate per slot (block or second)\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 amount of reserves the market has\n * @param badDebt The amount of badDebt in the market\n * @return The borrow rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\n */\n function getBorrowRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) external view virtual returns (uint256);\n\n /**\n * @notice Calculates the current supply interest rate per slot (block or second)\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 amount of reserves the market has\n * @param reserveFactorMantissa The current reserve factor the market has\n * @param badDebt The amount of badDebt in the market\n * @return The supply rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\n */\n function getSupplyRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 reserveFactorMantissa,\n uint256 badDebt\n ) external view virtual returns (uint256);\n\n /**\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\n * @return Always true\n */\n function isInterestRateModel() external pure virtual returns (bool) {\n return true;\n }\n}\n" + }, + "contracts/Lens/PoolLens.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IERC20Metadata } from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { ExponentialNoError } from \"../ExponentialNoError.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { Action, ComptrollerInterface, ComptrollerViewInterface } from \"../ComptrollerInterface.sol\";\nimport { PoolRegistryInterface } from \"../Pool/PoolRegistryInterface.sol\";\nimport { PoolRegistry } from \"../Pool/PoolRegistry.sol\";\nimport { RewardsDistributor } from \"../Rewards/RewardsDistributor.sol\";\nimport { TimeManagerV8 } from \"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\";\n\n/**\n * @title PoolLens\n * @author Venus\n * @notice The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information\n * for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be\n * looked up for specific pools and markets:\n- the vToken balance of a given user;\n- the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address;\n- the vToken address in a pool for a given asset;\n- a list of all pools that support an asset;\n- the underlying asset price of a vToken;\n- the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\n */\ncontract PoolLens is ExponentialNoError, TimeManagerV8 {\n /**\n * @dev Struct for PoolDetails.\n */\n struct PoolData {\n string name;\n address creator;\n address comptroller;\n uint256 blockPosted;\n uint256 timestampPosted;\n string category;\n string logoURL;\n string description;\n address priceOracle;\n uint256 closeFactor;\n uint256 liquidationIncentive;\n uint256 minLiquidatableCollateral;\n VTokenMetadata[] vTokens;\n }\n\n /**\n * @dev Struct for VToken.\n */\n struct VTokenMetadata {\n address vToken;\n uint256 exchangeRateCurrent;\n uint256 supplyRatePerBlockOrTimestamp;\n uint256 borrowRatePerBlockOrTimestamp;\n uint256 reserveFactorMantissa;\n uint256 supplyCaps;\n uint256 borrowCaps;\n uint256 totalBorrows;\n uint256 totalReserves;\n uint256 totalSupply;\n uint256 totalCash;\n bool isListed;\n uint256 collateralFactorMantissa;\n address underlyingAssetAddress;\n uint256 vTokenDecimals;\n uint256 underlyingDecimals;\n uint256 pausedActions;\n }\n\n /**\n * @dev Struct for VTokenBalance.\n */\n struct VTokenBalances {\n address vToken;\n uint256 balanceOf;\n uint256 borrowBalanceCurrent;\n uint256 balanceOfUnderlying;\n uint256 tokenBalance;\n uint256 tokenAllowance;\n }\n\n /**\n * @dev Struct for underlyingPrice of VToken.\n */\n struct VTokenUnderlyingPrice {\n address vToken;\n uint256 underlyingPrice;\n }\n\n /**\n * @dev Struct with pending reward info for a market.\n */\n struct PendingReward {\n address vTokenAddress;\n uint256 amount;\n }\n\n /**\n * @dev Struct with reward distribution totals for a single reward token and distributor.\n */\n struct RewardSummary {\n address distributorAddress;\n address rewardTokenAddress;\n uint256 totalRewards;\n PendingReward[] pendingRewards;\n }\n\n /**\n * @dev Struct used in RewardDistributor to save last updated market state.\n */\n struct RewardTokenState {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block number or timestamp the index was last updated at\n uint256 blockOrTimestamp;\n // The block number or timestamp at which to stop rewards\n uint256 lastRewardingBlockOrTimestamp;\n }\n\n /**\n * @dev Struct with bad debt of a market denominated\n */\n struct BadDebt {\n address vTokenAddress;\n uint256 badDebtUsd;\n }\n\n /**\n * @dev Struct with bad debt total denominated in usd for a pool and an array of BadDebt structs for each market\n */\n struct BadDebtSummary {\n address comptroller;\n uint256 totalBadDebtUsd;\n BadDebt[] badDebts;\n }\n\n /// @notice Address of the core pool comptroller (all markets are returned for this pool, including paused ones)\n address public immutable corePoolComptroller;\n\n /**\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\n * @param blocksPerYear_ The number of blocks per year\n * @param corePoolComptroller_ The address of the core pool comptroller\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor(\n bool timeBased_,\n uint256 blocksPerYear_,\n address corePoolComptroller_\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\n corePoolComptroller = corePoolComptroller_;\n }\n\n /**\n * @notice Queries the user's supply/borrow balances in vTokens\n * @param vTokens The list of vToken addresses\n * @param account The user Account\n * @return A list of structs containing balances data\n */\n function vTokenBalancesAll(VToken[] calldata vTokens, address account) external returns (VTokenBalances[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenBalances[] memory res = new VTokenBalances[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenBalances(vTokens[i], account);\n }\n return res;\n }\n\n /**\n * @notice Queries all pools with addtional details for each of them\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @return Arrays of all Venus pools' data\n */\n function getAllPools(address poolRegistryAddress) external view returns (PoolData[] memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n PoolRegistry.VenusPool[] memory venusPools = poolRegistryInterface.getAllPools();\n uint256 poolLength = venusPools.length;\n\n PoolData[] memory poolDataItems = new PoolData[](poolLength);\n\n for (uint256 i; i < poolLength; ++i) {\n PoolRegistry.VenusPool memory venusPool = venusPools[i];\n PoolData memory poolData = getPoolDataFromVenusPool(poolRegistryAddress, venusPool);\n poolDataItems[i] = poolData;\n }\n\n return poolDataItems;\n }\n\n /**\n * @notice Queries the details of a pool identified by Comptroller address\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param comptroller The Comptroller implementation address\n * @return PoolData structure containing the details of the pool\n */\n function getPoolByComptroller(\n address poolRegistryAddress,\n address comptroller\n ) external view returns (PoolData memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return getPoolDataFromVenusPool(poolRegistryAddress, poolRegistryInterface.getPoolByComptroller(comptroller));\n }\n\n /**\n * @notice Returns vToken holding the specified underlying asset in the specified pool\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param comptroller The pool comptroller\n * @param asset The underlyingAsset of VToken\n * @return Address of the vToken\n */\n function getVTokenForAsset(\n address poolRegistryAddress,\n address comptroller,\n address asset\n ) external view returns (address) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return poolRegistryInterface.getVTokenForAsset(comptroller, asset);\n }\n\n /**\n * @notice Returns all pools that support the specified underlying asset\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param asset The underlying asset of vToken\n * @return A list of Comptroller contracts\n */\n function getPoolsSupportedByAsset(\n address poolRegistryAddress,\n address asset\n ) external view returns (address[] memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return poolRegistryInterface.getPoolsSupportedByAsset(asset);\n }\n\n /**\n * @notice Returns the price data for the underlying assets of the specified vTokens\n * @param vTokens The list of vToken addresses\n * @return An array containing the price data for each asset\n */\n function vTokenUnderlyingPriceAll(\n VToken[] calldata vTokens\n ) external view returns (VTokenUnderlyingPrice[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenUnderlyingPrice[] memory res = new VTokenUnderlyingPrice[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenUnderlyingPrice(vTokens[i]);\n }\n return res;\n }\n\n /**\n * @notice Returns the pending rewards for a user for a given pool.\n * @param account The user account.\n * @param comptrollerAddress address\n * @return Pending rewards array\n */\n function getPendingRewards(\n address account,\n address comptrollerAddress\n ) external view returns (RewardSummary[] memory) {\n VToken[] memory markets = _getMarkets(ComptrollerInterface(comptrollerAddress));\n RewardsDistributor[] memory rewardsDistributors = ComptrollerViewInterface(comptrollerAddress)\n .getRewardDistributors();\n RewardSummary[] memory rewardSummary = new RewardSummary[](rewardsDistributors.length);\n for (uint256 i; i < rewardsDistributors.length; ++i) {\n RewardSummary memory reward;\n reward.distributorAddress = address(rewardsDistributors[i]);\n reward.rewardTokenAddress = address(rewardsDistributors[i].rewardToken());\n reward.totalRewards = rewardsDistributors[i].rewardTokenAccrued(account);\n reward.pendingRewards = _calculateNotDistributedAwards(account, markets, rewardsDistributors[i]);\n rewardSummary[i] = reward;\n }\n return rewardSummary;\n }\n\n /**\n * @notice Returns a summary of a pool's bad debt broken down by market\n *\n * @param comptrollerAddress Address of the comptroller\n *\n * @return badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and\n * a break down of bad debt by market\n */\n function getPoolBadDebt(address comptrollerAddress) external view returns (BadDebtSummary memory) {\n uint256 totalBadDebtUsd;\n\n // Get every listed market in the pool\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\n VToken[] memory markets = _getMarkets(ComptrollerInterface(comptrollerAddress));\n ResilientOracleInterface priceOracle = comptroller.oracle();\n\n BadDebt[] memory badDebts = new BadDebt[](markets.length);\n\n BadDebtSummary memory badDebtSummary;\n badDebtSummary.comptroller = comptrollerAddress;\n badDebtSummary.badDebts = badDebts;\n\n // // Calculate the bad debt is USD per market\n for (uint256 i; i < markets.length; ++i) {\n BadDebt memory badDebt;\n badDebt.vTokenAddress = address(markets[i]);\n badDebt.badDebtUsd =\n (VToken(address(markets[i])).badDebt() * priceOracle.getUnderlyingPrice(address(markets[i]))) /\n EXP_SCALE;\n badDebtSummary.badDebts[i] = badDebt;\n totalBadDebtUsd = totalBadDebtUsd + badDebt.badDebtUsd;\n }\n\n badDebtSummary.totalBadDebtUsd = totalBadDebtUsd;\n\n return badDebtSummary;\n }\n\n /**\n * @notice Queries the user's supply/borrow balances in the specified vToken\n * @param vToken vToken address\n * @param account The user Account\n * @return A struct containing the balances data\n */\n function vTokenBalances(VToken vToken, address account) public returns (VTokenBalances memory) {\n uint256 balanceOf = vToken.balanceOf(account);\n uint256 borrowBalanceCurrent = vToken.borrowBalanceCurrent(account);\n uint256 balanceOfUnderlying = vToken.balanceOfUnderlying(account);\n uint256 tokenBalance;\n uint256 tokenAllowance;\n\n IERC20 underlying = IERC20(vToken.underlying());\n tokenBalance = underlying.balanceOf(account);\n tokenAllowance = underlying.allowance(account, address(vToken));\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 Queries additional information for the pool\n * @param poolRegistryAddress Address of the PoolRegistry\n * @param venusPool The VenusPool Object from PoolRegistry\n * @return Enriched PoolData\n */\n function getPoolDataFromVenusPool(\n address poolRegistryAddress,\n PoolRegistry.VenusPool memory venusPool\n ) public view returns (PoolData memory) {\n // Get tokens in the Pool\n ComptrollerInterface comptrollerInstance = ComptrollerInterface(venusPool.comptroller);\n\n VToken[] memory vTokens = _getMarkets(comptrollerInstance);\n\n VTokenMetadata[] memory vTokenMetadataItems = vTokenMetadataAll(vTokens);\n\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n\n PoolRegistry.VenusPoolMetaData memory venusPoolMetaData = poolRegistryInterface.getVenusPoolMetadata(\n venusPool.comptroller\n );\n\n ComptrollerViewInterface comptrollerViewInstance = ComptrollerViewInterface(venusPool.comptroller);\n\n PoolData memory poolData = PoolData({\n name: venusPool.name,\n creator: venusPool.creator,\n comptroller: venusPool.comptroller,\n blockPosted: venusPool.blockPosted,\n timestampPosted: venusPool.timestampPosted,\n category: venusPoolMetaData.category,\n logoURL: venusPoolMetaData.logoURL,\n description: venusPoolMetaData.description,\n vTokens: vTokenMetadataItems,\n priceOracle: address(comptrollerViewInstance.oracle()),\n closeFactor: comptrollerViewInstance.closeFactorMantissa(),\n liquidationIncentive: comptrollerViewInstance.liquidationIncentiveMantissa(),\n minLiquidatableCollateral: comptrollerViewInstance.minLiquidatableCollateral()\n });\n\n return poolData;\n }\n\n /**\n * @notice Returns the metadata of VToken\n * @param vToken The address of vToken\n * @return VTokenMetadata struct\n */\n function vTokenMetadata(VToken vToken) public view returns (VTokenMetadata memory) {\n uint256 exchangeRateCurrent = vToken.exchangeRateStored();\n address comptrollerAddress = address(vToken.comptroller());\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\n (bool isListed, uint256 collateralFactorMantissa) = comptroller.markets(address(vToken));\n\n address underlyingAssetAddress = vToken.underlying();\n uint256 underlyingDecimals = IERC20Metadata(underlyingAssetAddress).decimals();\n\n uint256 pausedActions;\n for (uint8 i; i <= uint8(type(Action).max); ++i) {\n uint256 paused = ComptrollerInterface(comptrollerAddress).actionPaused(address(vToken), Action(i)) ? 1 : 0;\n pausedActions |= paused << i;\n }\n\n uint256 supplyRatePerBlock;\n\n if (vToken.totalSupply() > 0) {\n supplyRatePerBlock = vToken.supplyRatePerBlock();\n }\n\n return\n VTokenMetadata({\n vToken: address(vToken),\n exchangeRateCurrent: exchangeRateCurrent,\n supplyRatePerBlockOrTimestamp: supplyRatePerBlock,\n borrowRatePerBlockOrTimestamp: vToken.borrowRatePerBlock(),\n reserveFactorMantissa: vToken.reserveFactorMantissa(),\n supplyCaps: comptroller.supplyCaps(address(vToken)),\n borrowCaps: comptroller.borrowCaps(address(vToken)),\n totalBorrows: vToken.totalBorrows(),\n totalReserves: vToken.totalReserves(),\n totalSupply: vToken.totalSupply(),\n totalCash: vToken.getCash(),\n isListed: isListed,\n collateralFactorMantissa: collateralFactorMantissa,\n underlyingAssetAddress: underlyingAssetAddress,\n vTokenDecimals: vToken.decimals(),\n underlyingDecimals: underlyingDecimals,\n pausedActions: pausedActions\n });\n }\n\n /**\n * @notice Returns the metadata of all VTokens\n * @param vTokens The list of vToken addresses\n * @return An array of VTokenMetadata structs\n */\n function vTokenMetadataAll(VToken[] memory vTokens) public view returns (VTokenMetadata[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenMetadata[] memory res = new VTokenMetadata[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenMetadata(vTokens[i]);\n }\n return res;\n }\n\n /**\n * @notice Returns the price data for the underlying asset of the specified vToken\n * @param vToken vToken address\n * @return The price data for each asset\n */\n function vTokenUnderlyingPrice(VToken vToken) public view returns (VTokenUnderlyingPrice memory) {\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(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 Returns markets from a comptroller. For the core pool, all markets are returned.\n * For other pools, markets with zero internalCash are filtered.\n * @param comptroller The comptroller to query\n * @return An array of VToken addresses\n */\n function _getMarkets(ComptrollerInterface comptroller) internal view returns (VToken[] memory) {\n VToken[] memory allMarkets = comptroller.getAllMarkets();\n\n if (address(comptroller) == corePoolComptroller) {\n return allMarkets;\n }\n\n // Single-loop filter: pack active markets to the front of allMarkets\n uint256 count;\n uint256 len = allMarkets.length;\n for (uint256 i; i < len; ++i) {\n if (allMarkets[i].internalCash() > 0) {\n allMarkets[count] = allMarkets[i];\n ++count;\n }\n }\n\n // Trim the array to the active count\n assembly {\n mstore(allMarkets, count)\n }\n\n return allMarkets;\n }\n\n function _calculateNotDistributedAwards(\n address account,\n VToken[] memory markets,\n RewardsDistributor rewardsDistributor\n ) internal view returns (PendingReward[] memory) {\n PendingReward[] memory pendingRewards = new PendingReward[](markets.length);\n\n for (uint256 i; i < markets.length; ++i) {\n // Market borrow and supply state we will modify update in-memory, in order to not modify storage\n RewardTokenState memory borrowState;\n RewardTokenState memory supplyState;\n\n if (isTimeBased) {\n (\n borrowState.index,\n borrowState.blockOrTimestamp,\n borrowState.lastRewardingBlockOrTimestamp\n ) = rewardsDistributor.rewardTokenBorrowStateTimeBased(address(markets[i]));\n (\n supplyState.index,\n supplyState.blockOrTimestamp,\n supplyState.lastRewardingBlockOrTimestamp\n ) = rewardsDistributor.rewardTokenSupplyStateTimeBased(address(markets[i]));\n } else {\n (\n borrowState.index,\n borrowState.blockOrTimestamp,\n borrowState.lastRewardingBlockOrTimestamp\n ) = rewardsDistributor.rewardTokenBorrowState(address(markets[i]));\n (\n supplyState.index,\n supplyState.blockOrTimestamp,\n supplyState.lastRewardingBlockOrTimestamp\n ) = rewardsDistributor.rewardTokenSupplyState(address(markets[i]));\n }\n\n Exp memory marketBorrowIndex = Exp({ mantissa: markets[i].borrowIndex() });\n\n // Update market supply and borrow index in-memory\n updateMarketBorrowIndex(address(markets[i]), rewardsDistributor, borrowState, marketBorrowIndex);\n updateMarketSupplyIndex(address(markets[i]), rewardsDistributor, supplyState);\n\n // Calculate pending rewards\n uint256 borrowReward = calculateBorrowerReward(\n address(markets[i]),\n rewardsDistributor,\n account,\n borrowState,\n marketBorrowIndex\n );\n uint256 supplyReward = calculateSupplierReward(\n address(markets[i]),\n rewardsDistributor,\n account,\n supplyState\n );\n\n PendingReward memory pendingReward;\n pendingReward.vTokenAddress = address(markets[i]);\n pendingReward.amount = borrowReward + supplyReward;\n pendingRewards[i] = pendingReward;\n }\n return pendingRewards;\n }\n\n function updateMarketBorrowIndex(\n address vToken,\n RewardsDistributor rewardsDistributor,\n RewardTokenState memory borrowState,\n Exp memory marketBorrowIndex\n ) internal view {\n uint256 borrowSpeed = rewardsDistributor.rewardTokenBorrowSpeeds(vToken);\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n if (\n borrowState.lastRewardingBlockOrTimestamp > 0 &&\n blockNumberOrTimestamp > borrowState.lastRewardingBlockOrTimestamp\n ) {\n blockNumberOrTimestamp = borrowState.lastRewardingBlockOrTimestamp;\n }\n\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, borrowState.blockOrTimestamp);\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\n // Remove the total earned interest rate since the opening of the market from total borrows\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, borrowSpeed);\n Double memory ratio = borrowAmount > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\n } else if (deltaBlocksOrTimestamp > 0) {\n borrowState.blockOrTimestamp = blockNumberOrTimestamp;\n }\n }\n\n function updateMarketSupplyIndex(\n address vToken,\n RewardsDistributor rewardsDistributor,\n RewardTokenState memory supplyState\n ) internal view {\n uint256 supplySpeed = rewardsDistributor.rewardTokenSupplySpeeds(vToken);\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n if (\n supplyState.lastRewardingBlockOrTimestamp > 0 &&\n blockNumberOrTimestamp > supplyState.lastRewardingBlockOrTimestamp\n ) {\n blockNumberOrTimestamp = supplyState.lastRewardingBlockOrTimestamp;\n }\n\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, supplyState.blockOrTimestamp);\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\n uint256 supplyTokens = VToken(vToken).totalSupply();\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, supplySpeed);\n Double memory ratio = supplyTokens > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\n } else if (deltaBlocksOrTimestamp > 0) {\n supplyState.blockOrTimestamp = blockNumberOrTimestamp;\n }\n }\n\n function calculateBorrowerReward(\n address vToken,\n RewardsDistributor rewardsDistributor,\n address borrower,\n RewardTokenState memory borrowState,\n Exp memory marketBorrowIndex\n ) internal view returns (uint256) {\n Double memory borrowIndex = Double({ mantissa: borrowState.index });\n Double memory borrowerIndex = Double({\n mantissa: rewardsDistributor.rewardTokenBorrowerIndex(vToken, borrower)\n });\n if (borrowerIndex.mantissa == 0 && borrowIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\n // Covers the case where users borrowed tokens before the market's borrow state index was set\n borrowerIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\n }\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\n return borrowerDelta;\n }\n\n function calculateSupplierReward(\n address vToken,\n RewardsDistributor rewardsDistributor,\n address supplier,\n RewardTokenState memory supplyState\n ) internal view returns (uint256) {\n Double memory supplyIndex = Double({ mantissa: supplyState.index });\n Double memory supplierIndex = Double({\n mantissa: rewardsDistributor.rewardTokenSupplierIndex(vToken, supplier)\n });\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\n // Covers the case where users supplied tokens before the market's supply state index was set\n supplierIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\n }\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\n return supplierDelta;\n }\n}\n" + }, + "contracts/lib/constants.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\n/// @dev The approximate number of seconds per year\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\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" + }, + "contracts/lib/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 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" + }, + "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" + }, + "contracts/Pool/PoolRegistry.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\n\nimport { PoolRegistryInterface } from \"./PoolRegistryInterface.sol\";\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { ensureNonzeroAddress } from \"../lib/validators.sol\";\n\n/**\n * @title PoolRegistry\n * @author Venus\n * @notice The Isolated Pools architecture centers around the `PoolRegistry` contract. The `PoolRegistry` maintains a directory of isolated lending\n * pools and can perform actions like creating and registering new pools, adding new markets to existing pools, setting and updating the pool's required\n * metadata, and providing the getter methods to get information on the pools.\n *\n * Isolated lending has three main components: PoolRegistry, pools, and markets. The PoolRegistry is responsible for managing pools.\n * It can create new pools, update pool metadata and manage markets within pools. PoolRegistry contains getter methods to get the details of\n * any existing pool like `getVTokenForAsset` and `getPoolsSupportedByAsset`. It also contains methods for updating pool metadata (`updatePoolMetadata`)\n * and setting pool name (`setPoolName`).\n *\n * The directory of pools is managed through two mappings: `_poolByComptroller` which is a hashmap with the comptroller address as the key and `VenusPool` as\n * the value and `_poolsByID` which is an array of comptroller addresses. Individual pools can be accessed by calling `getPoolByComptroller` with the pool's\n * comptroller address. `_poolsByID` is used to iterate through all of the pools.\n *\n * PoolRegistry also contains a map of asset addresses called `_supportedPools` that maps to an array of assets suppored by each pool. This array of pools by\n * asset is retrieved by calling `getPoolsSupportedByAsset`.\n *\n * PoolRegistry registers new isolated pools in the directory with the `createRegistryPool` method. Isolated pools are composed of independent markets with\n * specific assets and custom risk management configurations according to their markets.\n */\ncontract PoolRegistry is Ownable2StepUpgradeable, AccessControlledV8, PoolRegistryInterface {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n struct AddMarketInput {\n VToken vToken;\n uint256 collateralFactor;\n uint256 liquidationThreshold;\n uint256 initialSupply;\n address vTokenReceiver;\n uint256 supplyCap;\n uint256 borrowCap;\n }\n\n uint256 internal constant MAX_POOL_NAME_LENGTH = 100;\n\n /**\n * @notice Maps pool's comptroller address to metadata.\n */\n mapping(address => VenusPoolMetaData) public metadata;\n\n /**\n * @dev Maps pool ID to pool's comptroller address\n */\n mapping(uint256 => address) private _poolsByID;\n\n /**\n * @dev Total number of pools created.\n */\n uint256 private _numberOfPools;\n\n /**\n * @dev Maps comptroller address to Venus pool Index.\n */\n mapping(address => VenusPool) private _poolByComptroller;\n\n /**\n * @dev Maps pool's comptroller address to asset to vToken.\n */\n mapping(address => mapping(address => address)) private _vTokens;\n\n /**\n * @dev Maps asset to list of supported pools.\n */\n mapping(address => address[]) private _supportedPools;\n\n /**\n * @notice Emitted when a new Venus pool is added to the directory.\n */\n event PoolRegistered(address indexed comptroller, VenusPool pool);\n\n /**\n * @notice Emitted when a pool name is set.\n */\n event PoolNameSet(address indexed comptroller, string oldName, string newName);\n\n /**\n * @notice Emitted when a pool metadata is updated.\n */\n event PoolMetadataUpdated(\n address indexed comptroller,\n VenusPoolMetaData oldMetadata,\n VenusPoolMetaData newMetadata\n );\n\n /**\n * @notice Emitted when a Market is added to the pool.\n */\n event MarketAdded(address indexed comptroller, address indexed vTokenAddress);\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the deployer to owner\n * @param accessControlManager_ AccessControlManager contract address\n */\n function initialize(address accessControlManager_) external initializer {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n }\n\n /**\n * @notice Adds a new Venus pool to the directory\n * @dev Price oracle must be configured before adding a pool\n * @param name The name of the pool\n * @param comptroller Pool's Comptroller contract\n * @param closeFactor The pool's close factor (scaled by 1e18)\n * @param liquidationIncentive The pool's liquidation incentive (scaled by 1e18)\n * @param minLiquidatableCollateral Minimal collateral for regular (non-batch) liquidations flow\n * @return index The index of the registered Venus pool\n * @custom:error ZeroAddressNotAllowed is thrown when Comptroller address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\n */\n function addPool(\n string calldata name,\n Comptroller comptroller,\n uint256 closeFactor,\n uint256 liquidationIncentive,\n uint256 minLiquidatableCollateral\n ) external virtual returns (uint256 index) {\n _checkAccessAllowed(\"addPool(string,address,uint256,uint256,uint256)\");\n // Input validation\n ensureNonzeroAddress(address(comptroller));\n ensureNonzeroAddress(address(comptroller.oracle()));\n\n uint256 poolId = _registerPool(name, address(comptroller));\n\n // Set Venus pool parameters\n comptroller.setCloseFactor(closeFactor);\n comptroller.setLiquidationIncentive(liquidationIncentive);\n comptroller.setMinLiquidatableCollateral(minLiquidatableCollateral);\n\n return poolId;\n }\n\n /**\n * @notice Add a market to an existing pool and then mint to provide initial supply\n * @param input The structure describing the parameters for adding a market to a pool\n * @custom:error ZeroAddressNotAllowed is thrown when vToken address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when vTokenReceiver address is zero\n */\n function addMarket(AddMarketInput memory input) external {\n _checkAccessAllowed(\"addMarket(AddMarketInput)\");\n ensureNonzeroAddress(address(input.vToken));\n ensureNonzeroAddress(input.vTokenReceiver);\n require(input.initialSupply > 0, \"PoolRegistry: initialSupply is zero\");\n\n VToken vToken = input.vToken;\n address vTokenAddress = address(vToken);\n address comptrollerAddress = address(vToken.comptroller());\n Comptroller comptroller = Comptroller(comptrollerAddress);\n address underlyingAddress = vToken.underlying();\n IERC20Upgradeable underlying = IERC20Upgradeable(underlyingAddress);\n\n require(_poolByComptroller[comptrollerAddress].creator != address(0), \"PoolRegistry: Pool not registered\");\n // solhint-disable-next-line reason-string\n require(\n _vTokens[comptrollerAddress][underlyingAddress] == address(0),\n \"PoolRegistry: Market already added for asset comptroller combination\"\n );\n\n comptroller.supportMarket(vToken);\n comptroller.setCollateralFactor(vToken, input.collateralFactor, input.liquidationThreshold);\n\n uint256[] memory newSupplyCaps = new uint256[](1);\n uint256[] memory newBorrowCaps = new uint256[](1);\n VToken[] memory vTokens = new VToken[](1);\n\n newSupplyCaps[0] = input.supplyCap;\n newBorrowCaps[0] = input.borrowCap;\n vTokens[0] = vToken;\n\n comptroller.setMarketSupplyCaps(vTokens, newSupplyCaps);\n comptroller.setMarketBorrowCaps(vTokens, newBorrowCaps);\n\n _vTokens[comptrollerAddress][underlyingAddress] = vTokenAddress;\n _supportedPools[underlyingAddress].push(comptrollerAddress);\n\n uint256 amountToSupply = _transferIn(underlying, msg.sender, input.initialSupply);\n underlying.forceApprove(vTokenAddress, 0);\n underlying.forceApprove(vTokenAddress, amountToSupply);\n vToken.mintBehalf(input.vTokenReceiver, amountToSupply);\n\n emit MarketAdded(comptrollerAddress, vTokenAddress);\n }\n\n /**\n * @notice Modify existing Venus pool name\n * @param comptroller Pool's Comptroller\n * @param name New pool name\n */\n function setPoolName(address comptroller, string calldata name) external {\n _checkAccessAllowed(\"setPoolName(address,string)\");\n _ensureValidName(name);\n VenusPool storage pool = _poolByComptroller[comptroller];\n string memory oldName = pool.name;\n pool.name = name;\n emit PoolNameSet(comptroller, oldName, name);\n }\n\n /**\n * @notice Update metadata of an existing pool\n * @param comptroller Pool's Comptroller\n * @param metadata_ New pool metadata\n */\n function updatePoolMetadata(address comptroller, VenusPoolMetaData calldata metadata_) external {\n _checkAccessAllowed(\"updatePoolMetadata(address,VenusPoolMetaData)\");\n VenusPoolMetaData memory oldMetadata = metadata[comptroller];\n metadata[comptroller] = metadata_;\n emit PoolMetadataUpdated(comptroller, oldMetadata, metadata_);\n }\n\n /**\n * @notice Returns arrays of all Venus pools' data\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\n * @return A list of all pools within PoolRegistry, with details for each pool\n */\n function getAllPools() external view override returns (VenusPool[] memory) {\n uint256 numberOfPools_ = _numberOfPools; // storage load to save gas\n VenusPool[] memory _pools = new VenusPool[](numberOfPools_);\n for (uint256 i = 1; i <= numberOfPools_; ++i) {\n address comptroller = _poolsByID[i];\n _pools[i - 1] = (_poolByComptroller[comptroller]);\n }\n return _pools;\n }\n\n /**\n * @param comptroller The comptroller proxy address associated to the pool\n * @return Returns Venus pool\n */\n function getPoolByComptroller(address comptroller) external view override returns (VenusPool memory) {\n return _poolByComptroller[comptroller];\n }\n\n /**\n * @param comptroller comptroller of Venus pool\n * @return Returns Metadata of Venus pool\n */\n function getVenusPoolMetadata(address comptroller) external view override returns (VenusPoolMetaData memory) {\n return metadata[comptroller];\n }\n\n function getVTokenForAsset(address comptroller, address asset) external view override returns (address) {\n return _vTokens[comptroller][asset];\n }\n\n function getPoolsSupportedByAsset(address asset) external view override returns (address[] memory) {\n return _supportedPools[asset];\n }\n\n /**\n * @dev Adds a new Venus pool to the directory (without checking msg.sender).\n * @param name The name of the pool\n * @param comptroller The pool's Comptroller proxy contract address\n * @return The index of the registered Venus pool\n */\n function _registerPool(string calldata name, address comptroller) internal returns (uint256) {\n VenusPool storage storedPool = _poolByComptroller[comptroller];\n\n require(storedPool.creator == address(0), \"PoolRegistry: Pool already exists in the directory.\");\n _ensureValidName(name);\n\n ++_numberOfPools;\n uint256 numberOfPools_ = _numberOfPools; // cache on stack to save storage read gas\n\n VenusPool memory pool = VenusPool(name, msg.sender, comptroller, block.number, block.timestamp);\n\n _poolsByID[numberOfPools_] = comptroller;\n _poolByComptroller[comptroller] = pool;\n\n emit PoolRegistered(comptroller, pool);\n return numberOfPools_;\n }\n\n function _transferIn(IERC20Upgradeable token, address from, uint256 amount) internal returns (uint256) {\n uint256 balanceBefore = token.balanceOf(address(this));\n token.safeTransferFrom(from, address(this), amount);\n uint256 balanceAfter = token.balanceOf(address(this));\n return balanceAfter - balanceBefore;\n }\n\n function _ensureValidName(string calldata name) internal pure {\n require(bytes(name).length <= MAX_POOL_NAME_LENGTH, \"Pool's name is too large\");\n }\n}\n" + }, + "contracts/Pool/PoolRegistryInterface.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 /**\n * @notice Struct for a Venus interest rate pool metadata.\n */\n struct VenusPoolMetaData {\n string category;\n string logoURL;\n string description;\n }\n\n /// @notice Get all pools in PoolRegistry\n function getAllPools() external view returns (VenusPool[] memory);\n\n /// @notice Get a pool by comptroller address\n function getPoolByComptroller(address comptroller) external view returns (VenusPool memory);\n\n /// @notice Get the address of the VToken contract in the Pool where the underlying token is the provided 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 /// @notice Get the metadata of a Pool by comptroller address\n function getVenusPoolMetadata(address comptroller) external view returns (VenusPoolMetaData memory);\n}\n" + }, + "contracts/Rewards/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\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 { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { TimeManagerV8 } from \"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\";\n\nimport { ExponentialNoError } from \"../ExponentialNoError.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { MaxLoopsLimitHelper } from \"../MaxLoopsLimitHelper.sol\";\nimport { RewardsDistributorStorage } from \"./RewardsDistributorStorage.sol\";\n\n/**\n * @title `RewardsDistributor`\n * @author Venus\n * @notice Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol.\n * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward\n * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool.\n * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward\n * token to be released each slot (block or second) for borrowers and suppliers, which is distributed based on a user’s percentage of the borrows or supplies\n * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting\n * their contributor reward token speed, which similarly allocates a fixed amount of reward token per slot (block or second).\n *\n * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed\n * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized\n * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\n */\ncontract RewardsDistributor is\n ExponentialNoError,\n Ownable2StepUpgradeable,\n AccessControlledV8,\n MaxLoopsLimitHelper,\n RewardsDistributorStorage,\n TimeManagerV8\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice The initial REWARD TOKEN index for a market\n uint224 public constant INITIAL_INDEX = 1e36;\n\n /// @notice Emitted when REWARD TOKEN is distributed to a supplier\n event DistributedSupplierRewardToken(\n VToken indexed vToken,\n address indexed supplier,\n uint256 rewardTokenDelta,\n uint256 rewardTokenTotal,\n uint256 rewardTokenSupplyIndex\n );\n\n /// @notice Emitted when REWARD TOKEN is distributed to a borrower\n event DistributedBorrowerRewardToken(\n VToken indexed vToken,\n address indexed borrower,\n uint256 rewardTokenDelta,\n uint256 rewardTokenTotal,\n uint256 rewardTokenBorrowIndex\n );\n\n /// @notice Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\n event RewardTokenSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /// @notice Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\n event RewardTokenBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /// @notice Emitted when REWARD TOKEN is granted by admin\n event RewardTokenGranted(address indexed recipient, uint256 amount);\n\n /// @notice Emitted when a new REWARD TOKEN speed is set for a contributor\n event ContributorRewardTokenSpeedUpdated(address indexed contributor, uint256 newSpeed);\n\n /// @notice Emitted when a market is initialized\n event MarketInitialized(address indexed vToken);\n\n /// @notice Emitted when a reward token supply index is updated\n event RewardTokenSupplyIndexUpdated(address indexed vToken);\n\n /// @notice Emitted when a reward token borrow index is updated\n event RewardTokenBorrowIndexUpdated(address indexed vToken, Exp marketBorrowIndex);\n\n /// @notice Emitted when a reward for contributor is updated\n event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued);\n\n /// @notice Emitted when a reward token last rewarding block for supply is updated\n event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\n\n /// @notice Emitted when a reward token last rewarding block for borrow is updated\n event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\n\n /// @notice Emitted when a reward token last rewarding timestamp for supply is updated\n event SupplyLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\n\n /// @notice Emitted when a reward token last rewarding timestamp for borrow is updated\n event BorrowLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\n\n modifier onlyComptroller() {\n require(address(comptroller) == msg.sender, \"Only comptroller can call this function\");\n _;\n }\n\n /**\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\n * @param blocksPerYear_ The number of blocks per year\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /**\n * @notice RewardsDistributor initializer\n * @dev Initializes the deployer to owner\n * @param comptroller_ Comptroller to attach the reward distributor to\n * @param rewardToken_ Reward token to distribute\n * @param loopsLimit_ Maximum number of iterations for the loops in this contract\n * @param accessControlManager_ AccessControlManager contract address\n */\n function initialize(\n Comptroller comptroller_,\n IERC20Upgradeable rewardToken_,\n uint256 loopsLimit_,\n address accessControlManager_\n ) external initializer {\n comptroller = comptroller_;\n rewardToken = rewardToken_;\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n\n _setMaxLoopsLimit(loopsLimit_);\n }\n\n /**\n * @notice Initializes the market state for a specific vToken\n * @param vToken The address of the vToken to be initialized\n * @custom:event MarketInitialized emits on success\n * @custom:access Only Comptroller\n */\n function initializeMarket(address vToken) external onlyComptroller {\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n isTimeBased\n ? _initializeMarketTimestampBased(vToken, blockNumberOrTimestamp)\n : _initializeMarketBlockBased(vToken, safe32(blockNumberOrTimestamp, \"block number exceeds 32 bits\"));\n\n emit MarketInitialized(vToken);\n }\n\n /*** Reward Token Distribution ***/\n\n /**\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them\n * Borrowers will begin to accrue after the first interaction with the protocol.\n * @dev This function should only be called when the user has a borrow position in the market\n * (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook)\n * We avoid an external call to check if they are in the market to save gas because this function is called in many places\n * @param vToken The market in which the borrower is interacting\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\n * @param marketBorrowIndex The current global borrow index of vToken\n */\n function distributeBorrowerRewardToken(\n address vToken,\n address borrower,\n Exp memory marketBorrowIndex\n ) external onlyComptroller {\n _distributeBorrowerRewardToken(vToken, borrower, marketBorrowIndex);\n }\n\n function updateRewardTokenSupplyIndex(address vToken) external onlyComptroller {\n _updateRewardTokenSupplyIndex(vToken);\n }\n\n /**\n * @notice Transfer REWARD TOKEN to the recipient\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\n * @param recipient The address of the recipient to transfer REWARD TOKEN to\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\n */\n function grantRewardToken(address recipient, uint256 amount) external onlyOwner {\n uint256 amountLeft = _grantRewardToken(recipient, amount);\n require(amountLeft == 0, \"insufficient rewardToken for grant\");\n emit RewardTokenGranted(recipient, amount);\n }\n\n function updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) external onlyComptroller {\n _updateRewardTokenBorrowIndex(vToken, marketBorrowIndex);\n }\n\n /**\n * @notice Set REWARD TOKEN borrow and supply speeds for the specified markets\n * @param vTokens The markets whose REWARD TOKEN speed to update\n * @param supplySpeeds New supply-side REWARD TOKEN speed for the corresponding market\n * @param borrowSpeeds New borrow-side REWARD TOKEN speed for the corresponding market\n */\n function setRewardTokenSpeeds(\n VToken[] memory vTokens,\n uint256[] memory supplySpeeds,\n uint256[] memory borrowSpeeds\n ) external {\n _checkAccessAllowed(\"setRewardTokenSpeeds(address[],uint256[],uint256[])\");\n uint256 numTokens = vTokens.length;\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \"invalid setRewardTokenSpeeds\");\n\n for (uint256 i; i < numTokens; ++i) {\n _setRewardTokenSpeed(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\n }\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding block for the specified markets, used when contract is block based\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\n * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market\n * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market\n */\n function setLastRewardingBlocks(\n VToken[] calldata vTokens,\n uint32[] calldata supplyLastRewardingBlocks,\n uint32[] calldata borrowLastRewardingBlocks\n ) external {\n _checkAccessAllowed(\"setLastRewardingBlocks(address[],uint32[],uint32[])\");\n require(!isTimeBased, \"Block-based operation only\");\n\n uint256 numTokens = vTokens.length;\n require(\n numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length,\n \"RewardsDistributor::setLastRewardingBlocks invalid input\"\n );\n\n for (uint256 i; i < numTokens; ) {\n _setLastRewardingBlock(vTokens[i], supplyLastRewardingBlocks[i], borrowLastRewardingBlocks[i]);\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding block timestamp for the specified markets, used when contract is time based\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\n * @param supplyLastRewardingBlockTimestamps New supply-side REWARD TOKEN last rewarding block timestamp for the corresponding market\n * @param borrowLastRewardingBlockTimestamps New borrow-side REWARD TOKEN last rewarding block timestamp for the corresponding market\n */\n function setLastRewardingBlockTimestamps(\n VToken[] calldata vTokens,\n uint256[] calldata supplyLastRewardingBlockTimestamps,\n uint256[] calldata borrowLastRewardingBlockTimestamps\n ) external {\n _checkAccessAllowed(\"setLastRewardingBlockTimestamps(address[],uint256[],uint256[])\");\n require(isTimeBased, \"Time-based operation only\");\n\n uint256 numTokens = vTokens.length;\n require(\n numTokens == supplyLastRewardingBlockTimestamps.length &&\n numTokens == borrowLastRewardingBlockTimestamps.length,\n \"RewardsDistributor::setLastRewardingBlockTimestamps invalid input\"\n );\n\n for (uint256 i; i < numTokens; ) {\n _setLastRewardingBlockTimestamp(\n vTokens[i],\n supplyLastRewardingBlockTimestamps[i],\n borrowLastRewardingBlockTimestamps[i]\n );\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Set REWARD TOKEN speed for a single contributor\n * @param contributor The contributor whose REWARD TOKEN speed to update\n * @param rewardTokenSpeed New REWARD TOKEN speed for contributor\n */\n function setContributorRewardTokenSpeed(address contributor, uint256 rewardTokenSpeed) external onlyOwner {\n // note that REWARD TOKEN speed could be set to 0 to halt liquidity rewards for a contributor\n updateContributorRewards(contributor);\n if (rewardTokenSpeed == 0) {\n // release storage\n delete lastContributorBlock[contributor];\n } else {\n lastContributorBlock[contributor] = getBlockNumberOrTimestamp();\n }\n rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed;\n\n emit ContributorRewardTokenSpeedUpdated(contributor, rewardTokenSpeed);\n }\n\n function distributeSupplierRewardToken(address vToken, address supplier) external onlyComptroller {\n _distributeSupplierRewardToken(vToken, supplier);\n }\n\n /**\n * @notice Claim all the rewardToken accrued by holder in all markets\n * @param holder The address to claim REWARD TOKEN for\n */\n function claimRewardToken(address holder) external {\n return claimRewardToken(holder, comptroller.getAllMarkets());\n }\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) external onlyOwner {\n _setMaxLoopsLimit(limit);\n }\n\n /**\n * @notice Calculate additional accrued REWARD TOKEN for a contributor since last accrual\n * @param contributor The address to calculate contributor rewards for\n */\n function updateContributorRewards(address contributor) public {\n uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor];\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, lastContributorBlock[contributor]);\n if (deltaBlocksOrTimestamp > 0 && rewardTokenSpeed > 0) {\n uint256 newAccrued = mul_(deltaBlocksOrTimestamp, rewardTokenSpeed);\n uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued);\n\n rewardTokenAccrued[contributor] = contributorAccrued;\n lastContributorBlock[contributor] = blockNumberOrTimestamp;\n\n emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]);\n }\n }\n\n /**\n * @notice Claim all the rewardToken accrued by holder in the specified markets\n * @param holder The address to claim REWARD TOKEN for\n * @param vTokens The list of markets to claim REWARD TOKEN in\n */\n function claimRewardToken(address holder, VToken[] memory vTokens) public {\n uint256 vTokensCount = vTokens.length;\n\n _ensureMaxLoops(vTokensCount);\n\n for (uint256 i; i < vTokensCount; ++i) {\n VToken vToken = vTokens[i];\n require(comptroller.isMarketListed(vToken), \"market must be listed\");\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\n _distributeBorrowerRewardToken(address(vToken), holder, borrowIndex);\n _updateRewardTokenSupplyIndex(address(vToken));\n _distributeSupplierRewardToken(address(vToken), holder);\n }\n rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]);\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding block for a single market.\n * @param vToken market's whose reward token last rewarding block to be updated\n * @param supplyLastRewardingBlock New supply-side REWARD TOKEN last rewarding block for market\n * @param borrowLastRewardingBlock New borrow-side REWARD TOKEN last rewarding block for market\n */\n function _setLastRewardingBlock(\n VToken vToken,\n uint32 supplyLastRewardingBlock,\n uint32 borrowLastRewardingBlock\n ) internal {\n require(comptroller.isMarketListed(vToken), \"rewardToken market is not listed\");\n\n uint256 blockNumber = getBlockNumberOrTimestamp();\n\n require(supplyLastRewardingBlock > blockNumber, \"setting last rewarding block in the past is not allowed\");\n require(borrowLastRewardingBlock > blockNumber, \"setting last rewarding block in the past is not allowed\");\n\n uint32 currentSupplyLastRewardingBlock = rewardTokenSupplyState[address(vToken)].lastRewardingBlock;\n uint32 currentBorrowLastRewardingBlock = rewardTokenBorrowState[address(vToken)].lastRewardingBlock;\n\n require(\n currentSupplyLastRewardingBlock == 0 || currentSupplyLastRewardingBlock > blockNumber,\n \"this RewardsDistributor is already locked\"\n );\n require(\n currentBorrowLastRewardingBlock == 0 || currentBorrowLastRewardingBlock > blockNumber,\n \"this RewardsDistributor is already locked\"\n );\n\n if (currentSupplyLastRewardingBlock != supplyLastRewardingBlock) {\n rewardTokenSupplyState[address(vToken)].lastRewardingBlock = supplyLastRewardingBlock;\n emit SupplyLastRewardingBlockUpdated(address(vToken), supplyLastRewardingBlock);\n }\n\n if (currentBorrowLastRewardingBlock != borrowLastRewardingBlock) {\n rewardTokenBorrowState[address(vToken)].lastRewardingBlock = borrowLastRewardingBlock;\n emit BorrowLastRewardingBlockUpdated(address(vToken), borrowLastRewardingBlock);\n }\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding timestamp for a single market.\n * @param vToken market's whose reward token last rewarding timestamp to be updated\n * @param supplyLastRewardingBlockTimestamp New supply-side REWARD TOKEN last rewarding timestamp for market\n * @param borrowLastRewardingBlockTimestamp New borrow-side REWARD TOKEN last rewarding timestamp for market\n */\n function _setLastRewardingBlockTimestamp(\n VToken vToken,\n uint256 supplyLastRewardingBlockTimestamp,\n uint256 borrowLastRewardingBlockTimestamp\n ) internal {\n require(comptroller.isMarketListed(vToken), \"rewardToken market is not listed\");\n\n uint256 blockTimestamp = getBlockNumberOrTimestamp();\n\n require(\n supplyLastRewardingBlockTimestamp > blockTimestamp,\n \"setting last rewarding timestamp in the past is not allowed\"\n );\n require(\n borrowLastRewardingBlockTimestamp > blockTimestamp,\n \"setting last rewarding timestamp in the past is not allowed\"\n );\n\n uint256 currentSupplyLastRewardingBlockTimestamp = rewardTokenSupplyStateTimeBased[address(vToken)]\n .lastRewardingTimestamp;\n uint256 currentBorrowLastRewardingBlockTimestamp = rewardTokenBorrowStateTimeBased[address(vToken)]\n .lastRewardingTimestamp;\n\n require(\n currentSupplyLastRewardingBlockTimestamp == 0 || currentSupplyLastRewardingBlockTimestamp > blockTimestamp,\n \"this RewardsDistributor is already locked\"\n );\n require(\n currentBorrowLastRewardingBlockTimestamp == 0 || currentBorrowLastRewardingBlockTimestamp > blockTimestamp,\n \"this RewardsDistributor is already locked\"\n );\n\n if (currentSupplyLastRewardingBlockTimestamp != supplyLastRewardingBlockTimestamp) {\n rewardTokenSupplyStateTimeBased[address(vToken)].lastRewardingTimestamp = supplyLastRewardingBlockTimestamp;\n emit SupplyLastRewardingBlockTimestampUpdated(address(vToken), supplyLastRewardingBlockTimestamp);\n }\n\n if (currentBorrowLastRewardingBlockTimestamp != borrowLastRewardingBlockTimestamp) {\n rewardTokenBorrowStateTimeBased[address(vToken)].lastRewardingTimestamp = borrowLastRewardingBlockTimestamp;\n emit BorrowLastRewardingBlockTimestampUpdated(address(vToken), borrowLastRewardingBlockTimestamp);\n }\n }\n\n /**\n * @notice Set REWARD TOKEN speed for a single market.\n * @param vToken market's whose reward token rate to be updated\n * @param supplySpeed New supply-side REWARD TOKEN speed for market\n * @param borrowSpeed New borrow-side REWARD TOKEN speed for market\n */\n function _setRewardTokenSpeed(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\n require(comptroller.isMarketListed(vToken), \"rewardToken market is not listed\");\n\n if (rewardTokenSupplySpeeds[address(vToken)] != supplySpeed) {\n // Supply speed updated so let's update supply state to ensure that\n // 1. REWARD TOKEN accrued properly for the old speed, and\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\n _updateRewardTokenSupplyIndex(address(vToken));\n\n // Update speed and emit event\n rewardTokenSupplySpeeds[address(vToken)] = supplySpeed;\n emit RewardTokenSupplySpeedUpdated(vToken, supplySpeed);\n }\n\n if (rewardTokenBorrowSpeeds[address(vToken)] != borrowSpeed) {\n // Borrow speed updated so let's update borrow state to ensure that\n // 1. REWARD TOKEN accrued properly for the old speed, and\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\n\n // Update speed and emit event\n rewardTokenBorrowSpeeds[address(vToken)] = borrowSpeed;\n emit RewardTokenBorrowSpeedUpdated(vToken, borrowSpeed);\n }\n }\n\n /**\n * @notice Calculate REWARD TOKEN 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 REWARD TOKEN to\n */\n function _distributeSupplierRewardToken(address vToken, address supplier) internal {\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\n\n uint256 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\n uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier];\n\n // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN\n rewardTokenSupplierIndex[vToken][supplier] = supplyIndex;\n\n if (supplierIndex == 0 && supplyIndex >= INITIAL_INDEX) {\n // Covers the case where users supplied tokens before the market's supply state index was set.\n // Rewards the user with REWARD TOKEN accrued from the start of when supplier rewards were first\n // set for the market.\n supplierIndex = INITIAL_INDEX;\n }\n\n // Calculate change in the cumulative sum of the REWARD TOKEN per vToken accrued\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\n\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\n\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerVToken\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\n\n uint256 supplierAccrued = add_(rewardTokenAccrued[supplier], supplierDelta);\n rewardTokenAccrued[supplier] = supplierAccrued;\n\n emit DistributedSupplierRewardToken(VToken(vToken), supplier, supplierDelta, supplierAccrued, supplyIndex);\n }\n\n /**\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them.\n * @param vToken The market in which the borrower is interacting\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\n * @param marketBorrowIndex The current global borrow index of vToken\n */\n function _distributeBorrowerRewardToken(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\n\n uint256 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\n uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower];\n\n // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN\n rewardTokenBorrowerIndex[vToken][borrower] = borrowIndex;\n\n if (borrowerIndex == 0 && borrowIndex >= INITIAL_INDEX) {\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\n // Rewards the user with REWARD TOKEN accrued from the start of when borrower rewards were first\n // set for the market.\n borrowerIndex = INITIAL_INDEX;\n }\n\n // Calculate change in the cumulative sum of the REWARD TOKEN per borrowed unit accrued\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\n\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\n\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerBorrowedUnit\n if (borrowerAmount != 0) {\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\n\n uint256 borrowerAccrued = add_(rewardTokenAccrued[borrower], borrowerDelta);\n rewardTokenAccrued[borrower] = borrowerAccrued;\n\n emit DistributedBorrowerRewardToken(VToken(vToken), borrower, borrowerDelta, borrowerAccrued, borrowIndex);\n }\n }\n\n /**\n * @notice Transfer REWARD TOKEN to the user.\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all.\n * @param user The address of the user to transfer REWARD TOKEN to\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\n * @return The amount of REWARD TOKEN which was NOT transferred to the user\n */\n function _grantRewardToken(address user, uint256 amount) internal returns (uint256) {\n uint256 rewardTokenRemaining = rewardToken.balanceOf(address(this));\n if (amount > 0 && amount <= rewardTokenRemaining) {\n rewardToken.safeTransfer(user, amount);\n return 0;\n }\n return amount;\n }\n\n /**\n * @notice Accrue REWARD TOKEN to the market by updating the supply index\n * @param vToken The market whose supply index to update\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\n */\n function _updateRewardTokenSupplyIndex(address vToken) internal {\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\n\n uint256 supplySpeed = rewardTokenSupplySpeeds[vToken];\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n if (!isTimeBased) {\n safe32(blockNumberOrTimestamp, \"block number exceeds 32 bits\");\n }\n\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\n ? supplyStateTimeBased.lastRewardingTimestamp\n : uint256(supplyState.lastRewardingBlock);\n\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\n }\n\n uint256 deltaBlocksOrTimestamp = sub_(\n blockNumberOrTimestamp,\n (isTimeBased ? supplyStateTimeBased.timestamp : uint256(supplyState.block))\n );\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\n uint256 supplyTokens = VToken(vToken).totalSupply();\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, supplySpeed);\n Double memory ratio = supplyTokens > 0\n ? fraction(accruedSinceUpdate, supplyTokens)\n : Double({ mantissa: 0 });\n uint224 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\n uint224 index = safe224(\n add_(Double({ mantissa: supplyIndex }), ratio).mantissa,\n \"new index exceeds 224 bits\"\n );\n\n if (isTimeBased) {\n supplyStateTimeBased.index = index;\n supplyStateTimeBased.timestamp = blockNumberOrTimestamp;\n } else {\n supplyState.index = index;\n supplyState.block = uint32(blockNumberOrTimestamp);\n }\n } else if (deltaBlocksOrTimestamp > 0) {\n isTimeBased ? supplyStateTimeBased.timestamp = blockNumberOrTimestamp : supplyState.block = uint32(\n blockNumberOrTimestamp\n );\n }\n\n emit RewardTokenSupplyIndexUpdated(vToken);\n }\n\n /**\n * @notice Accrue REWARD TOKEN to the market by updating the borrow index\n * @param vToken The market whose borrow index to update\n * @param marketBorrowIndex The current global borrow index of vToken\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\n */\n function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\n\n uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken];\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n if (!isTimeBased) {\n safe32(blockNumberOrTimestamp, \"block number exceeds 32 bits\");\n }\n\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\n ? borrowStateTimeBased.lastRewardingTimestamp\n : uint256(borrowState.lastRewardingBlock);\n\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\n }\n\n uint256 deltaBlocksOrTimestamp = sub_(\n blockNumberOrTimestamp,\n (isTimeBased ? borrowStateTimeBased.timestamp : uint256(borrowState.block))\n );\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, borrowSpeed);\n Double memory ratio = borrowAmount > 0\n ? fraction(accruedSinceUpdate, borrowAmount)\n : Double({ mantissa: 0 });\n uint224 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\n uint224 index = safe224(\n add_(Double({ mantissa: borrowIndex }), ratio).mantissa,\n \"new index exceeds 224 bits\"\n );\n\n if (isTimeBased) {\n borrowStateTimeBased.index = index;\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\n } else {\n borrowState.index = index;\n borrowState.block = uint32(blockNumberOrTimestamp);\n }\n } else if (deltaBlocksOrTimestamp > 0) {\n if (isTimeBased) {\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\n } else {\n borrowState.block = uint32(blockNumberOrTimestamp);\n }\n }\n\n emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex);\n }\n\n /**\n * @notice Initializes the market state for a specific vToken called when contract is block-based\n * @param vToken The address of the vToken to be initialized\n * @param blockNumber current block number\n */\n function _initializeMarketBlockBased(address vToken, uint32 blockNumber) internal {\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n RewardToken storage borrowState = rewardTokenBorrowState[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 = INITIAL_INDEX;\n }\n\n if (borrowState.index == 0) {\n // Initialize borrow state index with default value\n borrowState.index = INITIAL_INDEX;\n }\n\n /*\n * Update market state block numbers\n */\n supplyState.block = borrowState.block = blockNumber;\n }\n\n /**\n * @notice Initializes the market state for a specific vToken called when contract is time-based\n * @param vToken The address of the vToken to be initialized\n * @param blockTimestamp current block timestamp\n */\n function _initializeMarketTimestampBased(address vToken, uint256 blockTimestamp) internal {\n TimeBasedRewardToken storage supplyState = rewardTokenSupplyStateTimeBased[vToken];\n TimeBasedRewardToken storage borrowState = rewardTokenBorrowStateTimeBased[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 = INITIAL_INDEX;\n }\n\n if (borrowState.index == 0) {\n // Initialize borrow state index with default value\n borrowState.index = INITIAL_INDEX;\n }\n\n /*\n * Update market state block timestamp\n */\n supplyState.timestamp = borrowState.timestamp = blockTimestamp;\n }\n}\n" + }, + "contracts/Rewards/RewardsDistributorStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\nimport { Comptroller } from \"../Comptroller.sol\";\n\n/**\n * @title RewardsDistributorStorage\n * @author Venus\n * @dev Storage for RewardsDistributor\n */\ncontract RewardsDistributorStorage {\n struct RewardToken {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block number the index was last updated at\n uint32 block;\n // The block number at which to stop rewards\n uint32 lastRewardingBlock;\n }\n\n struct TimeBasedRewardToken {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block timestamp the index was last updated at\n uint256 timestamp;\n // The block timestamp at which to stop rewards\n uint256 lastRewardingTimestamp;\n }\n\n /// @notice The REWARD TOKEN market supply state for each market\n mapping(address => RewardToken) public rewardTokenSupplyState;\n\n /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\n mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex;\n\n /// @notice The REWARD TOKEN accrued but not yet transferred to each user\n mapping(address => uint256) public rewardTokenAccrued;\n\n /// @notice The rate at which rewardToken is distributed to the corresponding borrow market per slot (block or second)\n mapping(address => uint256) public rewardTokenBorrowSpeeds;\n\n /// @notice The rate at which rewardToken is distributed to the corresponding supply market per slot (block or second)\n mapping(address => uint256) public rewardTokenSupplySpeeds;\n\n /// @notice The REWARD TOKEN market borrow state for each market\n mapping(address => RewardToken) public rewardTokenBorrowState;\n\n /// @notice The portion of REWARD TOKEN that each contributor receives per slot (block or second)\n mapping(address => uint256) public rewardTokenContributorSpeeds;\n\n /// @notice Last slot (block or second) at which a contributor's REWARD TOKEN rewards have been allocated\n mapping(address => uint256) public lastContributorBlock;\n\n /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\n mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex;\n\n Comptroller internal comptroller;\n\n IERC20Upgradeable public rewardToken;\n\n /// @notice The REWARD TOKEN market supply state for each market\n mapping(address => TimeBasedRewardToken) public rewardTokenSupplyStateTimeBased;\n\n /// @notice The REWARD TOKEN market borrow state for each market\n mapping(address => TimeBasedRewardToken) public rewardTokenBorrowStateTimeBased;\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[37] private __gap;\n}\n" + }, + "contracts/VToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\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 { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { IProtocolShareReserve } from \"@venusprotocol/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\";\n\nimport { VTokenInterface } from \"./VTokenInterfaces.sol\";\nimport { ComptrollerInterface, ComptrollerViewInterface } from \"./ComptrollerInterface.sol\";\nimport { TokenErrorReporter } from \"./ErrorReporter.sol\";\nimport { InterestRateModel } from \"./InterestRateModel.sol\";\nimport { ExponentialNoError } from \"./ExponentialNoError.sol\";\nimport { TimeManagerV8 } from \"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\";\nimport { ensureNonzeroAddress } from \"./lib/validators.sol\";\n\n/**\n * @title VToken\n * @author Venus\n * @notice Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview,\n * each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of\n * the pool. The main actions a user regularly interacts with in a market are:\n\n- mint/redeem of vTokens;\n- transfer of vTokens;\n- borrow/repay a loan on an underlying asset;\n- liquidate a borrow or liquidate/heal an account.\n\n * A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`.\n * The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted\n * `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken`\n * as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that\n * a user may borrow up to a portion of their collateral determined by the market’s collateral factor. However, if their borrowed amount exceeds an amount\n * calculated using the market’s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also\n * pay off interest accrued on the borrow.\n * \n * The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller`\n * and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a\n * total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`.\n * Both functions settle all of an account’s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of\n * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\n */\ncontract VToken is\n Ownable2StepUpgradeable,\n AccessControlledV8,\n VTokenInterface,\n ExponentialNoError,\n TokenErrorReporter,\n TimeManagerV8\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5%\n\n // Maximum fraction of interest that can be set aside for reserves\n uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18;\n\n // Maximum borrow rate that can ever be applied per slot(block or second)\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n uint256 internal immutable MAX_BORROW_RATE_MANTISSA;\n\n /**\n * Reentrancy Guard **\n */\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 * @param timeBased_ A boolean indicating whether the contract is based on time or block.\n * @param blocksPerYear_ The number of blocks per year\n * @param maxBorrowRateMantissa_ The maximum value of borrowing rate mantissa\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor(\n bool timeBased_,\n uint256 blocksPerYear_,\n uint256 maxBorrowRateMantissa_\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n require(maxBorrowRateMantissa_ <= 1e18, \"Max borrow rate must be <= 1e18\");\n\n MAX_BORROW_RATE_MANTISSA = maxBorrowRateMantissa_;\n _disableInitializers();\n }\n\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_ ERC-20 name of this token\n * @param symbol_ ERC-20 symbol of this token\n * @param decimals_ ERC-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param accessControlManager_ AccessControlManager contract address\n * @param riskManagement Addresses of risk & income related contracts\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\n * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\n */\n function initialize(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address admin_,\n address accessControlManager_,\n RiskManagementInit memory riskManagement,\n uint256 reserveFactorMantissa_\n ) external initializer {\n ensureNonzeroAddress(admin_);\n\n // Initialize the market\n _initialize(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_,\n accessControlManager_,\n riskManagement,\n reserveFactorMantissa_\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 * @return success True if the transfer succeeded, reverts otherwise\n * @custom:event Emits Transfer event on success\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\n * @custom:access Not restricted\n */\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\n _transferTokens(msg.sender, msg.sender, dst, amount);\n return true;\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 success True if the transfer succeeded, reverts otherwise\n * @custom:event Emits Transfer event on success\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\n * @custom:access Not restricted\n */\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\n _transferTokens(msg.sender, src, dst, amount);\n return true;\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 (uint256.max means infinite)\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function approve(address spender, uint256 amount) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n transferAllowances[src][spender] = amount;\n emit Approval(src, spender, amount);\n return true;\n }\n\n /**\n * @notice Increase approval for `spender`\n * @param spender The address of the account which may transfer tokens\n * @param addedValue The number of additional tokens spender can transfer\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function increaseAllowance(address spender, uint256 addedValue) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n uint256 newAllowance = transferAllowances[src][spender];\n newAllowance += addedValue;\n transferAllowances[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n return true;\n }\n\n /**\n * @notice Decreases approval for `spender`\n * @param spender The address of the account which may transfer tokens\n * @param subtractedValue The number of tokens to remove from total approval\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n uint256 currentAllowance = transferAllowances[src][spender];\n require(currentAllowance >= subtractedValue, \"decreased allowance below zero\");\n unchecked {\n currentAllowance -= subtractedValue;\n }\n\n transferAllowances[src][spender] = currentAllowance;\n\n emit Approval(src, spender, currentAllowance);\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 amount The amount of underlying owned by `owner`\n */\n function balanceOfUnderlying(address owner) external override returns (uint256) {\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\n return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\n }\n\n /**\n * @notice Returns the current total borrows plus accrued interest\n * @return totalBorrows The total borrows with interest\n */\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\n accrueInterest();\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 borrowBalance The calculated balance\n */\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\n accrueInterest();\n return _borrowBalanceStored(account);\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function mint(uint256 mintAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _mintFresh(msg.sender, msg.sender, mintAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param minter User whom the supply will be attributed to\n * @param mintAmount The amount of the underlying asset to supply\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when minter address is zero\n */\n function mintBehalf(address minter, uint256 mintAmount) external override nonReentrant returns (uint256) {\n ensureNonzeroAddress(minter);\n\n accrueInterest();\n\n _mintFresh(msg.sender, minter, mintAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\n * @custom:access Not restricted\n */\n function redeem(uint256 redeemTokens) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _redeemFresh(msg.sender, msg.sender, redeemTokens, 0);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function redeemBehalf(address redeemer, uint256 redeemTokens) external override nonReentrant returns (uint256) {\n _ensureSenderIsDelegateOf(redeemer);\n\n accrueInterest();\n\n _redeemFresh(redeemer, msg.sender, redeemTokens, 0);\n return NO_ERROR;\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 receive from redeeming vTokens\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n */\n function redeemUnderlying(uint256 redeemAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _redeemFresh(msg.sender, msg.sender, 0, redeemAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function redeemUnderlyingBehalf(\n address redeemer,\n uint256 redeemAmount\n ) external override nonReentrant returns (uint256) {\n _ensureSenderIsDelegateOf(redeemer);\n\n accrueInterest();\n\n _redeemFresh(redeemer, msg.sender, 0, redeemAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Borrow event; may emit AccrueInterest\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\n * @custom:access Not restricted\n */\n function borrow(uint256 borrowAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _borrowFresh(msg.sender, msg.sender, borrowAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:error DelegateNotApproved is thrown if caller is not approved delegate\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\n * @custom:event Emits Borrow event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function borrowBehalf(address borrower, uint256 borrowAmount) external override returns (uint256) {\n _ensureSenderIsDelegateOf(borrower);\n accrueInterest();\n\n _borrowFresh(borrower, msg.sender, borrowAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function repayBorrow(uint256 repayAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _repayBorrowFresh(msg.sender, msg.sender, repayAmount);\n return NO_ERROR;\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, or type(uint256).max for the full outstanding amount\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _repayBorrowFresh(msg.sender, borrower, repayAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\n * @custom:access Not restricted\n */\n function liquidateBorrow(\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) external override returns (uint256) {\n _liquidateBorrow(msg.sender, borrower, repayAmount, vTokenCollateral, false);\n return NO_ERROR;\n }\n\n /**\n * @notice sets protocol share accumulated from liquidations\n * @dev must be equal or less than liquidation incentive - 1\n * @param newProtocolSeizeShareMantissa_ new protocol share mantissa\n * @custom:event Emits NewProtocolSeizeShare event on success\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:error ProtocolSeizeShareTooBig is thrown when the new seize share is too high\n * @custom:access Controlled by AccessControlManager\n */\n function setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa_) external {\n _checkAccessAllowed(\"setProtocolSeizeShare(uint256)\");\n uint256 liquidationIncentive = ComptrollerViewInterface(address(comptroller)).liquidationIncentiveMantissa();\n if (newProtocolSeizeShareMantissa_ + MANTISSA_ONE > liquidationIncentive) {\n revert ProtocolSeizeShareTooBig();\n }\n\n uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\n protocolSeizeShareMantissa = newProtocolSeizeShareMantissa_;\n emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa_);\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 * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\n * @custom:event Emits NewReserveFactor event; may emit AccrueInterest\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:error SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\n * @custom:access Controlled by AccessControlManager\n */\n function setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant {\n _checkAccessAllowed(\"setReserveFactor(uint256)\");\n\n accrueInterest();\n _setReserveFactorFresh(newReserveFactorMantissa);\n }\n\n /**\n * @notice Accrues interest and reduces reserves by transferring to the protocol reserve contract\n * @dev Gracefully return if reserves already reduced in accrueInterest\n * @param reduceAmount Amount of reduction to reserves\n * @custom:event Emits ReservesReduced event; may emit AccrueInterest\n * @custom:error ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash\n * @custom:error ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\n * @custom:access Not restricted\n */\n function reduceReserves(uint256 reduceAmount) external override nonReentrant {\n accrueInterest();\n if (reduceReservesBlockNumber == getBlockNumberOrTimestamp()) return;\n _reduceReservesFresh(reduceAmount);\n }\n\n /**\n * @notice The sender adds to reserves.\n * @param addAmount The amount of underlying token to add as reserves\n * @custom:event Emits ReservesAdded event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function addReserves(uint256 addAmount) external override nonReentrant {\n accrueInterest();\n _addReservesFresh(addAmount);\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 * @custom:event Emits NewMarketInterestRateModel event; may emit AccrueInterest\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:access Controlled by AccessControlManager\n */\n function setInterestRateModel(InterestRateModel newInterestRateModel) external override {\n _checkAccessAllowed(\"setInterestRateModel(address)\");\n\n accrueInterest();\n _setInterestRateModelFresh(newInterestRateModel);\n }\n\n /**\n * @notice Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially\n * \"forgiving\" the borrower. Healing is a situation that should rarely happen. However, some pools\n * may list risky assets or be configured improperly – we want to still handle such cases gracefully.\n * We assume that Comptroller does the seizing, so this function is only available to Comptroller.\n * @dev This function does not call any Comptroller hooks (like \"healAllowed\"), because we assume\n * the Comptroller does all the necessary checks before calling this function.\n * @param payer account who repays the debt\n * @param borrower account to heal\n * @param repayAmount amount to repay\n * @custom:event Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\n * @custom:error HealBorrowUnauthorized is thrown when the request does not come from Comptroller\n * @custom:access Only Comptroller\n */\n function healBorrow(address payer, address borrower, uint256 repayAmount) external override nonReentrant {\n if (repayAmount != 0) {\n comptroller.preRepayHook(address(this), borrower);\n }\n\n if (msg.sender != address(comptroller)) {\n revert HealBorrowUnauthorized();\n }\n\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n uint256 totalBorrowsNew = totalBorrows;\n\n uint256 actualRepayAmount;\n if (repayAmount != 0) {\n // _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\n // We violate checks-effects-interactions here to account for tokens that take transfer fees\n actualRepayAmount = _doTransferIn(payer, repayAmount);\n totalBorrowsNew = totalBorrowsNew - actualRepayAmount;\n emit RepayBorrow(\n payer,\n borrower,\n actualRepayAmount,\n accountBorrowsPrev - actualRepayAmount,\n totalBorrowsNew\n );\n }\n\n // The transaction will fail if trying to repay too much\n uint256 badDebtDelta = accountBorrowsPrev - actualRepayAmount;\n if (badDebtDelta != 0) {\n uint256 badDebtOld = badDebt;\n uint256 badDebtNew = badDebtOld + badDebtDelta;\n totalBorrowsNew = totalBorrowsNew - badDebtDelta;\n badDebt = badDebtNew;\n\n // We treat healing as \"repayment\", where vToken is the payer\n emit RepayBorrow(address(this), borrower, badDebtDelta, 0, totalBorrowsNew);\n emit BadDebtIncreased(borrower, badDebtDelta, badDebtOld, badDebtNew);\n }\n\n accountBorrows[borrower].principal = 0;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n emit HealBorrow(payer, borrower, repayAmount);\n }\n\n /**\n * @notice The extended version of liquidations, callable only by Comptroller. May skip\n * the close factor check. The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\n * @custom:error ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\n * @custom:access Only Comptroller\n */\n function forceLiquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) external override {\n if (msg.sender != address(comptroller)) {\n revert ForceLiquidateBorrowUnauthorized();\n }\n _liquidateBorrow(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\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 * @custom:event Emits Transfer, ReservesAdded events\n * @custom:error LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:access Not restricted\n */\n function seize(address liquidator, address borrower, uint256 seizeTokens) external override nonReentrant {\n _seize(msg.sender, liquidator, borrower, seizeTokens);\n }\n\n /**\n * @notice Updates bad debt\n * @dev Called only when bad debt is recovered from auction. Updates internal cash balance.\n * @param recoveredAmount_ The amount of bad debt recovered\n * @custom:event Emits BadDebtRecovered event\n * @custom:access Only Shortfall contract\n */\n function badDebtRecovered(uint256 recoveredAmount_) external {\n require(msg.sender == shortfall, \"only shortfall contract can update bad debt\");\n require(recoveredAmount_ <= badDebt, \"more than bad debt recovered from auction\");\n\n uint256 badDebtOld = badDebt;\n uint256 badDebtNew = badDebtOld - recoveredAmount_;\n badDebt = badDebtNew;\n internalCash += recoveredAmount_;\n\n emit BadDebtRecovered(badDebtOld, badDebtNew);\n }\n\n /**\n * @notice Sets protocol share reserve contract address\n * @param protocolShareReserve_ The address of the protocol share reserve contract\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\n * @custom:access Only Governance\n */\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\n _setProtocolShareReserve(protocolShareReserve_);\n }\n\n /**\n * @notice Sets shortfall contract address\n * @param shortfall_ The address of the shortfall contract\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\n * @custom:access Only Governance\n */\n function setShortfallContract(address shortfall_) external onlyOwner {\n _setShortfallContract(shortfall_);\n }\n\n /**\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\n * @param token The address of the ERC-20 token to sweep\n * @custom:access Only Governance\n */\n function sweepToken(IERC20Upgradeable token) external override {\n require(msg.sender == owner(), \"VToken::sweepToken: only admin can sweep tokens\");\n require(address(token) != underlying, \"VToken::sweepToken: can not sweep underlying token\");\n uint256 balance = token.balanceOf(address(this));\n token.safeTransfer(owner(), balance);\n\n emit SweepToken(address(token));\n }\n\n /**\n * @notice Sync internalCash with the actual underlying token balance\n * @dev Used for one-time migration after upgrade to initialize internalCash\n * @custom:event Emits CashSynced\n * @custom:access Controlled by AccessControlManager\n */\n function syncCash() external override nonReentrant {\n _checkAccessAllowed(\"syncCash()\");\n uint256 oldInternalCash = internalCash;\n uint256 actualCash = IERC20Upgradeable(underlying).balanceOf(address(this));\n internalCash = actualCash;\n emit CashSynced(oldInternalCash, actualCash);\n }\n\n /**\n * @notice A public function to set new threshold of slot(block or second) difference after which funds will be sent to the protocol share reserve\n * @param _newReduceReservesBlockOrTimestampDelta slot(block or second) difference value\n * @custom:access Only Governance\n */\n function setReduceReservesBlockDelta(uint256 _newReduceReservesBlockOrTimestampDelta) external {\n _checkAccessAllowed(\"setReduceReservesBlockDelta(uint256)\");\n require(_newReduceReservesBlockOrTimestampDelta > 0, \"Invalid Input\");\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, _newReduceReservesBlockOrTimestampDelta);\n reduceReservesBlockDelta = _newReduceReservesBlockOrTimestampDelta;\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 amount 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 amount 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 error Always NO_ERROR for compatibility with Venus core tooling\n * @return vTokenBalance User's balance of vTokens\n * @return borrowBalance Amount owed in terms of underlying\n * @return exchangeRate Stored exchange rate\n */\n function getAccountSnapshot(\n address account\n )\n external\n view\n override\n returns (uint256 error, uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRate)\n {\n return (NO_ERROR, accountTokens[account], _borrowBalanceStored(account), _exchangeRateStored());\n }\n\n /**\n * @notice Get the internally tracked cash balance of this vToken in the underlying asset\n * @return cash The quantity of underlying asset tracked internally by this contract\n */\n function getCash() external view override returns (uint256) {\n return _getCashPrior();\n }\n\n /**\n * @notice Returns the current per slot(block or second) borrow interest rate for this vToken\n * @return rate The borrow interest rate per slot(block or second), scaled by 1e18\n */\n function borrowRatePerBlock() external view override returns (uint256) {\n return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt);\n }\n\n /**\n * @notice Returns the current per-slot(block or second) supply interest rate for this v\n * @return rate The supply interest rate per slot(block or second), scaled by 1e18\n */\n function supplyRatePerBlock() external view override returns (uint256) {\n return\n interestRateModel.getSupplyRate(\n _getCashPrior(),\n totalBorrows,\n totalReserves,\n reserveFactorMantissa,\n badDebt\n );\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 borrowBalance The calculated balance\n */\n function borrowBalanceStored(address account) external view override returns (uint256) {\n return _borrowBalanceStored(account);\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 exchangeRate Calculated exchange rate scaled by 1e18\n */\n function exchangeRateStored() external view override returns (uint256) {\n return _exchangeRateStored();\n }\n\n /**\n * @notice Accrue interest then return the up-to-date exchange rate\n * @return exchangeRate Calculated exchange rate scaled by 1e18\n */\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\n accrueInterest();\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 slot(block or second)\n * up to the current slot(block or second) and writes new checkpoint to storage and\n * reduce spread reserves to protocol share reserve\n * if currentSlot - reduceReservesBlockNumber >= slotDelta\n * @return Always NO_ERROR\n * @custom:event Emits AccrueInterest event on success\n * @custom:access Not restricted\n */\n function accrueInterest() public virtual override returns (uint256) {\n /* Remember the initial block number or timestamp */\n uint256 currentSlotNumber = getBlockNumberOrTimestamp();\n uint256 accrualSlotNumberPrior = accrualBlockNumber;\n\n /* Short-circuit accumulating 0 interest */\n if (accrualSlotNumberPrior == currentSlotNumber) {\n return NO_ERROR;\n }\n\n /* Read the previous values out of storage */\n uint256 cashPrior = _getCashPrior();\n uint256 borrowsPrior = totalBorrows;\n uint256 reservesPrior = totalReserves;\n uint256 borrowIndexPrior = borrowIndex;\n\n /* Calculate the current borrow interest rate */\n uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt);\n require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, \"borrow rate is absurdly high\");\n\n /* Calculate the number of slots elapsed since the last accrual */\n uint256 slotDelta = currentSlotNumber - accrualSlotNumberPrior;\n\n /*\n * Calculate the interest accumulated into borrows and reserves and the new index:\n * simpleInterestFactor = borrowRate * slotDelta\n * interestAccumulated = simpleInterestFactor * totalBorrows\n * totalBorrowsNew = interestAccumulated + totalBorrows\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\n */\n\n Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), slotDelta);\n uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\n uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;\n uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\n Exp({ mantissa: reserveFactorMantissa }),\n interestAccumulated,\n reservesPrior\n );\n uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the previously calculated values into storage */\n accrualBlockNumber = currentSlotNumber;\n borrowIndex = borrowIndexNew;\n totalBorrows = totalBorrowsNew;\n totalReserves = totalReservesNew;\n\n if (currentSlotNumber - reduceReservesBlockNumber >= reduceReservesBlockDelta) {\n reduceReservesBlockNumber = currentSlotNumber;\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 NO_ERROR;\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 or timestamp\n * @param payer The address of the account which is sending the assets for supply\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 */\n function _mintFresh(address payer, address minter, uint256 mintAmount) internal {\n /* Fail if mint not allowed */\n comptroller.preMintHook(address(this), minter, mintAmount);\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert MintFreshnessCheck();\n }\n\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\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 * `_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 uint256 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 uint256 mintTokens = div_(actualMintAmount, exchangeRate);\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 * And write them into storage\n */\n totalSupply = totalSupply + mintTokens;\n uint256 balanceAfter = accountTokens[minter] + mintTokens;\n accountTokens[minter] = balanceAfter;\n\n /* We emit a Mint event, and a Transfer event */\n emit Mint(minter, actualMintAmount, mintTokens, balanceAfter);\n emit Transfer(address(0), minter, mintTokens);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.mintVerify(address(this), minter, actualMintAmount, mintTokens);\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 Comptroller.updateDelegate)\n * @dev Assumes interest has already been accrued up to the current slot(block or second)\n * @param redeemer The address of the account which is redeeming the tokens\n * @param receiver The receiver of the underlying 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 */\n function _redeemFresh(address redeemer, address receiver, uint256 redeemTokensIn, uint256 redeemAmountIn) internal {\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \"one of redeemTokensIn or redeemAmountIn must be zero\");\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert RedeemFreshnessCheck();\n }\n\n /* exchangeRate = invoke Exchange Rate Stored() */\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\n\n uint256 redeemTokens;\n uint256 redeemAmount;\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 */\n redeemTokens = redeemTokensIn;\n } else {\n /*\n * We get the current exchange rate and calculate the amount to be redeemed:\n * redeemTokens = redeemAmountIn / exchangeRate\n */\n redeemTokens = div_(redeemAmountIn, exchangeRate);\n\n uint256 _redeemAmount = mul_(redeemTokens, exchangeRate);\n if (_redeemAmount != 0 && _redeemAmount != redeemAmountIn) redeemTokens++; // round up\n }\n\n // redeemAmount = exchangeRate * redeemTokens\n redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokens);\n\n // Revert if amount is zero\n if (redeemAmount == 0) {\n revert(\"redeemAmount is zero\");\n }\n\n /* Fail if redeem not allowed */\n comptroller.preRedeemHook(address(this), redeemer, redeemTokens);\n\n /* Fail gracefully if protocol has insufficient cash */\n if (_getCashPrior() - totalReserves < redeemAmount) {\n revert RedeemTransferOutNotPossible();\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We write the previously calculated values into storage.\n * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\n */\n totalSupply = totalSupply - redeemTokens;\n uint256 balanceAfter = accountTokens[redeemer] - redeemTokens;\n accountTokens[redeemer] = balanceAfter;\n\n /*\n * We invoke _doTransferOut for the receiver and the redeemAmount.\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 _doTransferOut(receiver, redeemAmount);\n\n /* We emit a Transfer event, and a Redeem event */\n emit Transfer(redeemer, address(this), redeemTokens);\n emit Redeem(redeemer, redeemAmount, redeemTokens, balanceAfter);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.redeemVerify(address(this), redeemer, redeemAmount, redeemTokens);\n }\n\n /**\n * @notice Users or their delegates borrow assets from the protocol\n * @param borrower User who borrows the assets\n * @param receiver The receiver of the tokens, if called by a delegate\n * @param borrowAmount The amount of the underlying asset to borrow\n */\n function _borrowFresh(address borrower, address receiver, uint256 borrowAmount) internal {\n /* Fail if borrow not allowed */\n comptroller.preBorrowHook(address(this), borrower, borrowAmount);\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert BorrowFreshnessCheck();\n }\n\n /* Fail gracefully if protocol has insufficient underlying cash */\n if (_getCashPrior() - totalReserves < borrowAmount) {\n revert BorrowCashNotAvailable();\n }\n\n /*\n * We calculate the new borrower and total borrow balances, failing on overflow:\n * accountBorrowNew = accountBorrow + borrowAmount\n * totalBorrowsNew = totalBorrows + borrowAmount\n */\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;\n uint256 totalBorrowsNew = totalBorrows + borrowAmount;\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We write the previously calculated values into storage.\n * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\n `*/\n accountBorrows[borrower].principal = accountBorrowsNew;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n /*\n * We invoke _doTransferOut for the receiver and the borrowAmount.\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, accountBorrowsNew, totalBorrowsNew);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\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 underlying tokens being returned, or type(uint256).max for the full outstanding amount\n * @return (uint) the actual repayment amount.\n */\n function _repayBorrowFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256) {\n /* Fail if repayBorrow not allowed */\n comptroller.preRepayHook(address(this), borrower);\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert RepayBorrowFreshnessCheck();\n }\n\n /* We fetch the amount the borrower owes, with accumulated interest */\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n\n uint256 repayAmountFinal = repayAmount >= accountBorrowsPrev ? accountBorrowsPrev : 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 * 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 uint256 actualRepayAmount = _doTransferIn(payer, repayAmountFinal);\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 uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\n uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;\n\n /* We write the previously calculated values into storage */\n accountBorrows[borrower].principal = accountBorrowsNew;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n /* We emit a RepayBorrow event */\n emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.repayBorrowVerify(address(this), payer, borrower, actualRepayAmount, borrowIndex);\n\n return actualRepayAmount;\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n */\n function _liquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) internal nonReentrant {\n accrueInterest();\n\n uint256 error = vTokenCollateral.accrueInterest();\n if (error != NO_ERROR) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\n revert LiquidateAccrueCollateralInterestFailed(error);\n }\n\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\n }\n\n /**\n * @notice The liquidator liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n */\n function _liquidateBorrowFresh(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) internal {\n /* Fail if liquidate not allowed */\n comptroller.preLiquidateHook(\n address(this),\n address(vTokenCollateral),\n borrower,\n repayAmount,\n skipLiquidityCheck\n );\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert LiquidateFreshnessCheck();\n }\n\n /* Verify vTokenCollateral market's slot(block or second) number equals current slot(block or second) number */\n if (vTokenCollateral.accrualBlockNumber() != getBlockNumberOrTimestamp()) {\n revert LiquidateCollateralFreshnessCheck();\n }\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n revert LiquidateLiquidatorIsBorrower();\n }\n\n /* Fail if repayAmount = 0 */\n if (repayAmount == 0) {\n revert LiquidateCloseAmountIsZero();\n }\n\n /* Fail if repayAmount = type(uint256).max */\n if (repayAmount == type(uint256).max) {\n revert LiquidateCloseAmountIsUintMax();\n }\n\n /* Fail if repayBorrow fails */\n uint256 actualRepayAmount = _repayBorrowFresh(liquidator, borrower, repayAmount);\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.liquidateCalculateSeizeTokens(\n address(this),\n address(vTokenCollateral),\n actualRepayAmount\n );\n require(amountSeizeError == 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, call _seize internally to avoid re-entrancy, otherwise make an external call\n if (address(vTokenCollateral) == address(this)) {\n _seize(address(this), liquidator, borrower, seizeTokens);\n } else {\n vTokenCollateral.seize(liquidator, borrower, seizeTokens);\n }\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\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 * It's absolutely critical to use msg.sender as the seizer vToken and not a parameter.\n * @param seizerContract The contract seizing the collateral (either borrowed vToken or Comptroller)\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 */\n function _seize(address seizerContract, address liquidator, address borrower, uint256 seizeTokens) internal {\n /* Fail if seize not allowed */\n comptroller.preSeizeHook(address(this), seizerContract, liquidator, borrower);\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n revert LiquidateSeizeLiquidatorIsBorrower();\n }\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 uint256 liquidationIncentiveMantissa = ComptrollerViewInterface(address(comptroller))\n .liquidationIncentiveMantissa();\n uint256 numerator = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));\n uint256 protocolSeizeTokens = div_(numerator, Exp({ mantissa: liquidationIncentiveMantissa }));\n uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\n uint256 protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the calculated values into storage */\n totalSupply = totalSupply - protocolSeizeTokens;\n accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\n accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\n\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\n _doTransferOut(protocolShareReserve, protocolSeizeAmount);\n\n // Update the pool asset's state in the protocol share reserve for the above transfer.\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\n address(comptroller),\n underlying,\n IProtocolShareReserve.IncomeType.LIQUIDATION\n );\n\n /* Emit a Transfer event */\n emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\n emit ProtocolSeize(borrower, protocolShareReserve, protocolSeizeAmount);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.seizeVerify(address(this), seizerContract, liquidator, borrower, seizeTokens);\n }\n\n function _setComptroller(ComptrollerInterface newComptroller) internal {\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\n /**\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\n * @dev Admin function to set a new reserve factor\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\n */\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal {\n // Verify market's slot(block or second) number equals current slot(block or second) number\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert SetReserveFactorFreshCheck();\n }\n\n // Check newReserveFactor ≤ maxReserveFactor\n if (newReserveFactorMantissa > MAX_RESERVE_FACTOR_MANTISSA) {\n revert SetReserveFactorBoundsCheck();\n }\n\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\n reserveFactorMantissa = newReserveFactorMantissa;\n\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\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 actualAddAmount The actual amount added, excluding the potential token fees\n */\n function _addReservesFresh(uint256 addAmount) internal returns (uint256) {\n // totalReserves + actualAddAmount\n uint256 totalReservesNew;\n uint256 actualAddAmount;\n\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert AddReservesFactorFreshCheck(actualAddAmount);\n }\n\n actualAddAmount = _doTransferIn(msg.sender, addAmount);\n totalReservesNew = totalReserves + actualAddAmount;\n totalReserves = totalReservesNew;\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\n\n return actualAddAmount;\n }\n\n /**\n * @notice Reduces reserves by transferring to the protocol reserve contract\n * @dev Requires fresh interest accrual\n * @param reduceAmount Amount of reduction to reserves\n */\n function _reduceReservesFresh(uint256 reduceAmount) internal {\n if (reduceAmount == 0) {\n return;\n }\n // totalReserves - reduceAmount\n uint256 totalReservesNew;\n\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert ReduceReservesFreshCheck();\n }\n\n // Fail gracefully if protocol has insufficient underlying cash\n if (_getCashPrior() < reduceAmount) {\n revert ReduceReservesCashNotAvailable();\n }\n\n // Check reduceAmount ≤ reserves[n] (totalReserves)\n if (reduceAmount > totalReserves) {\n revert ReduceReservesCashValidation();\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 // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\n _doTransferOut(protocolShareReserve, reduceAmount);\n\n // Update the pool asset's state in the protocol share reserve for the above transfer.\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\n address(comptroller),\n underlying,\n IProtocolShareReserve.IncomeType.SPREAD\n );\n\n emit SpreadReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\n }\n\n /**\n * @notice updates the interest rate model (*requires fresh interest accrual)\n * @dev Admin function to update the interest rate model\n * @param newInterestRateModel the new interest rate model to use\n */\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal {\n // Used to store old model for use in the event that is emitted on success\n InterestRateModel oldInterestRateModel;\n\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert SetInterestRateModelFreshCheck();\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\n /**\n * Safe Token **\n */\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 returns (uint256) {\n IERC20Upgradeable token = IERC20Upgradeable(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 * @param to Receiver of the underlying tokens\n * @param amount Amount of underlying to transfer\n */\n function _doTransferOut(address to, uint256 amount) internal virtual {\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\n internalCash -= amount;\n token.safeTransfer(to, amount);\n }\n\n /**\n * @notice Transfer `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 */\n function _transferTokens(address spender, address src, address dst, uint256 tokens) internal {\n /* Fail if transfer not allowed */\n comptroller.preTransferHook(address(this), src, dst, tokens);\n\n /* Do not allow self-transfers */\n if (src == dst) {\n revert TransferNotAllowed();\n }\n\n /* Get the allowance, infinite for the account owner */\n uint256 startingAllowance;\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 uint256 allowanceNew = startingAllowance - tokens;\n uint256 srcTokensNew = accountTokens[src] - tokens;\n uint256 dstTokensNew = accountTokens[dst] + tokens;\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n\n accountTokens[src] = srcTokensNew;\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\n /**\n * @notice Initialize the 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_ ERC-20 name of this token\n * @param symbol_ ERC-20 symbol of this token\n * @param decimals_ ERC-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param accessControlManager_ AccessControlManager contract address\n * @param riskManagement Addresses of risk & income related contracts\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\n */\n function _initialize(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address admin_,\n address accessControlManager_,\n RiskManagementInit memory riskManagement,\n uint256 reserveFactorMantissa_\n ) internal onlyInitializing {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\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 _setComptroller(comptroller_);\n\n // Initialize slot(block or second) number and borrow index (slot(block or second) number mocks depend on comptroller being set)\n accrualBlockNumber = getBlockNumberOrTimestamp();\n borrowIndex = MANTISSA_ONE;\n\n // Set the interest rate model (depends on slot(block or second) number / borrow index)\n _setInterestRateModelFresh(interestRateModel_);\n\n _setReserveFactorFresh(reserveFactorMantissa_);\n\n name = name_;\n symbol = symbol_;\n decimals = decimals_;\n _setShortfallContract(riskManagement.shortfall);\n _setProtocolShareReserve(riskManagement.protocolShareReserve);\n protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA;\n\n // Set underlying and sanity check it\n underlying = underlying_;\n IERC20Upgradeable(underlying).totalSupply();\n\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\n _notEntered = true;\n _transferOwnership(admin_);\n }\n\n function _setShortfallContract(address shortfall_) internal {\n ensureNonzeroAddress(shortfall_);\n address oldShortfall = shortfall;\n shortfall = shortfall_;\n emit NewShortfallContract(oldShortfall, shortfall_);\n }\n\n function _setProtocolShareReserve(address payable protocolShareReserve_) internal {\n ensureNonzeroAddress(protocolShareReserve_);\n address oldProtocolShareReserve = address(protocolShareReserve);\n protocolShareReserve = protocolShareReserve_;\n emit NewProtocolShareReserve(oldProtocolShareReserve, address(protocolShareReserve_));\n }\n\n function _ensureSenderIsDelegateOf(address user) internal view {\n if (!ComptrollerViewInterface(address(comptroller)).approvedDelegates(user, msg.sender)) {\n revert DelegateNotApproved();\n }\n }\n\n /**\n * @notice Gets the internally tracked cash balance of this market\n * @dev Returns the internalCash state variable, which is updated on transfers in/out\n * @return The quantity of underlying tokens tracked internally by this contract\n */\n function _getCashPrior() internal view virtual returns (uint256) {\n return internalCash;\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 borrowBalance the calculated balance\n */\n function _borrowBalanceStored(address account) internal view returns (uint256) {\n /* Get borrowBalance and borrowIndex */\n BorrowSnapshot memory 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 0;\n }\n\n /* Calculate new borrow balance using the interest index:\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\n */\n uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;\n\n return principalTimesIndex / borrowSnapshot.interestIndex;\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 exchangeRate Calculated exchange rate scaled by 1e18\n */\n function _exchangeRateStored() internal view virtual returns (uint256) {\n uint256 _totalSupply = totalSupply;\n if (_totalSupply == 0) {\n /*\n * If there are no tokens minted:\n * exchangeRate = initialExchangeRate\n */\n return initialExchangeRateMantissa;\n }\n /*\n * Otherwise:\n * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply\n */\n uint256 totalCash = _getCashPrior();\n uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;\n uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply;\n\n return exchangeRate;\n }\n}\n" + }, + "contracts/VTokenInterfaces.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\nimport { ComptrollerInterface } from \"./ComptrollerInterface.sol\";\nimport { InterestRateModel } from \"./InterestRateModel.sol\";\n\n/**\n * @title VTokenStorage\n * @author Venus\n * @notice Storage layout used by the `VToken` contract\n */\n// solhint-disable-next-line max-states-count\ncontract VTokenStorage {\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 uint256 principal;\n uint256 interestIndex;\n }\n\n /**\n * @dev Guard variable for re-entrancy checks\n */\n bool internal _notEntered;\n\n /**\n * @notice Underlying asset for this VToken\n */\n address public underlying;\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 Protocol share Reserve contract address\n */\n address payable public protocolShareReserve;\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 InterestRateModel public interestRateModel;\n\n // Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\n uint256 internal initialExchangeRateMantissa;\n\n /**\n * @notice Fraction of interest currently set aside for reserves\n */\n uint256 public reserveFactorMantissa;\n\n /**\n * @notice Slot(block or second) number that interest was last accrued at\n */\n uint256 public accrualBlockNumber;\n\n /**\n * @notice Accumulator of the total earned interest rate since the opening of the market\n */\n uint256 public borrowIndex;\n\n /**\n * @notice Total amount of outstanding borrows of the underlying in this market\n */\n uint256 public totalBorrows;\n\n /**\n * @notice Total amount of reserves of the underlying held in this market\n */\n uint256 public totalReserves;\n\n /**\n * @notice Total number of tokens in circulation\n */\n uint256 public totalSupply;\n\n /**\n * @notice Total bad debt of the market\n */\n uint256 public badDebt;\n\n // Official record of token balances for each account\n mapping(address => uint256) internal accountTokens;\n\n // Approved token transfer amounts on behalf of others\n mapping(address => mapping(address => uint256)) internal transferAllowances;\n\n // Mapping of account addresses to outstanding borrow balances\n mapping(address => BorrowSnapshot) internal accountBorrows;\n\n /**\n * @notice Share of seized collateral that is added to reserves\n */\n uint256 public protocolSeizeShareMantissa;\n\n /**\n * @notice Storage of Shortfall contract address\n */\n address public shortfall;\n\n /**\n * @notice delta slot (block or second) after which reserves will be reduced\n */\n uint256 public reduceReservesBlockDelta;\n\n /**\n * @notice last slot (block or second) number at which reserves were reduced\n */\n uint256 public reduceReservesBlockNumber;\n\n /**\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\n * @dev Updated via _doTransferIn(), _doTransferOut(), syncCash(), and badDebtRecovered(). Must be initialized via syncCash() 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[47] private __gap;\n}\n\n/**\n * @title VTokenInterface\n * @author Venus\n * @notice Interface implemented by the `VToken` contract\n */\nabstract contract VTokenInterface is VTokenStorage {\n struct RiskManagementInit {\n address shortfall;\n address payable protocolShareReserve;\n }\n\n /*** Market Events ***/\n\n /**\n * @notice Event emitted when interest is accrued\n */\n event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\n\n /**\n * @notice Event emitted when tokens are minted\n */\n event Mint(address indexed minter, uint256 mintAmount, uint256 mintTokens, uint256 accountBalance);\n\n /**\n * @notice Event emitted when tokens are redeemed\n */\n event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens, uint256 accountBalance);\n\n /**\n * @notice Event emitted when underlying is borrowed\n */\n event Borrow(address indexed borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\n\n /**\n * @notice Event emitted when a borrow is repaid\n */\n event RepayBorrow(\n address indexed payer,\n address indexed borrower,\n uint256 repayAmount,\n uint256 accountBorrows,\n uint256 totalBorrows\n );\n\n /**\n * @notice Event emitted when bad debt is accumulated on a market\n * @param borrower borrower to \"forgive\"\n * @param badDebtDelta amount of new bad debt recorded\n * @param badDebtOld previous bad debt value\n * @param badDebtNew new bad debt value\n */\n event BadDebtIncreased(address indexed borrower, uint256 badDebtDelta, uint256 badDebtOld, uint256 badDebtNew);\n\n /**\n * @notice Event emitted when bad debt is recovered via an auction\n * @param badDebtOld previous bad debt value\n * @param badDebtNew new bad debt value\n */\n event BadDebtRecovered(uint256 badDebtOld, uint256 badDebtNew);\n\n /**\n * @notice Event emitted when a borrow is liquidated\n */\n event LiquidateBorrow(\n address indexed liquidator,\n address indexed borrower,\n uint256 repayAmount,\n address indexed vTokenCollateral,\n uint256 seizeTokens\n );\n\n /*** Admin Events ***/\n\n /**\n * @notice Event emitted when comptroller is changed\n */\n event NewComptroller(ComptrollerInterface indexed oldComptroller, ComptrollerInterface indexed newComptroller);\n\n /**\n * @notice Event emitted when shortfall contract address is changed\n */\n event NewShortfallContract(address indexed oldShortfall, address indexed newShortfall);\n\n /**\n * @notice Event emitted when protocol share reserve contract address is changed\n */\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\n\n /**\n * @notice Event emitted when interestRateModel is changed\n */\n event NewMarketInterestRateModel(\n InterestRateModel indexed oldInterestRateModel,\n InterestRateModel indexed newInterestRateModel\n );\n\n /**\n * @notice Event emitted when protocol seize share is changed\n */\n event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\n\n /**\n * @notice Event emitted when the reserve factor is changed\n */\n event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\n\n /**\n * @notice Event emitted when the reserves are added\n */\n event ReservesAdded(address indexed benefactor, uint256 addAmount, uint256 newTotalReserves);\n\n /**\n * @notice Event emitted when the spread reserves are reduced\n */\n event SpreadReservesReduced(address indexed protocolShareReserve, uint256 reduceAmount, uint256 newTotalReserves);\n\n /**\n * @notice EIP20 Transfer event\n */\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n /**\n * @notice EIP20 Approval event\n */\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /**\n * @notice Event emitted when healing the borrow\n */\n event HealBorrow(address indexed payer, address indexed borrower, uint256 repayAmount);\n\n /**\n * @notice Event emitted when tokens are swept\n */\n event SweepToken(address indexed token);\n\n /**\n * @notice Event emitted when reduce reserves slot (block or second) delta is changed\n */\n event NewReduceReservesBlockDelta(\n uint256 oldReduceReservesBlockOrTimestampDelta,\n uint256 newReduceReservesBlockOrTimestampDelta\n );\n\n /**\n * @notice Event emitted when liquidation reserves are reduced\n */\n event ProtocolSeize(address indexed from, address indexed to, uint256 amount);\n\n /**\n * @notice Event emitted when internalCash is synced with actual token balance\n */\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\n\n /*** User Interface ***/\n\n function mint(uint256 mintAmount) external virtual returns (uint256);\n\n function mintBehalf(address minter, uint256 mintAllowed) external virtual returns (uint256);\n\n function redeem(uint256 redeemTokens) external virtual returns (uint256);\n\n function redeemBehalf(address redeemer, uint256 redeemTokens) external virtual returns (uint256);\n\n function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);\n\n function redeemUnderlyingBehalf(address redeemer, uint256 redeemAmount) external virtual returns (uint256);\n\n function borrow(uint256 borrowAmount) external virtual returns (uint256);\n\n function borrowBehalf(address borrwwer, uint256 borrowAmount) external virtual returns (uint256);\n\n function repayBorrow(uint256 repayAmount) external virtual returns (uint256);\n\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);\n\n function liquidateBorrow(\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) external virtual returns (uint256);\n\n function healBorrow(address payer, address borrower, uint256 repayAmount) external virtual;\n\n function forceLiquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipCloseFactorCheck\n ) external virtual;\n\n function seize(address liquidator, address borrower, uint256 seizeTokens) external virtual;\n\n function transfer(address dst, uint256 amount) external virtual returns (bool);\n\n function transferFrom(address src, address dst, uint256 amount) external virtual returns (bool);\n\n function accrueInterest() external virtual returns (uint256);\n\n function sweepToken(IERC20Upgradeable token) external virtual;\n\n /*** Admin Functions ***/\n\n function setReserveFactor(uint256 newReserveFactorMantissa) external virtual;\n\n function reduceReserves(uint256 reduceAmount) external virtual;\n\n function exchangeRateCurrent() external virtual returns (uint256);\n\n function borrowBalanceCurrent(address account) external virtual returns (uint256);\n\n function setInterestRateModel(InterestRateModel newInterestRateModel) external virtual;\n\n function addReserves(uint256 addAmount) external virtual;\n\n function syncCash() external virtual;\n\n function totalBorrowsCurrent() external virtual returns (uint256);\n\n function balanceOfUnderlying(address owner) external virtual returns (uint256);\n\n function approve(address spender, uint256 amount) external virtual returns (bool);\n\n function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool);\n\n function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool);\n\n function allowance(address owner, address spender) external view virtual returns (uint256);\n\n function balanceOf(address owner) external view virtual returns (uint256);\n\n function getAccountSnapshot(address account) external view virtual returns (uint256, uint256, uint256, uint256);\n\n function borrowRatePerBlock() external view virtual returns (uint256);\n\n function supplyRatePerBlock() external view virtual returns (uint256);\n\n function borrowBalanceStored(address account) external view virtual returns (uint256);\n\n function exchangeRateStored() external view virtual returns (uint256);\n\n function getCash() external view virtual returns (uint256);\n\n /**\n * @notice Indicator that this is a VToken contract (for inspection)\n * @return Always true\n */\n function isVToken() external pure virtual returns (bool) {\n return true;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200, + "details": { + "yul": true + } + }, + "evmVersion": "paris", + "outputSelection": { + "*": { + "*": [ + "storageLayout", + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} diff --git a/deployments/basemainnet_addresses.json b/deployments/basemainnet_addresses.json index 97dd220f0..176b701b7 100644 --- a/deployments/basemainnet_addresses.json +++ b/deployments/basemainnet_addresses.json @@ -11,7 +11,7 @@ "JumpRateModelV2_base0bps_slope800bps_jump25000bps_kink8000bps_timeBased": "0xB7FCED42486F8DB8155fD509e726F9604fCdd41F", "JumpRateModelV2_base0bps_slope900bps_jump30000bps_kink4500bps_timeBased": "0x527c29aAfB367fAd5AFf97855EBFAa610AA514CA", "NativeTokenGateway_vWETH_Core": "0x8e890ca3829c740895cdEACd4a3BE36ff9343643", - "PoolLens": "0x89825677fb4845f5Fc0B227e387455ECa1200058", + "PoolLens": "0x70F86E84CfB7c5bd8E845aC643c2BDBFf811F335", "PoolRegistry": "0xeef902918DdeCD773D4B422aa1C6e1673EB9136F", "PoolRegistry_Implementation": "0x88eF9Fd7004f81c1B1CA59375178425C97A7eE68", "PoolRegistry_Proxy": "0xeef902918DdeCD773D4B422aa1C6e1673EB9136F", diff --git a/deployments/ethereum.json b/deployments/ethereum.json index 91fbf36e6..4f3162119 100644 --- a/deployments/ethereum.json +++ b/deployments/ethereum.json @@ -13720,7 +13720,7 @@ ] }, "PoolLens": { - "address": "0x277950603178BDD223eB53B9b7cF5D0053aa3473", + "address": "0x3716C24EA86A67cAf890d7C9e4C4505cDDC2F8A2", "abi": [ { "inputs": [ @@ -13733,6 +13733,11 @@ "internalType": "uint256", "name": "blocksPerYear_", "type": "uint256" + }, + { + "internalType": "address", + "name": "corePoolComptroller_", + "type": "address" } ], "stateMutability": "nonpayable", @@ -13761,6 +13766,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "corePoolComptroller", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { diff --git a/deployments/ethereum/PoolLens.json b/deployments/ethereum/PoolLens.json index 7b3fa188c..5b6047a56 100644 --- a/deployments/ethereum/PoolLens.json +++ b/deployments/ethereum/PoolLens.json @@ -1,5 +1,5 @@ { - "address": "0x277950603178BDD223eB53B9b7cF5D0053aa3473", + "address": "0x3716C24EA86A67cAf890d7C9e4C4505cDDC2F8A2", "abi": [ { "inputs": [ @@ -12,6 +12,11 @@ "internalType": "uint256", "name": "blocksPerYear_", "type": "uint256" + }, + { + "internalType": "address", + "name": "corePoolComptroller_", + "type": "address" } ], "stateMutability": "nonpayable", @@ -40,6 +45,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "corePoolComptroller", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -1168,28 +1186,28 @@ "type": "function" } ], - "transactionHash": "0x0725ae4f818886ea6eab00f0703882316e7487238f1d86bcdc7a7f4ae713330b", + "transactionHash": "0xca8a106be49ad039c078c7072aa8910e5f1066c97e6281984ab8f346266c1831", "receipt": { "to": null, - "from": "0x63c72cf38D2C35278e2F18A4FE79225A66dFA942", - "contractAddress": "0x277950603178BDD223eB53B9b7cF5D0053aa3473", - "transactionIndex": 2, - "gasUsed": "3548925", + "from": "0xA9d02961b4B8902023Ce464F47502950f6e359b4", + "contractAddress": "0x3716C24EA86A67cAf890d7C9e4C4505cDDC2F8A2", + "transactionIndex": 373, + "gasUsed": "3593167", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xca182ee4bbfba291adc37a80361be201bae2dc69c7a22c1cec84cc78288c09f0", - "transactionHash": "0x0725ae4f818886ea6eab00f0703882316e7487238f1d86bcdc7a7f4ae713330b", + "blockHash": "0xf6f3508d7eace24fec0c8d5f4547f78abbd092ebcf29de57d8069aea043b4e7e", + "transactionHash": "0xca8a106be49ad039c078c7072aa8910e5f1066c97e6281984ab8f346266c1831", "logs": [], - "blockNumber": 22886599, - "cumulativeGasUsed": "3892542", + "blockNumber": 24777668, + "cumulativeGasUsed": "48687209", "status": 1, "byzantium": true }, - "args": [false, 2628000], - "numDeployments": 4, - "solcInputHash": "5d85ae64b25e3c9d9e054a829e1676d1", - "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"timeBased_\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"blocksPerYear_\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidBlocksPerYear\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTimeBasedConfiguration\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"blocksOrSecondsPerYear\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"}],\"name\":\"getAllPools\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockNumberOrTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getPendingRewards\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"distributorAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"rewardTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalRewards\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.PendingReward[]\",\"name\":\"pendingRewards\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.RewardSummary[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getPoolBadDebt\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalBadDebtUsd\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"badDebtUsd\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.BadDebt[]\",\"name\":\"badDebts\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.BadDebtSummary\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolByComptroller\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolRegistryInterface.VenusPool\",\"name\":\"venusPool\",\"type\":\"tuple\"}],\"name\":\"getPoolDataFromVenusPool\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getPoolsSupportedByAsset\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getVTokenForAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isTimeBased\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"vTokenBalances\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalanceCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balanceOfUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenAllowance\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenBalances\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"vTokenBalancesAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalanceCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balanceOfUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenAllowance\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenBalances[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"vTokenMetadata\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"vTokenMetadataAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"vTokenUnderlyingPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"underlyingPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenUnderlyingPrice\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"vTokenUnderlyingPriceAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"underlyingPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenUnderlyingPrice[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"params\":{\"blocksPerYear_\":\"The number of blocks per year\",\"timeBased_\":\"A boolean indicating whether the contract is based on time or block.\"}},\"getAllPools(address)\":{\"details\":\"This function is not designed to be called in a transaction: it is too gas-intensive\",\"params\":{\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"Arrays of all Venus pools' data\"}},\"getBlockNumberOrTimestamp()\":{\"details\":\"Function to simply retrieve block number or block timestamp\",\"returns\":{\"_0\":\"Current block number or block timestamp\"}},\"getPendingRewards(address,address)\":{\"params\":{\"account\":\"The user account.\",\"comptrollerAddress\":\"address\"},\"returns\":{\"_0\":\"Pending rewards array\"}},\"getPoolBadDebt(address)\":{\"params\":{\"comptrollerAddress\":\"Address of the comptroller\"},\"returns\":{\"_0\":\"badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and a break down of bad debt by market\"}},\"getPoolByComptroller(address,address)\":{\"params\":{\"comptroller\":\"The Comptroller implementation address\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"PoolData structure containing the details of the pool\"}},\"getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))\":{\"params\":{\"poolRegistryAddress\":\"Address of the PoolRegistry\",\"venusPool\":\"The VenusPool Object from PoolRegistry\"},\"returns\":{\"_0\":\"Enriched PoolData\"}},\"getPoolsSupportedByAsset(address,address)\":{\"params\":{\"asset\":\"The underlying asset of vToken\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"A list of Comptroller contracts\"}},\"getVTokenForAsset(address,address,address)\":{\"params\":{\"asset\":\"The underlyingAsset of VToken\",\"comptroller\":\"The pool comptroller\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"Address of the vToken\"}},\"vTokenBalances(address,address)\":{\"params\":{\"account\":\"The user Account\",\"vToken\":\"vToken address\"},\"returns\":{\"_0\":\"A struct containing the balances data\"}},\"vTokenBalancesAll(address[],address)\":{\"params\":{\"account\":\"The user Account\",\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"A list of structs containing balances data\"}},\"vTokenMetadata(address)\":{\"params\":{\"vToken\":\"The address of vToken\"},\"returns\":{\"_0\":\"VTokenMetadata struct\"}},\"vTokenMetadataAll(address[])\":{\"params\":{\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"An array of VTokenMetadata structs\"}},\"vTokenUnderlyingPrice(address)\":{\"params\":{\"vToken\":\"vToken address\"},\"returns\":{\"_0\":\"The price data for each asset\"}},\"vTokenUnderlyingPriceAll(address[])\":{\"params\":{\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"An array containing the price data for each asset\"}}},\"title\":\"PoolLens\",\"version\":1},\"userdoc\":{\"errors\":{\"InvalidBlocksPerYear()\":[{\"notice\":\"Thrown when blocks per year is invalid\"}],\"InvalidTimeBasedConfiguration()\":[{\"notice\":\"Thrown when time based but blocks per year is provided\"}]},\"kind\":\"user\",\"methods\":{\"blocksOrSecondsPerYear()\":{\"notice\":\"Stores blocksPerYear if isTimeBased is true else secondsPerYear is stored\"},\"getAllPools(address)\":{\"notice\":\"Queries all pools with addtional details for each of them\"},\"getPendingRewards(address,address)\":{\"notice\":\"Returns the pending rewards for a user for a given pool.\"},\"getPoolBadDebt(address)\":{\"notice\":\"Returns a summary of a pool's bad debt broken down by market\"},\"getPoolByComptroller(address,address)\":{\"notice\":\"Queries the details of a pool identified by Comptroller address\"},\"getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))\":{\"notice\":\"Queries additional information for the pool\"},\"getPoolsSupportedByAsset(address,address)\":{\"notice\":\"Returns all pools that support the specified underlying asset\"},\"getVTokenForAsset(address,address,address)\":{\"notice\":\"Returns vToken holding the specified underlying asset in the specified pool\"},\"isTimeBased()\":{\"notice\":\"Acknowledges if a contract is time based or not\"},\"vTokenBalances(address,address)\":{\"notice\":\"Queries the user's supply/borrow balances in the specified vToken\"},\"vTokenBalancesAll(address[],address)\":{\"notice\":\"Queries the user's supply/borrow balances in vTokens\"},\"vTokenMetadata(address)\":{\"notice\":\"Returns the metadata of VToken\"},\"vTokenMetadataAll(address[])\":{\"notice\":\"Returns the metadata of all VTokens\"},\"vTokenUnderlyingPrice(address)\":{\"notice\":\"Returns the price data for the underlying asset of the specified vToken\"},\"vTokenUnderlyingPriceAll(address[])\":{\"notice\":\"Returns the price data for the underlying assets of the specified vTokens\"}},\"notice\":\"The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be looked up for specific pools and markets: - the vToken balance of a given user; - the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address; - the vToken address in a pool for a given asset; - a list of all pools that support an asset; - the underlying asset price of a vToken; - the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Lens/PoolLens.sol\":\"PoolLens\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"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\",\"keccak256\":\"0x9140dabc466abab21b48b72dbda26736b1183a310d0e677d3719d201df026510\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x359a1ab89b46b9aba7bcad3fb651924baf4893d15153049b9976b0fc9be1358e\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x07e881de3b9f6d2c07909f193f24b96c7fe4ea60013260f3f25aecd8bab3c2f8\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x75097e35253e7fb282ee4d7f27a80eaacfa759923185bf17302a89cbc059c5ef\",\"license\":\"MIT\"},\"@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\"},\"@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 private _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\",\"keccak256\":\"0x0dcf283925f4dddc23ca0ee71d2cb96a9dd6e4cf08061b69fde1697ea39dc514\",\"license\":\"BSD-3-Clause\"},\"@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/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface IProtocolShareReserve {\\n /// @notice it represents the type of vToken income\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION\\n }\\n\\n function updateAssetsState(\\n address comptroller,\\n address asset,\\n IncomeType incomeType\\n ) external;\\n}\\n\",\"keccak256\":\"0x5fddc5b63fdd850b3b5c83576cda50dcb27a205dbb1a23af17d9da0d9f04fa0a\",\"license\":\"BSD-3-Clause\"},\"@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\",\"keccak256\":\"0x57a2bbb9b8e02b1c0a5c0e305fef1328a22db56c3d4b148c362010a6e767243c\",\"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\"},\"@venusprotocol/venus-protocol/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\",\"keccak256\":\"0xd112f60183416ad796093b4a83a80ddc1b8b655965f02ae55ca82e2a0c68f97d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/venus-protocol/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\",\"keccak256\":\"0x5285c875114db2ea2be0b81b65722d5761806217022db733323c4e03365a95e7\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IPrime } from \\\"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\\\";\\n\\nimport { ComptrollerInterface, Action } from \\\"./ComptrollerInterface.sol\\\";\\nimport { ComptrollerStorage } from \\\"./ComptrollerStorage.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"./MaxLoopsLimitHelper.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title Comptroller\\n * @author Venus\\n * @notice The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating,\\n * and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts\\n * with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows\\n * or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing\\n * liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow,\\n * as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the\\n * markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market\\u2019s corresponding liquidation threshold,\\n * the borrow is eligible for liquidation.\\n *\\n * The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed\\n * the `minLiquidatableCollateral` for the `Comptroller`:\\n *\\n * - `healAccount()`: This function is called to seize all of a given user\\u2019s collateral, requiring the `msg.sender` repay a certain percentage\\n * of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed\\n * 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt\\n * and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool.\\n * - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation\\n * incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic\\n * verifying that the repay amount does not exceed the close factor.\\n */\\ncontract Comptroller is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n ComptrollerStorage,\\n ComptrollerInterface,\\n ExponentialNoError,\\n MaxLoopsLimitHelper\\n{\\n // PoolRegistry, immutable to save on gas\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable poolRegistry;\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(VToken indexed vToken, address indexed account);\\n\\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(VToken vToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa);\\n\\n /// @notice Emitted when liquidation threshold is changed by admin\\n event NewLiquidationThreshold(\\n VToken vToken,\\n uint256 oldLiquidationThresholdMantissa,\\n uint256 newLiquidationThresholdMantissa\\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 an action is paused on a market\\n event ActionPausedMarket(VToken vToken, Action action, bool pauseState);\\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 the collateral threshold (in USD) for non-batch liquidations is changed\\n event NewMinLiquidatableCollateral(uint256 oldMinLiquidatableCollateral, uint256 newMinLiquidatableCollateral);\\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 a rewards distributor is added\\n event NewRewardsDistributor(address indexed rewardsDistributor, address indexed rewardToken);\\n\\n /// @notice Emitted when a market is supported\\n event MarketSupported(VToken vToken);\\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 a market\\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\\n\\n /// @notice Emitted when a market is unlisted\\n event MarketUnlisted(address indexed vToken);\\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 Thrown when collateral factor exceeds the upper bound\\n error InvalidCollateralFactor();\\n\\n /// @notice Thrown when liquidation threshold exceeds the collateral factor\\n error InvalidLiquidationThreshold();\\n\\n /// @notice Thrown when the action is only available to specific sender, but the real sender was different\\n error UnexpectedSender(address expectedSender, address actualSender);\\n\\n /// @notice Thrown when the oracle returns an invalid price for some asset\\n error PriceError(address vToken);\\n\\n /// @notice Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\\n error SnapshotError(address vToken, address user);\\n\\n /// @notice Thrown when the market is not listed\\n error MarketNotListed(address market);\\n\\n /// @notice Thrown when a market has an unexpected comptroller\\n error ComptrollerMismatch();\\n\\n /// @notice Thrown when user is not member of market\\n error MarketNotCollateral(address vToken, address user);\\n\\n /// @notice Thrown when borrow action is not paused\\n error BorrowActionNotPaused();\\n\\n /// @notice Thrown when mint action is not paused\\n error MintActionNotPaused();\\n\\n /// @notice Thrown when redeem action is not paused\\n error RedeemActionNotPaused();\\n\\n /// @notice Thrown when repay action is not paused\\n error RepayActionNotPaused();\\n\\n /// @notice Thrown when seize action is not paused\\n error SeizeActionNotPaused();\\n\\n /// @notice Thrown when exit market action is not paused\\n error ExitMarketActionNotPaused();\\n\\n /// @notice Thrown when transfer action is not paused\\n error TransferActionNotPaused();\\n\\n /// @notice Thrown when enter market action is not paused\\n error EnterMarketActionNotPaused();\\n\\n /// @notice Thrown when liquidate action is not paused\\n error LiquidateActionNotPaused();\\n\\n /// @notice Thrown when borrow cap is not zero\\n error BorrowCapIsNotZero();\\n\\n /// @notice Thrown when supply cap is not zero\\n error SupplyCapIsNotZero();\\n\\n /// @notice Thrown when collateral factor is not zero\\n error CollateralFactorIsNotZero();\\n\\n /**\\n * @notice Thrown during the liquidation if user's total collateral amount is lower than\\n * a predefined threshold. In this case only batch liquidations (either liquidateAccount\\n * or healAccount) are available.\\n */\\n error MinimalCollateralViolated(uint256 expectedGreaterThan, uint256 actual);\\n error CollateralExceedsThreshold(uint256 expectedLessThanOrEqualTo, uint256 actual);\\n error InsufficientCollateral(uint256 collateralToSeize, uint256 availableCollateral);\\n\\n /// @notice Thrown when the account doesn't have enough liquidity to redeem or borrow\\n error InsufficientLiquidity();\\n\\n /// @notice Thrown when trying to liquidate a healthy account\\n error InsufficientShortfall();\\n\\n /// @notice Thrown when trying to repay more than allowed by close factor\\n error TooMuchRepay();\\n\\n /// @notice Thrown if the user is trying to exit a market in which they have an outstanding debt\\n error NonzeroBorrowBalance();\\n\\n /// @notice Thrown when trying to perform an action that is paused\\n error ActionPaused(address market, Action action);\\n\\n /// @notice Thrown when trying to add a market that is already listed\\n error MarketAlreadyListed(address market);\\n\\n /// @notice Thrown if the supply cap is exceeded\\n error SupplyCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if the borrow cap is exceeded\\n error BorrowCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if delegate approval status is already set to the requested value\\n error DelegationStatusUnchanged();\\n\\n /// @param poolRegistry_ Pool registry address\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n constructor(address poolRegistry_) {\\n ensureNonzeroAddress(poolRegistry_);\\n\\n poolRegistry = poolRegistry_;\\n _disableInitializers();\\n }\\n\\n /**\\n * @param loopLimit Limit for the loops can iterate to avoid the DOS\\n * @param accessControlManager Access control manager contract address\\n */\\n function initialize(uint256 loopLimit, address accessControlManager) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager);\\n\\n _setMaxLoopsLimit(loopLimit);\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation; enabling them to be used as collateral\\n * @param vTokens The list of addresses of the vToken markets to be enabled\\n * @return errors An array of NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketEntered is emitted for each market on success\\n * @custom:error ActionPaused error is thrown if entering any of the markets is paused\\n * @custom:error MarketNotListed error is thrown if any of the markets is not listed\\n * @custom:access Not restricted\\n */\\n function enterMarkets(address[] memory vTokens) external override returns (uint256[] memory) {\\n uint256 len = vTokens.length;\\n\\n uint256[] memory results = new uint256[](len);\\n for (uint256 i; i < len; ++i) {\\n VToken vToken = VToken(vTokens[i]);\\n\\n _addToMarket(vToken, msg.sender);\\n results[i] = NO_ERROR;\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Unlist a market by setting isListed to false\\n * @dev Checks if all actions are paused, borrow/supply caps is set to 0 and collateral factor is to 0.\\n * @param market The address of the market (token) to unlist\\n * @return uint256 Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketUnlisted is emitted on success\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error BorrowActionNotPaused error is thrown if borrow action is not paused\\n * @custom:error MintActionNotPaused error is thrown if mint action is not paused\\n * @custom:error RedeemActionNotPaused error is thrown if redeem action is not paused\\n * @custom:error RepayActionNotPaused error is thrown if repay action is not paused\\n * @custom:error EnterMarketActionNotPaused error is thrown if enter market action is not paused\\n * @custom:error LiquidateActionNotPaused error is thrown if liquidate action is not paused\\n * @custom:error BorrowCapIsNotZero error is thrown if borrow cap is not zero\\n * @custom:error SupplyCapIsNotZero error is thrown if supply cap is not zero\\n * @custom:error CollateralFactorIsNotZero error is thrown if collateral factor is not zero\\n */\\n function unlistMarket(address market) external returns (uint256) {\\n _checkAccessAllowed(\\\"unlistMarket(address)\\\");\\n\\n Market storage _market = markets[market];\\n\\n if (!_market.isListed) {\\n revert MarketNotListed(market);\\n }\\n\\n if (!actionPaused(market, Action.BORROW)) {\\n revert BorrowActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.MINT)) {\\n revert MintActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.REDEEM)) {\\n revert RedeemActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.REPAY)) {\\n revert RepayActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.SEIZE)) {\\n revert SeizeActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.ENTER_MARKET)) {\\n revert EnterMarketActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.LIQUIDATE)) {\\n revert LiquidateActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.TRANSFER)) {\\n revert TransferActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.EXIT_MARKET)) {\\n revert ExitMarketActionNotPaused();\\n }\\n\\n if (borrowCaps[market] != 0) {\\n revert BorrowCapIsNotZero();\\n }\\n\\n if (supplyCaps[market] != 0) {\\n revert SupplyCapIsNotZero();\\n }\\n\\n if (_market.collateralFactorMantissa != 0) {\\n revert CollateralFactorIsNotZero();\\n }\\n\\n _market.isListed = false;\\n emit MarketUnlisted(market);\\n\\n return NO_ERROR;\\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 * @custom:event DelegateUpdated emits on success\\n * @custom:error ZeroAddressNotAllowed is thrown when delegate address is zero\\n * @custom:error DelegationStatusUnchanged is thrown if approval status is already set to the requested value\\n * @custom:access Not restricted\\n */\\n function updateDelegate(address delegate, bool approved) external {\\n ensureNonzeroAddress(delegate);\\n if (approvedDelegates[msg.sender][delegate] == approved) {\\n revert DelegationStatusUnchanged();\\n }\\n\\n approvedDelegates[msg.sender][delegate] = approved;\\n emit DelegateUpdated(msg.sender, delegate, approved);\\n }\\n\\n /**\\n * @notice Removes asset from sender's account liquidity calculation; disabling them as collateral\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketExited is emitted on success\\n * @custom:error ActionPaused error is thrown if exiting the market is paused\\n * @custom:error NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function exitMarket(address vTokenAddress) external override returns (uint256) {\\n _checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\\n VToken vToken = VToken(vTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\\n (uint256 tokensHeld, uint256 amountOwed, ) = _safeGetAccountSnapshot(vToken, msg.sender);\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n revert NonzeroBorrowBalance();\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n _checkRedeemAllowed(vTokenAddress, msg.sender, tokensHeld);\\n\\n Market storage marketToExit = markets[address(vToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return 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 // load into memory for faster iteration\\n VToken[] memory userAssetList = accountAssets[msg.sender];\\n uint256 len = userAssetList.length;\\n\\n uint256 assetIndex = len;\\n for (uint256 i; i < len; ++i) {\\n if (userAssetList[i] == vToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n VToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.pop();\\n\\n emit MarketExited(vToken, msg.sender);\\n\\n return NO_ERROR;\\n }\\n\\n /*** Policy Hooks ***/\\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 * @custom:error ActionPaused error is thrown if supplying to this market is paused\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\\n * @custom:access Not restricted\\n */\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external override {\\n _checkActionPauseState(vToken, Action.MINT);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n uint256 supplyCap = supplyCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (supplyCap != type(uint256).max) {\\n uint256 vTokenSupply = VToken(vToken).totalSupply();\\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\\n if (nextTotalSupply > supplyCap) {\\n revert SupplyCapExceeded(vToken, supplyCap);\\n }\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, minter);\\n }\\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external override {\\n _checkActionPauseState(vToken, Action.REDEEM);\\n\\n _checkRedeemAllowed(vToken, redeemer, redeemTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, redeemer);\\n }\\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 if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(redeemer, vToken);\\n }\\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 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 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 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 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 * @custom:error ActionPaused error is thrown if borrowing is paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if there is not enough collateral to borrow\\n * @custom:error BorrowCapExceeded is thrown if the borrow cap will be exceeded should this borrow succeed\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted if vToken is enabled as collateral, otherwise only vToken\\n */\\n /// disable-eslint\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external override {\\n _checkActionPauseState(vToken, Action.BORROW);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (!markets[vToken].accountMembership[borrower]) {\\n // only vTokens may call borrowAllowed if borrower not in market\\n _checkSenderIs(vToken);\\n\\n // attempt to add borrower to the market or revert\\n _addToMarket(VToken(msg.sender), borrower);\\n }\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (oracle.getUnderlyingPrice(vToken) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 borrowCap = borrowCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (borrowCap != type(uint256).max) {\\n uint256 totalBorrows = VToken(vToken).totalBorrows();\\n uint256 badDebt = VToken(vToken).badDebt();\\n uint256 nextTotalBorrows = totalBorrows + borrowAmount + badDebt;\\n if (nextTotalBorrows > borrowCap) {\\n revert BorrowCapExceeded(vToken, borrowCap);\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n borrower,\\n VToken(vToken),\\n 0,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\n }\\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 borrower The account which would borrowed the asset\\n * @custom:error ActionPaused error is thrown if repayments are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:access Not restricted\\n */\\n function preRepayHook(address vToken, address borrower) external override {\\n _checkActionPauseState(vToken, Action.REPAY);\\n\\n oracle.updatePrice(vToken);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\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 borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n * @param skipLiquidityCheck Allows the borrow to be liquidated regardless of the account liquidity\\n * @custom:error ActionPaused error is thrown if liquidations are paused in this market\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor\\n * @custom:error MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations\\n * @custom:error InsufficientShortfall is thrown when trying to liquidate a healthy account\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n */\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external override {\\n // Pause Action.LIQUIDATE on BORROWED TOKEN to prevent liquidating it.\\n // If we want to pause liquidating to vTokenCollateral, we should pause\\n // Action.SEIZE on it\\n _checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(address(vTokenBorrowed));\\n }\\n if (!markets[vTokenCollateral].isListed) {\\n revert MarketNotListed(address(vTokenCollateral));\\n }\\n\\n uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\\n\\n /* Allow accounts to be liquidated if it is a forced liquidation */\\n if (skipLiquidityCheck || isForcedLiquidationEnabled[vTokenBorrowed]) {\\n if (repayAmount > borrowBalance) {\\n revert TooMuchRepay();\\n }\\n return;\\n }\\n\\n /* The borrower must have shortfall and collateral > threshold in order to be liquidatable */\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral <= minLiquidatableCollateral) {\\n /* The liquidator should use either liquidateAccount or healAccount */\\n revert MinimalCollateralViolated(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint256 maxClose = mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance);\\n if (repayAmount > maxClose) {\\n revert TooMuchRepay();\\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 seizerContract Contract that tries to seize the asset (either borrowed vToken or Comptroller)\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @custom:error ActionPaused error is thrown if seizing this type of collateral is paused\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error ComptrollerMismatch error is when seizer contract or seized asset belong to different pools\\n * @custom:access Not restricted\\n */\\n function preSeizeHook(\\n address vTokenCollateral,\\n address seizerContract,\\n address liquidator,\\n address borrower\\n ) external override {\\n // Pause Action.SEIZE on COLLATERAL to prevent seizing it.\\n // If we want to pause liquidating vTokenBorrowed, we should pause\\n // Action.LIQUIDATE on it\\n _checkActionPauseState(vTokenCollateral, Action.SEIZE);\\n\\n Market storage market = markets[vTokenCollateral];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(vTokenCollateral);\\n }\\n\\n if (seizerContract == address(this)) {\\n // If Comptroller is the seizer, just check if collateral's comptroller\\n // is equal to the current address\\n if (address(VToken(vTokenCollateral).comptroller()) != address(this)) {\\n revert ComptrollerMismatch();\\n }\\n } else {\\n // If the seizer is not the Comptroller, check that the seizer is a\\n // listed market, and that the markets' comptrollers match\\n if (!markets[seizerContract].isListed) {\\n revert MarketNotListed(seizerContract);\\n }\\n if (VToken(vTokenCollateral).comptroller() != VToken(seizerContract).comptroller()) {\\n revert ComptrollerMismatch();\\n }\\n }\\n\\n if (!market.accountMembership[borrower]) {\\n revert MarketNotCollateral(vTokenCollateral, borrower);\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vTokenCollateral);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, borrower);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, liquidator);\\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external override {\\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 _checkRedeemAllowed(vToken, src, transferTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, src);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, dst);\\n }\\n }\\n\\n /*** Pool-level operations ***/\\n\\n /**\\n * @notice Seizes all the remaining collateral, makes msg.sender repay the existing\\n * borrows, and treats the rest of the debt as bad debt (for each market).\\n * The sender has to repay a certain percentage of the debt, computed as\\n * collateral / (borrows * liquidationIncentive).\\n * @param user account to heal\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for healing\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function healAccount(address user) external {\\n VToken[] memory userAssets = getAssetsIn(user);\\n uint256 userAssetsCount = userAssets.length;\\n\\n address liquidator = msg.sender;\\n {\\n ResilientOracleInterface oracle_ = oracle;\\n // We need all user's markets to be fresh for the computations to be correct\\n for (uint256 i; i < userAssetsCount; ++i) {\\n userAssets[i].accrueInterest();\\n oracle_.updatePrice(address(userAssets[i]));\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(user, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n // percentage = collateral / (borrows * liquidation incentive)\\n Exp memory collateral = Exp({ mantissa: snapshot.totalCollateral });\\n Exp memory scaledBorrows = mul_(\\n Exp({ mantissa: snapshot.borrows }),\\n Exp({ mantissa: liquidationIncentiveMantissa })\\n );\\n\\n Exp memory percentage = div_(collateral, scaledBorrows);\\n if (lessThanExp(Exp({ mantissa: MANTISSA_ONE }), percentage)) {\\n revert CollateralExceedsThreshold(scaledBorrows.mantissa, collateral.mantissa);\\n }\\n\\n for (uint256 i; i < userAssetsCount; ++i) {\\n VToken market = userAssets[i];\\n\\n (uint256 tokens, uint256 borrowBalance, ) = _safeGetAccountSnapshot(market, user);\\n uint256 repaymentAmount = mul_ScalarTruncate(percentage, borrowBalance);\\n\\n // Seize the entire collateral\\n if (tokens != 0) {\\n market.seize(liquidator, user, tokens);\\n }\\n // Repay a certain percentage of the borrow, forgive the rest\\n if (borrowBalance != 0) {\\n market.healBorrow(liquidator, user, repaymentAmount);\\n }\\n }\\n }\\n\\n /**\\n * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than\\n * a predefined threshold, and the account collateral can be seized to cover all borrows. If\\n * the collateral is higher than the threshold, use regular liquidations. If the collateral is\\n * below the threshold, and the account is insolvent, use healAccount.\\n * @param borrower the borrower address\\n * @param orders an array of liquidation orders\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation\\n * @custom:error InsufficientCollateral error is thrown when there is not enough collateral to cover the debt\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function liquidateAccount(address borrower, LiquidationOrder[] calldata orders) external {\\n // We will accrue interest and update the oracle prices later during the liquidation\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n // You should use the regular vToken.liquidateBorrow(...) call\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n uint256 collateralToSeize = mul_ScalarTruncate(\\n Exp({ mantissa: liquidationIncentiveMantissa }),\\n snapshot.borrows\\n );\\n if (collateralToSeize >= snapshot.totalCollateral) {\\n // There is not enough collateral to seize. Use healBorrow to repay some part of the borrow\\n // and record bad debt.\\n revert InsufficientCollateral(collateralToSeize, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n uint256 ordersCount = orders.length;\\n\\n _ensureMaxLoops(ordersCount / 2);\\n\\n for (uint256 i; i < ordersCount; ++i) {\\n if (!markets[address(orders[i].vTokenBorrowed)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenBorrowed));\\n }\\n if (!markets[address(orders[i].vTokenCollateral)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenCollateral));\\n }\\n\\n LiquidationOrder calldata order = orders[i];\\n order.vTokenBorrowed.forceLiquidateBorrow(\\n msg.sender,\\n borrower,\\n order.repayAmount,\\n order.vTokenCollateral,\\n true\\n );\\n }\\n\\n VToken[] memory borrowMarkets = getAssetsIn(borrower);\\n uint256 marketsCount = borrowMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower);\\n require(borrowBalance == 0, \\\"Nonzero borrow balance after liquidation\\\");\\n }\\n }\\n\\n /**\\n * @notice Sets the closeFactor to use when liquidating borrows\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @custom:event Emits NewCloseFactor on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCloseFactor(uint256 newCloseFactorMantissa) external {\\n _checkAccessAllowed(\\\"setCloseFactor(uint256)\\\");\\n require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, \\\"Close factor greater than maximum close factor\\\");\\n require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, \\\"Close factor smaller than minimum close factor\\\");\\n\\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev This function is restricted by the AccessControlManager\\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 * @custom:event Emits NewCollateralFactor when collateral factor is updated\\n * and NewLiquidationThreshold when liquidation threshold is updated\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InvalidCollateralFactor error is thrown when collateral factor is too high\\n * @custom:error InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor\\n * @custom:error PriceError is thrown when the oracle returns an invalid price for the asset\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCollateralFactor(\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external {\\n _checkAccessAllowed(\\\"setCollateralFactor(address,uint256,uint256)\\\");\\n\\n // Verify market is listed\\n Market storage market = markets[address(vToken)];\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Check collateral factor <= 0.9\\n if (newCollateralFactorMantissa > MAX_COLLATERAL_FACTOR_MANTISSA) {\\n revert InvalidCollateralFactor();\\n }\\n\\n // Ensure that liquidation threshold <= 1\\n if (newLiquidationThresholdMantissa > MANTISSA_ONE) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // Ensure that liquidation threshold >= CF\\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n }\\n\\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\\n emit NewLiquidationThreshold(vToken, oldLiquidationThresholdMantissa, newLiquidationThresholdMantissa);\\n }\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev This function is restricted by the AccessControlManager\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @custom:event Emits NewLiquidationIncentive on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external {\\n require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, \\\"liquidation incentive should be greater than 1e18\\\");\\n\\n _checkAccessAllowed(\\\"setLiquidationIncentive(uint256)\\\");\\n\\n // Save current value for use in log\\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\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\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Only callable by the PoolRegistry\\n * @param vToken The address of the market (token) to list\\n * @custom:error MarketAlreadyListed is thrown if the market is already listed in this pool\\n * @custom:access Only PoolRegistry\\n */\\n function supportMarket(VToken vToken) external {\\n _checkSenderIs(poolRegistry);\\n\\n if (markets[address(vToken)].isListed) {\\n revert MarketAlreadyListed(address(vToken));\\n }\\n\\n require(vToken.isVToken(), \\\"Comptroller: Invalid vToken\\\"); // Sanity check to make sure its really a VToken\\n\\n Market storage newMarket = markets[address(vToken)];\\n newMarket.isListed = true;\\n newMarket.collateralFactorMantissa = 0;\\n newMarket.liquidationThresholdMantissa = 0;\\n\\n _addMarket(address(vToken));\\n\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n rewardsDistributors[i].initializeMarket(address(vToken));\\n }\\n\\n emit MarketSupported(vToken);\\n }\\n\\n /**\\n * @notice Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A borrow cap of type(uint256).max corresponds to unlimited borrowing.\\n * @dev Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed\\n until the total borrows amount goes below the new borrow cap\\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 type(uint256).max corresponds to unlimited borrowing.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\\n _checkAccessAllowed(\\\"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 _ensureMaxLoops(numMarkets);\\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 * @notice Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A supply cap of type(uint256).max corresponds to unlimited supply.\\n * @dev Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed\\n until the total supplies amount goes below the new supply cap\\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 type(uint256).max corresponds to unlimited supply.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\\n _checkAccessAllowed(\\\"setMarketSupplyCaps(address[],uint256[])\\\");\\n uint256 vTokensCount = vTokens.length;\\n\\n require(vTokensCount != 0, \\\"invalid number of markets\\\");\\n require(vTokensCount == newSupplyCaps.length, \\\"invalid number of markets\\\");\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Pause/unpause specified actions\\n * @dev This function is restricted by the AccessControlManager\\n * @param marketsList Markets to pause/unpause the actions on\\n * @param actionsList List of action ids to pause/unpause\\n * @param paused The new paused state (true=paused, false=unpaused)\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setActionsPaused(VToken[] calldata marketsList, Action[] calldata actionsList, bool paused) external {\\n _checkAccessAllowed(\\\"setActionsPaused(address[],uint256[],bool)\\\");\\n\\n uint256 marketsCount = marketsList.length;\\n uint256 actionsCount = actionsList.length;\\n\\n _ensureMaxLoops(marketsCount * actionsCount);\\n\\n for (uint256 marketIdx; marketIdx < marketsCount; ++marketIdx) {\\n for (uint256 actionIdx; actionIdx < actionsCount; ++actionIdx) {\\n _setActionPaused(address(marketsList[marketIdx]), actionsList[actionIdx], paused);\\n }\\n }\\n }\\n\\n /**\\n * @notice Set the given collateral threshold for non-batch liquidations. Regular liquidations\\n * will fail if the collateral amount is less than this threshold. Liquidators should use batch\\n * operations like liquidateAccount or healAccount.\\n * @dev This function is restricted by the AccessControlManager\\n * @param newMinLiquidatableCollateral The new min liquidatable collateral (in USD).\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external {\\n _checkAccessAllowed(\\\"setMinLiquidatableCollateral(uint256)\\\");\\n\\n uint256 oldMinLiquidatableCollateral = minLiquidatableCollateral;\\n minLiquidatableCollateral = newMinLiquidatableCollateral;\\n emit NewMinLiquidatableCollateral(oldMinLiquidatableCollateral, newMinLiquidatableCollateral);\\n }\\n\\n /**\\n * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor\\n * contracts with the same rewardToken, and there could be overlaping among them considering the last reward slot (block or second)\\n * @dev Only callable by the admin\\n * @param _rewardsDistributor Address of the RewardDistributor contract to add\\n * @custom:access Only Governance\\n * @custom:event Emits NewRewardsDistributor with distributor address\\n */\\n function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner {\\n require(!rewardsDistributorExists[address(_rewardsDistributor)], \\\"already exists\\\");\\n\\n uint256 rewardsDistributorsLen = rewardsDistributors.length;\\n _ensureMaxLoops(rewardsDistributorsLen + 1);\\n\\n rewardsDistributors.push(_rewardsDistributor);\\n rewardsDistributorExists[address(_rewardsDistributor)] = true;\\n\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n _rewardsDistributor.initializeMarket(address(allMarkets[i]));\\n }\\n\\n emit NewRewardsDistributor(address(_rewardsDistributor), address(_rewardsDistributor.rewardToken()));\\n }\\n\\n /**\\n * @notice Sets a new price oracle for the Comptroller\\n * @dev Only callable by the admin\\n * @param newOracle Address of the new price oracle to set\\n * @custom:event Emits NewPriceOracle on success\\n * @custom:error ZeroAddressNotAllowed is thrown when the new oracle address is zero\\n */\\n function setPriceOracle(ResilientOracleInterface newOracle) external onlyOwner {\\n ensureNonzeroAddress(address(newOracle));\\n\\n ResilientOracleInterface oldOracle = oracle;\\n oracle = newOracle;\\n emit NewPriceOracle(oldOracle, newOracle);\\n }\\n\\n /**\\n * @notice Set the for loop iteration limit to avoid DOS\\n * @param limit Limit for the max loops can execute at a time\\n */\\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Sets the prime token contract for the comptroller\\n * @param _prime Address of the Prime contract\\n */\\n function setPrimeToken(IPrime _prime) external onlyOwner {\\n ensureNonzeroAddress(address(_prime));\\n\\n emit NewPrimeToken(prime, _prime);\\n prime = _prime;\\n }\\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 * @param vTokenBorrowed Borrowed vToken\\n * @param enable Whether to enable forced liquidations\\n */\\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\\n _checkAccessAllowed(\\\"setForcedLiquidation(address,bool)\\\");\\n ensureNonzeroAddress(vTokenBorrowed);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(vTokenBorrowed);\\n }\\n\\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to liquidation threshold requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of liquidation threshold requirements,\\n * @return shortfall Account shortfall below liquidation threshold requirements\\n */\\n function getAccountLiquidity(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getLiquidationThreshold);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to collateral requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of collateral requirements,\\n * @return shortfall Account shortfall below collateral requirements\\n */\\n function getBorrowingPower(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getCollateralFactor);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Hypothetical account liquidity in excess of collateral requirements,\\n * @return shortfall 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 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n account,\\n VToken(vTokenModify),\\n redeemTokens,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\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 markets The list of market addresses\\n */\\n function getAllMarkets() external view override returns (VToken[] memory) {\\n return allMarkets;\\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 /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns whether the given account is entered in a given market\\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 market specified, 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 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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return tokensToSeize Number of vTokenCollateral tokens to be seized in a liquidation\\n * @custom:error PriceError if the oracle returns an invalid price\\n */\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view override returns (uint256 error, uint256 tokensToSeize) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint256 priceBorrowedMantissa = _safeGetUnderlyingPrice(VToken(vTokenBorrowed));\\n uint256 priceCollateralMantissa = _safeGetUnderlyingPrice(VToken(vTokenCollateral));\\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 uint256 exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint256 seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n\\n numerator = mul_(Exp({ mantissa: liquidationIncentiveMantissa }), Exp({ mantissa: priceBorrowedMantissa }));\\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\\n ratio = div_(numerator, denominator);\\n\\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\\n\\n return (NO_ERROR, seizeTokens);\\n }\\n\\n /**\\n * @notice Returns reward speed given a vToken\\n * @param vToken The vToken to get the reward speeds for\\n * @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors\\n */\\n function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {\\n uint256 rewardsDistributorsLength = rewardsDistributors.length;\\n rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);\\n for (uint256 i; i < rewardsDistributorsLength; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n address rewardToken = address(rewardsDistributor.rewardToken());\\n rewardSpeeds[i] = RewardSpeeds({\\n rewardToken: rewardToken,\\n supplySpeed: rewardsDistributor.rewardTokenSupplySpeeds(vToken),\\n borrowSpeed: rewardsDistributor.rewardTokenBorrowSpeeds(vToken)\\n });\\n }\\n return rewardSpeeds;\\n }\\n\\n /**\\n * @notice Return all reward distributors for this pool\\n * @return Array of RewardDistributor addresses\\n */\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory) {\\n return rewardsDistributors;\\n }\\n\\n /**\\n * @notice A marker method that returns true for a valid Comptroller contract\\n * @return Always true\\n */\\n function isComptroller() external pure override returns (bool) {\\n return true;\\n }\\n\\n /**\\n * @notice Update the prices of all the tokens associated with the provided account\\n * @param account Address of the account to get associated tokens with\\n */\\n function updatePrices(address account) public {\\n VToken[] memory vTokens = getAssetsIn(account);\\n uint256 vTokensCount = vTokens.length;\\n\\n ResilientOracleInterface oracle_ = oracle;\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n oracle_.updatePrice(address(vTokens[i]));\\n }\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param market vToken address\\n * @param action Action to check\\n * @return paused True if the action is paused otherwise false\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][action];\\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 list with the assets the account has entered\\n */\\n function getAssetsIn(address account) public 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 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 */\\n function _addToMarket(VToken vToken, address borrower) internal {\\n _checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = markets[address(vToken)];\\n\\n if (!marketToJoin.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return;\\n }\\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\\n /**\\n * @notice Internal function to validate that a market hasn't already been added\\n * and if it hasn't adds it\\n * @param vToken The market to support\\n */\\n function _addMarket(address vToken) internal {\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n if (allMarkets[i] == VToken(vToken)) {\\n revert MarketAlreadyListed(vToken);\\n }\\n }\\n allMarkets.push(VToken(vToken));\\n marketsCount = allMarkets.length;\\n _ensureMaxLoops(marketsCount);\\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 _setActionPaused(address market, Action action, bool paused) internal {\\n require(markets[market].isListed, \\\"cannot pause a market that is not listed\\\");\\n _actionPaused[market][action] = paused;\\n emit ActionPausedMarket(VToken(market), action, paused);\\n }\\n\\n /**\\n * @dev Internal function to check that vTokens can be safely redeemed for the underlying asset.\\n * @param vToken Address of the vTokens to redeem\\n * @param redeemer Account redeeming the tokens\\n * @param redeemTokens The number of tokens to redeem\\n */\\n function _checkRedeemAllowed(address vToken, address redeemer, uint256 redeemTokens) internal {\\n Market storage market = markets[vToken];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!market.accountMembership[redeemer]) {\\n return;\\n }\\n\\n // Update the prices of tokens\\n updatePrices(redeemer);\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n _getCollateralFactor\\n );\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n }\\n\\n /**\\n * @notice Get the total collateral, weighted collateral, borrow balance, liquidity, shortfall\\n * @param account The account to get the snapshot for\\n * @param weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n * liquidation threshold. Accepts the address of the vToken and returns the weight as Exp.\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getCurrentLiquiditySnapshot(\\n address account,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n return _getHypotheticalLiquiditySnapshot(account, VToken(address(0)), 0, 0, weight);\\n }\\n\\n /**\\n * @notice Determine what the supply/borrow balances 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 weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n liquidation threshold. Accepts the address of the VToken and returns the weight\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getHypotheticalLiquiditySnapshot(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n // For each asset the account is in\\n VToken[] memory assets = getAssetsIn(account);\\n uint256 assetsCount = assets.length;\\n\\n for (uint256 i; i < assetsCount; ++i) {\\n VToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the vToken\\n (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) = _safeGetAccountSnapshot(\\n asset,\\n account\\n );\\n\\n // Get the normalized price of the asset\\n Exp memory oraclePrice = Exp({ mantissa: _safeGetUnderlyingPrice(asset) });\\n\\n // Pre-compute conversion factors from vTokens -> usd\\n Exp memory vTokenPrice = mul_(Exp({ mantissa: exchangeRateMantissa }), oraclePrice);\\n Exp memory weightedVTokenPrice = mul_(weight(asset), vTokenPrice);\\n\\n // weightedCollateral += weightedVTokenPrice * vTokenBalance\\n snapshot.weightedCollateral = mul_ScalarTruncateAddUInt(\\n weightedVTokenPrice,\\n vTokenBalance,\\n snapshot.weightedCollateral\\n );\\n\\n // totalCollateral += vTokenPrice * vTokenBalance\\n snapshot.totalCollateral = mul_ScalarTruncateAddUInt(vTokenPrice, vTokenBalance, snapshot.totalCollateral);\\n\\n // borrows += oraclePrice * borrowBalance\\n snapshot.borrows = mul_ScalarTruncateAddUInt(oraclePrice, borrowBalance, snapshot.borrows);\\n\\n // Calculate effects of interacting with vTokenModify\\n if (asset == vTokenModify) {\\n // redeem effect\\n // effects += tokensToDenom * redeemTokens\\n snapshot.effects = mul_ScalarTruncateAddUInt(weightedVTokenPrice, redeemTokens, snapshot.effects);\\n\\n // borrow effect\\n // effects += oraclePrice * borrowAmount\\n snapshot.effects = mul_ScalarTruncateAddUInt(oraclePrice, borrowAmount, snapshot.effects);\\n }\\n }\\n\\n uint256 borrowPlusEffects = snapshot.borrows + snapshot.effects;\\n // These are safe, as the underflow condition is checked first\\n unchecked {\\n if (snapshot.weightedCollateral > borrowPlusEffects) {\\n snapshot.liquidity = snapshot.weightedCollateral - borrowPlusEffects;\\n snapshot.shortfall = 0;\\n } else {\\n snapshot.liquidity = 0;\\n snapshot.shortfall = borrowPlusEffects - snapshot.weightedCollateral;\\n }\\n }\\n\\n return snapshot;\\n }\\n\\n /**\\n * @dev Retrieves price from oracle for an asset and checks it is nonzero\\n * @param asset Address for asset to query price\\n * @return Underlying price\\n */\\n function _safeGetUnderlyingPrice(VToken asset) internal view returns (uint256) {\\n uint256 oraclePriceMantissa = oracle.getUnderlyingPrice(address(asset));\\n if (oraclePriceMantissa == 0) {\\n revert PriceError(address(asset));\\n }\\n return oraclePriceMantissa;\\n }\\n\\n /**\\n * @dev Return collateral factor for a market\\n * @param asset Address for asset\\n * @return Collateral factor as exponential\\n */\\n function _getCollateralFactor(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].collateralFactorMantissa });\\n }\\n\\n /**\\n * @dev Retrieves liquidation threshold for a market as an exponential\\n * @param asset Address for asset to liquidation threshold\\n * @return Liquidation threshold as exponential\\n */\\n function _getLiquidationThreshold(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].liquidationThresholdMantissa });\\n }\\n\\n /**\\n * @dev Returns supply and borrow balances of user in vToken, reverts on failure\\n * @param vToken Market to query\\n * @param user Account address\\n * @return vTokenBalance Balance of vTokens, the same as vToken.balanceOf(user)\\n * @return borrowBalance Borrowed amount, including the interest\\n * @return exchangeRateMantissa Stored exchange rate\\n */\\n function _safeGetAccountSnapshot(\\n VToken vToken,\\n address user\\n ) internal view returns (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) {\\n uint256 err;\\n (err, vTokenBalance, borrowBalance, exchangeRateMantissa) = vToken.getAccountSnapshot(user);\\n if (err != 0) {\\n revert SnapshotError(address(vToken), user);\\n }\\n return (vTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /// @notice Reverts if the call is not from expectedSender\\n /// @param expectedSender Expected transaction sender\\n function _checkSenderIs(address expectedSender) internal view {\\n if (msg.sender != expectedSender) {\\n revert UnexpectedSender(expectedSender, msg.sender);\\n }\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n /// @param market Market to check\\n /// @param action Action to check\\n function _checkActionPauseState(address market, Action action) private view {\\n if (actionPaused(market, action)) {\\n revert ActionPaused(market, action);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7c6e1c6264e4681f82a9ac1bcd9155197a930033291ee5561ad97a56006f5e9c\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.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\\n/**\\n * @title ComptrollerInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract.\\n */\\ninterface ComptrollerInterface {\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\\n\\n function exitMarket(address vToken) external returns (uint256);\\n\\n /*** Policy Hooks ***/\\n\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external;\\n\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external;\\n\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external;\\n\\n function preRepayHook(address vToken, address borrower) external;\\n\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external;\\n\\n function preSeizeHook(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower\\n ) external;\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\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 seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external;\\n\\n function isComptroller() external view returns (bool);\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 repayAmount\\n ) external view returns (uint256, uint256);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n}\\n\\n/**\\n * @title ComptrollerViewInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract, including only some util view functions.\\n */\\ninterface ComptrollerViewInterface {\\n function markets(address) external view returns (bool, uint256);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function closeFactorMantissa() external view returns (uint256);\\n\\n function liquidationIncentiveMantissa() external view returns (uint256);\\n\\n function minLiquidatableCollateral() external view returns (uint256);\\n\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function borrowCaps(address) external view returns (uint256);\\n\\n function supplyCaps(address) external view returns (uint256);\\n\\n function approvedDelegates(address user, address delegate) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xcbf7f9977472650c61345b7cbde23e81f626e1f8863bab4c6ce3dacfc7604919\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { IPrime } from \\\"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\\\";\\nimport { Action } from \\\"./ComptrollerInterface.sol\\\";\\n\\n/**\\n * @title ComptrollerStorage\\n * @author Venus\\n * @notice Storage layout for the `Comptroller` contract.\\n */\\ncontract ComptrollerStorage {\\n struct LiquidationOrder {\\n VToken vTokenCollateral;\\n VToken vTokenBorrowed;\\n uint256 repayAmount;\\n }\\n\\n struct AccountLiquiditySnapshot {\\n uint256 totalCollateral;\\n uint256 weightedCollateral;\\n uint256 borrows;\\n uint256 effects;\\n uint256 liquidity;\\n uint256 shortfall;\\n }\\n\\n struct RewardSpeeds {\\n address rewardToken;\\n uint256 supplySpeed;\\n uint256 borrowSpeed;\\n }\\n\\n struct Market {\\n // Whether or not this market is listed\\n bool isListed;\\n // 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 uint256 collateralFactorMantissa;\\n // 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 uint256 liquidationThresholdMantissa;\\n // Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n }\\n\\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 Per-account mapping of \\\"assets you are in\\\"\\n */\\n mapping(address => VToken[]) public accountAssets;\\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 /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\\n mapping(address => uint256) public borrowCaps;\\n\\n /// @notice Minimal collateral required for regular (non-batch) liquidations\\n uint256 public minLiquidatableCollateral;\\n\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\\n mapping(address => uint256) public supplyCaps;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(Action => bool)) internal _actionPaused;\\n\\n // List of Reward Distributors added\\n RewardsDistributor[] internal rewardsDistributors;\\n\\n // Used to check if rewards distributor is added\\n mapping(address => bool) internal rewardsDistributorExists;\\n\\n /// @notice Flag indicating whether forced liquidation enabled for a market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n\\n uint256 internal constant NO_ERROR = 0;\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant MIN_CLOSE_FACTOR_MANTISSA = 0.05e18; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant MAX_CLOSE_FACTOR_MANTISSA = 0.9e18; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.95e18; // 0.95\\n\\n /// Prime token address\\n IPrime public prime;\\n\\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 /**\\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[47] private __gap;\\n}\\n\",\"keccak256\":\"0x4df44cb65ac152bac2be4b4545430e703005a74a55b72e144100b16421bd8bfd\",\"license\":\"BSD-3-Clause\"},\"contracts/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title TokenErrorReporter\\n * @author Venus\\n * @notice Errors that can be thrown by the `VToken` contract.\\n */\\ncontract TokenErrorReporter {\\n uint256 public constant NO_ERROR = 0; // support legacy return codes\\n\\n error TransferNotAllowed();\\n\\n error MintFreshnessCheck();\\n\\n error RedeemFreshnessCheck();\\n error RedeemTransferOutNotPossible();\\n\\n error BorrowFreshnessCheck();\\n error BorrowCashNotAvailable();\\n error DelegateNotApproved();\\n\\n error RepayBorrowFreshnessCheck();\\n\\n error HealBorrowUnauthorized();\\n error ForceLiquidateBorrowUnauthorized();\\n\\n error LiquidateFreshnessCheck();\\n error LiquidateCollateralFreshnessCheck();\\n error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\\n error LiquidateLiquidatorIsBorrower();\\n error LiquidateCloseAmountIsZero();\\n error LiquidateCloseAmountIsUintMax();\\n\\n error LiquidateSeizeLiquidatorIsBorrower();\\n\\n error ProtocolSeizeShareTooBig();\\n\\n error SetReserveFactorFreshCheck();\\n error SetReserveFactorBoundsCheck();\\n\\n error AddReservesFactorFreshCheck(uint256 actualAddAmount);\\n\\n error ReduceReservesFreshCheck();\\n error ReduceReservesCashNotAvailable();\\n error ReduceReservesCashValidation();\\n\\n error SetInterestRateModelFreshCheck();\\n}\\n\",\"keccak256\":\"0x7a7ced1caaac2d9242659ebd50b99f308c725ce958ac9e11f7ada404b1d97a7b\",\"license\":\"BSD-3-Clause\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from \\\"./lib/constants.sol\\\";\\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 struct Exp {\\n uint256 mantissa;\\n }\\n\\n struct Double {\\n uint256 mantissa;\\n }\\n\\n uint256 internal constant EXP_SCALE = EXP_SCALE_;\\n uint256 internal constant DOUBLE_SCALE = 1e36;\\n uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;\\n uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint256) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / EXP_SCALE;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\\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 // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint256 scalar, uint256 addend) internal pure returns (uint256) {\\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 function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\\n require(n <= type(uint224).max, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\\n require(n <= type(uint32).max, 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_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a + b;\\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_(uint256 a, uint256 b) internal pure returns (uint256) {\\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) / EXP_SCALE });\\n }\\n\\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / EXP_SCALE;\\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) / DOUBLE_SCALE });\\n }\\n\\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / DOUBLE_SCALE;\\n }\\n\\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a * b;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return div_(mul_(a, EXP_SCALE), 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, DOUBLE_SCALE), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return div_(mul_(a, DOUBLE_SCALE), b.mantissa);\\n }\\n\\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a / b;\\n }\\n\\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });\\n }\\n}\\n\",\"keccak256\":\"0x8afbe8a24fe3539c124e718681ed3dcebd24c40dd53095786c0155998213b9b0\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModel.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\nabstract contract InterestRateModel {\\n /**\\n * @notice Calculates the current borrow interest rate per slot (block or second)\\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 amount of reserves the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per slot (block or second)\\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 amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\\n * @return Always true\\n */\\n function isInterestRateModel() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xc4fda1ab75ebe4b187b707c4f10c58780f343cf343c537f641dc75d3cd28ab51\",\"license\":\"BSD-3-Clause\"},\"contracts/Lens/PoolLens.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { IERC20Metadata } from \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Action, ComptrollerInterface, ComptrollerViewInterface } from \\\"../ComptrollerInterface.sol\\\";\\nimport { PoolRegistryInterface } from \\\"../Pool/PoolRegistryInterface.sol\\\";\\nimport { PoolRegistry } from \\\"../Pool/PoolRegistry.sol\\\";\\nimport { RewardsDistributor } from \\\"../Rewards/RewardsDistributor.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\n\\n/**\\n * @title PoolLens\\n * @author Venus\\n * @notice The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information\\n * for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be\\n * looked up for specific pools and markets:\\n- the vToken balance of a given user;\\n- the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address;\\n- the vToken address in a pool for a given asset;\\n- a list of all pools that support an asset;\\n- the underlying asset price of a vToken;\\n- the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\\n */\\ncontract PoolLens is ExponentialNoError, TimeManagerV8 {\\n /**\\n * @dev Struct for PoolDetails.\\n */\\n struct PoolData {\\n string name;\\n address creator;\\n address comptroller;\\n uint256 blockPosted;\\n uint256 timestampPosted;\\n string category;\\n string logoURL;\\n string description;\\n address priceOracle;\\n uint256 closeFactor;\\n uint256 liquidationIncentive;\\n uint256 minLiquidatableCollateral;\\n VTokenMetadata[] vTokens;\\n }\\n\\n /**\\n * @dev Struct for VToken.\\n */\\n struct VTokenMetadata {\\n address vToken;\\n uint256 exchangeRateCurrent;\\n uint256 supplyRatePerBlockOrTimestamp;\\n uint256 borrowRatePerBlockOrTimestamp;\\n uint256 reserveFactorMantissa;\\n uint256 supplyCaps;\\n uint256 borrowCaps;\\n uint256 totalBorrows;\\n uint256 totalReserves;\\n uint256 totalSupply;\\n uint256 totalCash;\\n bool isListed;\\n uint256 collateralFactorMantissa;\\n address underlyingAssetAddress;\\n uint256 vTokenDecimals;\\n uint256 underlyingDecimals;\\n uint256 pausedActions;\\n }\\n\\n /**\\n * @dev Struct for VTokenBalance.\\n */\\n struct VTokenBalances {\\n address vToken;\\n uint256 balanceOf;\\n uint256 borrowBalanceCurrent;\\n uint256 balanceOfUnderlying;\\n uint256 tokenBalance;\\n uint256 tokenAllowance;\\n }\\n\\n /**\\n * @dev Struct for underlyingPrice of VToken.\\n */\\n struct VTokenUnderlyingPrice {\\n address vToken;\\n uint256 underlyingPrice;\\n }\\n\\n /**\\n * @dev Struct with pending reward info for a market.\\n */\\n struct PendingReward {\\n address vTokenAddress;\\n uint256 amount;\\n }\\n\\n /**\\n * @dev Struct with reward distribution totals for a single reward token and distributor.\\n */\\n struct RewardSummary {\\n address distributorAddress;\\n address rewardTokenAddress;\\n uint256 totalRewards;\\n PendingReward[] pendingRewards;\\n }\\n\\n /**\\n * @dev Struct used in RewardDistributor to save last updated market state.\\n */\\n struct RewardTokenState {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number or timestamp the index was last updated at\\n uint256 blockOrTimestamp;\\n // The block number or timestamp at which to stop rewards\\n uint256 lastRewardingBlockOrTimestamp;\\n }\\n\\n /**\\n * @dev Struct with bad debt of a market denominated\\n */\\n struct BadDebt {\\n address vTokenAddress;\\n uint256 badDebtUsd;\\n }\\n\\n /**\\n * @dev Struct with bad debt total denominated in usd for a pool and an array of BadDebt structs for each market\\n */\\n struct BadDebtSummary {\\n address comptroller;\\n uint256 totalBadDebtUsd;\\n BadDebt[] badDebts;\\n }\\n\\n /**\\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) {}\\n\\n /**\\n * @notice Queries the user's supply/borrow balances in vTokens\\n * @param vTokens The list of vToken addresses\\n * @param account The user Account\\n * @return A list of structs containing balances data\\n */\\n function vTokenBalancesAll(VToken[] calldata vTokens, address account) external returns (VTokenBalances[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenBalances[] memory res = new VTokenBalances[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenBalances(vTokens[i], account);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Queries all pools with addtional details for each of them\\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @return Arrays of all Venus pools' data\\n */\\n function getAllPools(address poolRegistryAddress) external view returns (PoolData[] memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n PoolRegistry.VenusPool[] memory venusPools = poolRegistryInterface.getAllPools();\\n uint256 poolLength = venusPools.length;\\n\\n PoolData[] memory poolDataItems = new PoolData[](poolLength);\\n\\n for (uint256 i; i < poolLength; ++i) {\\n PoolRegistry.VenusPool memory venusPool = venusPools[i];\\n PoolData memory poolData = getPoolDataFromVenusPool(poolRegistryAddress, venusPool);\\n poolDataItems[i] = poolData;\\n }\\n\\n return poolDataItems;\\n }\\n\\n /**\\n * @notice Queries the details of a pool identified by Comptroller address\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param comptroller The Comptroller implementation address\\n * @return PoolData structure containing the details of the pool\\n */\\n function getPoolByComptroller(\\n address poolRegistryAddress,\\n address comptroller\\n ) external view returns (PoolData memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return getPoolDataFromVenusPool(poolRegistryAddress, poolRegistryInterface.getPoolByComptroller(comptroller));\\n }\\n\\n /**\\n * @notice Returns vToken holding the specified underlying asset in the specified pool\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param comptroller The pool comptroller\\n * @param asset The underlyingAsset of VToken\\n * @return Address of the vToken\\n */\\n function getVTokenForAsset(\\n address poolRegistryAddress,\\n address comptroller,\\n address asset\\n ) external view returns (address) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return poolRegistryInterface.getVTokenForAsset(comptroller, asset);\\n }\\n\\n /**\\n * @notice Returns all pools that support the specified underlying asset\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param asset The underlying asset of vToken\\n * @return A list of Comptroller contracts\\n */\\n function getPoolsSupportedByAsset(\\n address poolRegistryAddress,\\n address asset\\n ) external view returns (address[] memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return poolRegistryInterface.getPoolsSupportedByAsset(asset);\\n }\\n\\n /**\\n * @notice Returns the price data for the underlying assets of the specified vTokens\\n * @param vTokens The list of vToken addresses\\n * @return An array containing the price data for each asset\\n */\\n function vTokenUnderlyingPriceAll(\\n VToken[] calldata vTokens\\n ) external view returns (VTokenUnderlyingPrice[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenUnderlyingPrice[] memory res = new VTokenUnderlyingPrice[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenUnderlyingPrice(vTokens[i]);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Returns the pending rewards for a user for a given pool.\\n * @param account The user account.\\n * @param comptrollerAddress address\\n * @return Pending rewards array\\n */\\n function getPendingRewards(\\n address account,\\n address comptrollerAddress\\n ) external view returns (RewardSummary[] memory) {\\n VToken[] memory markets = ComptrollerInterface(comptrollerAddress).getAllMarkets();\\n RewardsDistributor[] memory rewardsDistributors = ComptrollerViewInterface(comptrollerAddress)\\n .getRewardDistributors();\\n RewardSummary[] memory rewardSummary = new RewardSummary[](rewardsDistributors.length);\\n for (uint256 i; i < rewardsDistributors.length; ++i) {\\n RewardSummary memory reward;\\n reward.distributorAddress = address(rewardsDistributors[i]);\\n reward.rewardTokenAddress = address(rewardsDistributors[i].rewardToken());\\n reward.totalRewards = rewardsDistributors[i].rewardTokenAccrued(account);\\n reward.pendingRewards = _calculateNotDistributedAwards(account, markets, rewardsDistributors[i]);\\n rewardSummary[i] = reward;\\n }\\n return rewardSummary;\\n }\\n\\n /**\\n * @notice Returns a summary of a pool's bad debt broken down by market\\n *\\n * @param comptrollerAddress Address of the comptroller\\n *\\n * @return badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and\\n * a break down of bad debt by market\\n */\\n function getPoolBadDebt(address comptrollerAddress) external view returns (BadDebtSummary memory) {\\n uint256 totalBadDebtUsd;\\n\\n // Get every market in the pool\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\\n VToken[] memory markets = comptroller.getAllMarkets();\\n ResilientOracleInterface priceOracle = comptroller.oracle();\\n\\n BadDebt[] memory badDebts = new BadDebt[](markets.length);\\n\\n BadDebtSummary memory badDebtSummary;\\n badDebtSummary.comptroller = comptrollerAddress;\\n badDebtSummary.badDebts = badDebts;\\n\\n // // Calculate the bad debt is USD per market\\n for (uint256 i; i < markets.length; ++i) {\\n BadDebt memory badDebt;\\n badDebt.vTokenAddress = address(markets[i]);\\n badDebt.badDebtUsd =\\n (VToken(address(markets[i])).badDebt() * priceOracle.getUnderlyingPrice(address(markets[i]))) /\\n EXP_SCALE;\\n badDebtSummary.badDebts[i] = badDebt;\\n totalBadDebtUsd = totalBadDebtUsd + badDebt.badDebtUsd;\\n }\\n\\n badDebtSummary.totalBadDebtUsd = totalBadDebtUsd;\\n\\n return badDebtSummary;\\n }\\n\\n /**\\n * @notice Queries the user's supply/borrow balances in the specified vToken\\n * @param vToken vToken address\\n * @param account The user Account\\n * @return A struct containing the balances data\\n */\\n function vTokenBalances(VToken vToken, address account) public returns (VTokenBalances memory) {\\n uint256 balanceOf = vToken.balanceOf(account);\\n uint256 borrowBalanceCurrent = vToken.borrowBalanceCurrent(account);\\n uint256 balanceOfUnderlying = vToken.balanceOfUnderlying(account);\\n uint256 tokenBalance;\\n uint256 tokenAllowance;\\n\\n IERC20 underlying = IERC20(vToken.underlying());\\n tokenBalance = underlying.balanceOf(account);\\n tokenAllowance = underlying.allowance(account, address(vToken));\\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 Queries additional information for the pool\\n * @param poolRegistryAddress Address of the PoolRegistry\\n * @param venusPool The VenusPool Object from PoolRegistry\\n * @return Enriched PoolData\\n */\\n function getPoolDataFromVenusPool(\\n address poolRegistryAddress,\\n PoolRegistry.VenusPool memory venusPool\\n ) public view returns (PoolData memory) {\\n // Get tokens in the Pool\\n ComptrollerInterface comptrollerInstance = ComptrollerInterface(venusPool.comptroller);\\n\\n VToken[] memory vTokens = comptrollerInstance.getAllMarkets();\\n\\n VTokenMetadata[] memory vTokenMetadataItems = vTokenMetadataAll(vTokens);\\n\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n\\n PoolRegistry.VenusPoolMetaData memory venusPoolMetaData = poolRegistryInterface.getVenusPoolMetadata(\\n venusPool.comptroller\\n );\\n\\n ComptrollerViewInterface comptrollerViewInstance = ComptrollerViewInterface(venusPool.comptroller);\\n\\n PoolData memory poolData = PoolData({\\n name: venusPool.name,\\n creator: venusPool.creator,\\n comptroller: venusPool.comptroller,\\n blockPosted: venusPool.blockPosted,\\n timestampPosted: venusPool.timestampPosted,\\n category: venusPoolMetaData.category,\\n logoURL: venusPoolMetaData.logoURL,\\n description: venusPoolMetaData.description,\\n vTokens: vTokenMetadataItems,\\n priceOracle: address(comptrollerViewInstance.oracle()),\\n closeFactor: comptrollerViewInstance.closeFactorMantissa(),\\n liquidationIncentive: comptrollerViewInstance.liquidationIncentiveMantissa(),\\n minLiquidatableCollateral: comptrollerViewInstance.minLiquidatableCollateral()\\n });\\n\\n return poolData;\\n }\\n\\n /**\\n * @notice Returns the metadata of VToken\\n * @param vToken The address of vToken\\n * @return VTokenMetadata struct\\n */\\n function vTokenMetadata(VToken vToken) public view returns (VTokenMetadata memory) {\\n uint256 exchangeRateCurrent = vToken.exchangeRateStored();\\n address comptrollerAddress = address(vToken.comptroller());\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\\n (bool isListed, uint256 collateralFactorMantissa) = comptroller.markets(address(vToken));\\n\\n address underlyingAssetAddress = vToken.underlying();\\n uint256 underlyingDecimals = IERC20Metadata(underlyingAssetAddress).decimals();\\n\\n uint256 pausedActions;\\n for (uint8 i; i <= uint8(type(Action).max); ++i) {\\n uint256 paused = ComptrollerInterface(comptrollerAddress).actionPaused(address(vToken), Action(i)) ? 1 : 0;\\n pausedActions |= paused << i;\\n }\\n\\n uint256 supplyRatePerBlock;\\n\\n if (vToken.totalSupply() > 0) {\\n supplyRatePerBlock = vToken.supplyRatePerBlock();\\n }\\n\\n return\\n VTokenMetadata({\\n vToken: address(vToken),\\n exchangeRateCurrent: exchangeRateCurrent,\\n supplyRatePerBlockOrTimestamp: supplyRatePerBlock,\\n borrowRatePerBlockOrTimestamp: vToken.borrowRatePerBlock(),\\n reserveFactorMantissa: vToken.reserveFactorMantissa(),\\n supplyCaps: comptroller.supplyCaps(address(vToken)),\\n borrowCaps: comptroller.borrowCaps(address(vToken)),\\n totalBorrows: vToken.totalBorrows(),\\n totalReserves: vToken.totalReserves(),\\n totalSupply: vToken.totalSupply(),\\n totalCash: vToken.getCash(),\\n isListed: isListed,\\n collateralFactorMantissa: collateralFactorMantissa,\\n underlyingAssetAddress: underlyingAssetAddress,\\n vTokenDecimals: vToken.decimals(),\\n underlyingDecimals: underlyingDecimals,\\n pausedActions: pausedActions\\n });\\n }\\n\\n /**\\n * @notice Returns the metadata of all VTokens\\n * @param vTokens The list of vToken addresses\\n * @return An array of VTokenMetadata structs\\n */\\n function vTokenMetadataAll(VToken[] memory vTokens) public view returns (VTokenMetadata[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenMetadata[] memory res = new VTokenMetadata[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenMetadata(vTokens[i]);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Returns the price data for the underlying asset of the specified vToken\\n * @param vToken vToken address\\n * @return The price data for each asset\\n */\\n function vTokenUnderlyingPrice(VToken vToken) public view returns (VTokenUnderlyingPrice memory) {\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(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 function _calculateNotDistributedAwards(\\n address account,\\n VToken[] memory markets,\\n RewardsDistributor rewardsDistributor\\n ) internal view returns (PendingReward[] memory) {\\n PendingReward[] memory pendingRewards = new PendingReward[](markets.length);\\n\\n for (uint256 i; i < markets.length; ++i) {\\n // Market borrow and supply state we will modify update in-memory, in order to not modify storage\\n RewardTokenState memory borrowState;\\n RewardTokenState memory supplyState;\\n\\n if (isTimeBased) {\\n (\\n borrowState.index,\\n borrowState.blockOrTimestamp,\\n borrowState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenBorrowStateTimeBased(address(markets[i]));\\n (\\n supplyState.index,\\n supplyState.blockOrTimestamp,\\n supplyState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenSupplyStateTimeBased(address(markets[i]));\\n } else {\\n (\\n borrowState.index,\\n borrowState.blockOrTimestamp,\\n borrowState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenBorrowState(address(markets[i]));\\n (\\n supplyState.index,\\n supplyState.blockOrTimestamp,\\n supplyState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenSupplyState(address(markets[i]));\\n }\\n\\n Exp memory marketBorrowIndex = Exp({ mantissa: markets[i].borrowIndex() });\\n\\n // Update market supply and borrow index in-memory\\n updateMarketBorrowIndex(address(markets[i]), rewardsDistributor, borrowState, marketBorrowIndex);\\n updateMarketSupplyIndex(address(markets[i]), rewardsDistributor, supplyState);\\n\\n // Calculate pending rewards\\n uint256 borrowReward = calculateBorrowerReward(\\n address(markets[i]),\\n rewardsDistributor,\\n account,\\n borrowState,\\n marketBorrowIndex\\n );\\n uint256 supplyReward = calculateSupplierReward(\\n address(markets[i]),\\n rewardsDistributor,\\n account,\\n supplyState\\n );\\n\\n PendingReward memory pendingReward;\\n pendingReward.vTokenAddress = address(markets[i]);\\n pendingReward.amount = borrowReward + supplyReward;\\n pendingRewards[i] = pendingReward;\\n }\\n return pendingRewards;\\n }\\n\\n function updateMarketBorrowIndex(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n RewardTokenState memory borrowState,\\n Exp memory marketBorrowIndex\\n ) internal view {\\n uint256 borrowSpeed = rewardsDistributor.rewardTokenBorrowSpeeds(vToken);\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (\\n borrowState.lastRewardingBlockOrTimestamp > 0 &&\\n blockNumberOrTimestamp > borrowState.lastRewardingBlockOrTimestamp\\n ) {\\n blockNumberOrTimestamp = borrowState.lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, borrowState.blockOrTimestamp);\\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\\n // Remove the total earned interest rate since the opening of the market from total borrows\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, borrowSpeed);\\n Double memory ratio = borrowAmount > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\\n } else if (deltaBlocksOrTimestamp > 0) {\\n borrowState.blockOrTimestamp = blockNumberOrTimestamp;\\n }\\n }\\n\\n function updateMarketSupplyIndex(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n RewardTokenState memory supplyState\\n ) internal view {\\n uint256 supplySpeed = rewardsDistributor.rewardTokenSupplySpeeds(vToken);\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (\\n supplyState.lastRewardingBlockOrTimestamp > 0 &&\\n blockNumberOrTimestamp > supplyState.lastRewardingBlockOrTimestamp\\n ) {\\n blockNumberOrTimestamp = supplyState.lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, supplyState.blockOrTimestamp);\\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, supplySpeed);\\n Double memory ratio = supplyTokens > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\\n } else if (deltaBlocksOrTimestamp > 0) {\\n supplyState.blockOrTimestamp = blockNumberOrTimestamp;\\n }\\n }\\n\\n function calculateBorrowerReward(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n address borrower,\\n RewardTokenState memory borrowState,\\n Exp memory marketBorrowIndex\\n ) internal view returns (uint256) {\\n Double memory borrowIndex = Double({ mantissa: borrowState.index });\\n Double memory borrowerIndex = Double({\\n mantissa: rewardsDistributor.rewardTokenBorrowerIndex(vToken, borrower)\\n });\\n if (borrowerIndex.mantissa == 0 && borrowIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set\\n borrowerIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\\n }\\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n return borrowerDelta;\\n }\\n\\n function calculateSupplierReward(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n address supplier,\\n RewardTokenState memory supplyState\\n ) internal view returns (uint256) {\\n Double memory supplyIndex = Double({ mantissa: supplyState.index });\\n Double memory supplierIndex = Double({\\n mantissa: rewardsDistributor.rewardTokenSupplierIndex(vToken, supplier)\\n });\\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\\n // Covers the case where users supplied tokens before the market's supply state index was set\\n supplierIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\\n }\\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n return supplierDelta;\\n }\\n}\\n\",\"keccak256\":\"0x2c696c531d8aeb2c58dbf3631f01602937621ac15c59080affe5b0808ba5f421\",\"license\":\"BSD-3-Clause\"},\"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\",\"keccak256\":\"0x4c25e30635485d162177effa384eee51768b0141a567a0da16ff6ad673274166\",\"license\":\"BSD-3-Clause\"},\"contracts/Pool/PoolRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\nimport { PoolRegistryInterface } from \\\"./PoolRegistryInterface.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"../lib/validators.sol\\\";\\n\\n/**\\n * @title PoolRegistry\\n * @author Venus\\n * @notice The Isolated Pools architecture centers around the `PoolRegistry` contract. The `PoolRegistry` maintains a directory of isolated lending\\n * pools and can perform actions like creating and registering new pools, adding new markets to existing pools, setting and updating the pool's required\\n * metadata, and providing the getter methods to get information on the pools.\\n *\\n * Isolated lending has three main components: PoolRegistry, pools, and markets. The PoolRegistry is responsible for managing pools.\\n * It can create new pools, update pool metadata and manage markets within pools. PoolRegistry contains getter methods to get the details of\\n * any existing pool like `getVTokenForAsset` and `getPoolsSupportedByAsset`. It also contains methods for updating pool metadata (`updatePoolMetadata`)\\n * and setting pool name (`setPoolName`).\\n *\\n * The directory of pools is managed through two mappings: `_poolByComptroller` which is a hashmap with the comptroller address as the key and `VenusPool` as\\n * the value and `_poolsByID` which is an array of comptroller addresses. Individual pools can be accessed by calling `getPoolByComptroller` with the pool's\\n * comptroller address. `_poolsByID` is used to iterate through all of the pools.\\n *\\n * PoolRegistry also contains a map of asset addresses called `_supportedPools` that maps to an array of assets suppored by each pool. This array of pools by\\n * asset is retrieved by calling `getPoolsSupportedByAsset`.\\n *\\n * PoolRegistry registers new isolated pools in the directory with the `createRegistryPool` method. Isolated pools are composed of independent markets with\\n * specific assets and custom risk management configurations according to their markets.\\n */\\ncontract PoolRegistry is Ownable2StepUpgradeable, AccessControlledV8, PoolRegistryInterface {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n struct AddMarketInput {\\n VToken vToken;\\n uint256 collateralFactor;\\n uint256 liquidationThreshold;\\n uint256 initialSupply;\\n address vTokenReceiver;\\n uint256 supplyCap;\\n uint256 borrowCap;\\n }\\n\\n uint256 internal constant MAX_POOL_NAME_LENGTH = 100;\\n\\n /**\\n * @notice Maps pool's comptroller address to metadata.\\n */\\n mapping(address => VenusPoolMetaData) public metadata;\\n\\n /**\\n * @dev Maps pool ID to pool's comptroller address\\n */\\n mapping(uint256 => address) private _poolsByID;\\n\\n /**\\n * @dev Total number of pools created.\\n */\\n uint256 private _numberOfPools;\\n\\n /**\\n * @dev Maps comptroller address to Venus pool Index.\\n */\\n mapping(address => VenusPool) private _poolByComptroller;\\n\\n /**\\n * @dev Maps pool's comptroller address to asset to vToken.\\n */\\n mapping(address => mapping(address => address)) private _vTokens;\\n\\n /**\\n * @dev Maps asset to list of supported pools.\\n */\\n mapping(address => address[]) private _supportedPools;\\n\\n /**\\n * @notice Emitted when a new Venus pool is added to the directory.\\n */\\n event PoolRegistered(address indexed comptroller, VenusPool pool);\\n\\n /**\\n * @notice Emitted when a pool name is set.\\n */\\n event PoolNameSet(address indexed comptroller, string oldName, string newName);\\n\\n /**\\n * @notice Emitted when a pool metadata is updated.\\n */\\n event PoolMetadataUpdated(\\n address indexed comptroller,\\n VenusPoolMetaData oldMetadata,\\n VenusPoolMetaData newMetadata\\n );\\n\\n /**\\n * @notice Emitted when a Market is added to the pool.\\n */\\n event MarketAdded(address indexed comptroller, address indexed vTokenAddress);\\n\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor() {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializes the deployer to owner\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(address accessControlManager_) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n /**\\n * @notice Adds a new Venus pool to the directory\\n * @dev Price oracle must be configured before adding a pool\\n * @param name The name of the pool\\n * @param comptroller Pool's Comptroller contract\\n * @param closeFactor The pool's close factor (scaled by 1e18)\\n * @param liquidationIncentive The pool's liquidation incentive (scaled by 1e18)\\n * @param minLiquidatableCollateral Minimal collateral for regular (non-batch) liquidations flow\\n * @return index The index of the registered Venus pool\\n * @custom:error ZeroAddressNotAllowed is thrown when Comptroller address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\\n */\\n function addPool(\\n string calldata name,\\n Comptroller comptroller,\\n uint256 closeFactor,\\n uint256 liquidationIncentive,\\n uint256 minLiquidatableCollateral\\n ) external virtual returns (uint256 index) {\\n _checkAccessAllowed(\\\"addPool(string,address,uint256,uint256,uint256)\\\");\\n // Input validation\\n ensureNonzeroAddress(address(comptroller));\\n ensureNonzeroAddress(address(comptroller.oracle()));\\n\\n uint256 poolId = _registerPool(name, address(comptroller));\\n\\n // Set Venus pool parameters\\n comptroller.setCloseFactor(closeFactor);\\n comptroller.setLiquidationIncentive(liquidationIncentive);\\n comptroller.setMinLiquidatableCollateral(minLiquidatableCollateral);\\n\\n return poolId;\\n }\\n\\n /**\\n * @notice Add a market to an existing pool and then mint to provide initial supply\\n * @param input The structure describing the parameters for adding a market to a pool\\n * @custom:error ZeroAddressNotAllowed is thrown when vToken address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when vTokenReceiver address is zero\\n */\\n function addMarket(AddMarketInput memory input) external {\\n _checkAccessAllowed(\\\"addMarket(AddMarketInput)\\\");\\n ensureNonzeroAddress(address(input.vToken));\\n ensureNonzeroAddress(input.vTokenReceiver);\\n require(input.initialSupply > 0, \\\"PoolRegistry: initialSupply is zero\\\");\\n\\n VToken vToken = input.vToken;\\n address vTokenAddress = address(vToken);\\n address comptrollerAddress = address(vToken.comptroller());\\n Comptroller comptroller = Comptroller(comptrollerAddress);\\n address underlyingAddress = vToken.underlying();\\n IERC20Upgradeable underlying = IERC20Upgradeable(underlyingAddress);\\n\\n require(_poolByComptroller[comptrollerAddress].creator != address(0), \\\"PoolRegistry: Pool not registered\\\");\\n // solhint-disable-next-line reason-string\\n require(\\n _vTokens[comptrollerAddress][underlyingAddress] == address(0),\\n \\\"PoolRegistry: Market already added for asset comptroller combination\\\"\\n );\\n\\n comptroller.supportMarket(vToken);\\n comptroller.setCollateralFactor(vToken, input.collateralFactor, input.liquidationThreshold);\\n\\n uint256[] memory newSupplyCaps = new uint256[](1);\\n uint256[] memory newBorrowCaps = new uint256[](1);\\n VToken[] memory vTokens = new VToken[](1);\\n\\n newSupplyCaps[0] = input.supplyCap;\\n newBorrowCaps[0] = input.borrowCap;\\n vTokens[0] = vToken;\\n\\n comptroller.setMarketSupplyCaps(vTokens, newSupplyCaps);\\n comptroller.setMarketBorrowCaps(vTokens, newBorrowCaps);\\n\\n _vTokens[comptrollerAddress][underlyingAddress] = vTokenAddress;\\n _supportedPools[underlyingAddress].push(comptrollerAddress);\\n\\n uint256 amountToSupply = _transferIn(underlying, msg.sender, input.initialSupply);\\n underlying.forceApprove(vTokenAddress, 0);\\n underlying.forceApprove(vTokenAddress, amountToSupply);\\n vToken.mintBehalf(input.vTokenReceiver, amountToSupply);\\n\\n emit MarketAdded(comptrollerAddress, vTokenAddress);\\n }\\n\\n /**\\n * @notice Modify existing Venus pool name\\n * @param comptroller Pool's Comptroller\\n * @param name New pool name\\n */\\n function setPoolName(address comptroller, string calldata name) external {\\n _checkAccessAllowed(\\\"setPoolName(address,string)\\\");\\n _ensureValidName(name);\\n VenusPool storage pool = _poolByComptroller[comptroller];\\n string memory oldName = pool.name;\\n pool.name = name;\\n emit PoolNameSet(comptroller, oldName, name);\\n }\\n\\n /**\\n * @notice Update metadata of an existing pool\\n * @param comptroller Pool's Comptroller\\n * @param metadata_ New pool metadata\\n */\\n function updatePoolMetadata(address comptroller, VenusPoolMetaData calldata metadata_) external {\\n _checkAccessAllowed(\\\"updatePoolMetadata(address,VenusPoolMetaData)\\\");\\n VenusPoolMetaData memory oldMetadata = metadata[comptroller];\\n metadata[comptroller] = metadata_;\\n emit PoolMetadataUpdated(comptroller, oldMetadata, metadata_);\\n }\\n\\n /**\\n * @notice Returns arrays of all Venus pools' data\\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\\n * @return A list of all pools within PoolRegistry, with details for each pool\\n */\\n function getAllPools() external view override returns (VenusPool[] memory) {\\n uint256 numberOfPools_ = _numberOfPools; // storage load to save gas\\n VenusPool[] memory _pools = new VenusPool[](numberOfPools_);\\n for (uint256 i = 1; i <= numberOfPools_; ++i) {\\n address comptroller = _poolsByID[i];\\n _pools[i - 1] = (_poolByComptroller[comptroller]);\\n }\\n return _pools;\\n }\\n\\n /**\\n * @param comptroller The comptroller proxy address associated to the pool\\n * @return Returns Venus pool\\n */\\n function getPoolByComptroller(address comptroller) external view override returns (VenusPool memory) {\\n return _poolByComptroller[comptroller];\\n }\\n\\n /**\\n * @param comptroller comptroller of Venus pool\\n * @return Returns Metadata of Venus pool\\n */\\n function getVenusPoolMetadata(address comptroller) external view override returns (VenusPoolMetaData memory) {\\n return metadata[comptroller];\\n }\\n\\n function getVTokenForAsset(address comptroller, address asset) external view override returns (address) {\\n return _vTokens[comptroller][asset];\\n }\\n\\n function getPoolsSupportedByAsset(address asset) external view override returns (address[] memory) {\\n return _supportedPools[asset];\\n }\\n\\n /**\\n * @dev Adds a new Venus pool to the directory (without checking msg.sender).\\n * @param name The name of the pool\\n * @param comptroller The pool's Comptroller proxy contract address\\n * @return The index of the registered Venus pool\\n */\\n function _registerPool(string calldata name, address comptroller) internal returns (uint256) {\\n VenusPool storage storedPool = _poolByComptroller[comptroller];\\n\\n require(storedPool.creator == address(0), \\\"PoolRegistry: Pool already exists in the directory.\\\");\\n _ensureValidName(name);\\n\\n ++_numberOfPools;\\n uint256 numberOfPools_ = _numberOfPools; // cache on stack to save storage read gas\\n\\n VenusPool memory pool = VenusPool(name, msg.sender, comptroller, block.number, block.timestamp);\\n\\n _poolsByID[numberOfPools_] = comptroller;\\n _poolByComptroller[comptroller] = pool;\\n\\n emit PoolRegistered(comptroller, pool);\\n return numberOfPools_;\\n }\\n\\n function _transferIn(IERC20Upgradeable token, address from, uint256 amount) internal returns (uint256) {\\n uint256 balanceBefore = token.balanceOf(address(this));\\n token.safeTransferFrom(from, address(this), amount);\\n uint256 balanceAfter = token.balanceOf(address(this));\\n return balanceAfter - balanceBefore;\\n }\\n\\n function _ensureValidName(string calldata name) internal pure {\\n require(bytes(name).length <= MAX_POOL_NAME_LENGTH, \\\"Pool's name is too large\\\");\\n }\\n}\\n\",\"keccak256\":\"0xafbb871f7b4db3ef439d846baa5f18a136192f9b43ea695c81262a77b06c4b25\",\"license\":\"BSD-3-Clause\"},\"contracts/Pool/PoolRegistryInterface.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 /**\\n * @notice Struct for a Venus interest rate pool metadata.\\n */\\n struct VenusPoolMetaData {\\n string category;\\n string logoURL;\\n string description;\\n }\\n\\n /// @notice Get all pools in PoolRegistry\\n function getAllPools() external view returns (VenusPool[] memory);\\n\\n /// @notice Get a pool by comptroller address\\n function getPoolByComptroller(address comptroller) external view returns (VenusPool memory);\\n\\n /// @notice Get the address of the VToken contract in the Pool where the underlying token is the provided 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 /// @notice Get the metadata of a Pool by comptroller address\\n function getVenusPoolMetadata(address comptroller) external view returns (VenusPoolMetaData memory);\\n}\\n\",\"keccak256\":\"0x7b39cda3b372a686501ce3c2aad288c6af410148110318249d75d4516729c92c\",\"license\":\"BSD-3-Clause\"},\"contracts/Rewards/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\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 { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"../MaxLoopsLimitHelper.sol\\\";\\nimport { RewardsDistributorStorage } from \\\"./RewardsDistributorStorage.sol\\\";\\n\\n/**\\n * @title `RewardsDistributor`\\n * @author Venus\\n * @notice Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol.\\n * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward\\n * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool.\\n * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward\\n * token to be released each slot (block or second) for borrowers and suppliers, which is distributed based on a user\\u2019s percentage of the borrows or supplies\\n * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting\\n * their contributor reward token speed, which similarly allocates a fixed amount of reward token per slot (block or second).\\n *\\n * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed\\n * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized\\n * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\\n */\\ncontract RewardsDistributor is\\n ExponentialNoError,\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n MaxLoopsLimitHelper,\\n RewardsDistributorStorage,\\n TimeManagerV8\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice The initial REWARD TOKEN index for a market\\n uint224 public constant INITIAL_INDEX = 1e36;\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a supplier\\n event DistributedSupplierRewardToken(\\n VToken indexed vToken,\\n address indexed supplier,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenSupplyIndex\\n );\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a borrower\\n event DistributedBorrowerRewardToken(\\n VToken indexed vToken,\\n address indexed borrower,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenBorrowIndex\\n );\\n\\n /// @notice Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when REWARD TOKEN is granted by admin\\n event RewardTokenGranted(address indexed recipient, uint256 amount);\\n\\n /// @notice Emitted when a new REWARD TOKEN speed is set for a contributor\\n event ContributorRewardTokenSpeedUpdated(address indexed contributor, uint256 newSpeed);\\n\\n /// @notice Emitted when a market is initialized\\n event MarketInitialized(address indexed vToken);\\n\\n /// @notice Emitted when a reward token supply index is updated\\n event RewardTokenSupplyIndexUpdated(address indexed vToken);\\n\\n /// @notice Emitted when a reward token borrow index is updated\\n event RewardTokenBorrowIndexUpdated(address indexed vToken, Exp marketBorrowIndex);\\n\\n /// @notice Emitted when a reward for contributor is updated\\n event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued);\\n\\n /// @notice Emitted when a reward token last rewarding block for supply is updated\\n event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding block for borrow is updated\\n event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding timestamp for supply is updated\\n event SupplyLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\\n\\n /// @notice Emitted when a reward token last rewarding timestamp for borrow is updated\\n event BorrowLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\\n\\n modifier onlyComptroller() {\\n require(address(comptroller) == msg.sender, \\\"Only comptroller can call this function\\\");\\n _;\\n }\\n\\n /**\\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice RewardsDistributor initializer\\n * @dev Initializes the deployer to owner\\n * @param comptroller_ Comptroller to attach the reward distributor to\\n * @param rewardToken_ Reward token to distribute\\n * @param loopsLimit_ Maximum number of iterations for the loops in this contract\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(\\n Comptroller comptroller_,\\n IERC20Upgradeable rewardToken_,\\n uint256 loopsLimit_,\\n address accessControlManager_\\n ) external initializer {\\n comptroller = comptroller_;\\n rewardToken = rewardToken_;\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n\\n _setMaxLoopsLimit(loopsLimit_);\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken\\n * @param vToken The address of the vToken to be initialized\\n * @custom:event MarketInitialized emits on success\\n * @custom:access Only Comptroller\\n */\\n function initializeMarket(address vToken) external onlyComptroller {\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n isTimeBased\\n ? _initializeMarketTimestampBased(vToken, blockNumberOrTimestamp)\\n : _initializeMarketBlockBased(vToken, safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\"));\\n\\n emit MarketInitialized(vToken);\\n }\\n\\n /*** Reward Token Distribution ***/\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them\\n * Borrowers will begin to accrue after the first interaction with the protocol.\\n * @dev This function should only be called when the user has a borrow position in the market\\n * (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook)\\n * We avoid an external call to check if they are in the market to save gas because this function is called in many places\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function distributeBorrowerRewardToken(\\n address vToken,\\n address borrower,\\n Exp memory marketBorrowIndex\\n ) external onlyComptroller {\\n _distributeBorrowerRewardToken(vToken, borrower, marketBorrowIndex);\\n }\\n\\n function updateRewardTokenSupplyIndex(address vToken) external onlyComptroller {\\n _updateRewardTokenSupplyIndex(vToken);\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the recipient\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\\n * @param recipient The address of the recipient to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n */\\n function grantRewardToken(address recipient, uint256 amount) external onlyOwner {\\n uint256 amountLeft = _grantRewardToken(recipient, amount);\\n require(amountLeft == 0, \\\"insufficient rewardToken for grant\\\");\\n emit RewardTokenGranted(recipient, amount);\\n }\\n\\n function updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) external onlyComptroller {\\n _updateRewardTokenBorrowIndex(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN borrow and supply speeds for the specified markets\\n * @param vTokens The markets whose REWARD TOKEN speed to update\\n * @param supplySpeeds New supply-side REWARD TOKEN speed for the corresponding market\\n * @param borrowSpeeds New borrow-side REWARD TOKEN speed for the corresponding market\\n */\\n function setRewardTokenSpeeds(\\n VToken[] memory vTokens,\\n uint256[] memory supplySpeeds,\\n uint256[] memory borrowSpeeds\\n ) external {\\n _checkAccessAllowed(\\\"setRewardTokenSpeeds(address[],uint256[],uint256[])\\\");\\n uint256 numTokens = vTokens.length;\\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \\\"invalid setRewardTokenSpeeds\\\");\\n\\n for (uint256 i; i < numTokens; ++i) {\\n _setRewardTokenSpeed(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for the specified markets, used when contract is block based\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market\\n * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market\\n */\\n function setLastRewardingBlocks(\\n VToken[] calldata vTokens,\\n uint32[] calldata supplyLastRewardingBlocks,\\n uint32[] calldata borrowLastRewardingBlocks\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlocks(address[],uint32[],uint32[])\\\");\\n require(!isTimeBased, \\\"Block-based operation only\\\");\\n\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length,\\n \\\"RewardsDistributor::setLastRewardingBlocks invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlock(vTokens[i], supplyLastRewardingBlocks[i], borrowLastRewardingBlocks[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block timestamp for the specified markets, used when contract is time based\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlockTimestamps New supply-side REWARD TOKEN last rewarding block timestamp for the corresponding market\\n * @param borrowLastRewardingBlockTimestamps New borrow-side REWARD TOKEN last rewarding block timestamp for the corresponding market\\n */\\n function setLastRewardingBlockTimestamps(\\n VToken[] calldata vTokens,\\n uint256[] calldata supplyLastRewardingBlockTimestamps,\\n uint256[] calldata borrowLastRewardingBlockTimestamps\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlockTimestamps(address[],uint256[],uint256[])\\\");\\n require(isTimeBased, \\\"Time-based operation only\\\");\\n\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlockTimestamps.length &&\\n numTokens == borrowLastRewardingBlockTimestamps.length,\\n \\\"RewardsDistributor::setLastRewardingBlockTimestamps invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlockTimestamp(\\n vTokens[i],\\n supplyLastRewardingBlockTimestamps[i],\\n borrowLastRewardingBlockTimestamps[i]\\n );\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single contributor\\n * @param contributor The contributor whose REWARD TOKEN speed to update\\n * @param rewardTokenSpeed New REWARD TOKEN speed for contributor\\n */\\n function setContributorRewardTokenSpeed(address contributor, uint256 rewardTokenSpeed) external onlyOwner {\\n // note that REWARD TOKEN speed could be set to 0 to halt liquidity rewards for a contributor\\n updateContributorRewards(contributor);\\n if (rewardTokenSpeed == 0) {\\n // release storage\\n delete lastContributorBlock[contributor];\\n } else {\\n lastContributorBlock[contributor] = getBlockNumberOrTimestamp();\\n }\\n rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed;\\n\\n emit ContributorRewardTokenSpeedUpdated(contributor, rewardTokenSpeed);\\n }\\n\\n function distributeSupplierRewardToken(address vToken, address supplier) external onlyComptroller {\\n _distributeSupplierRewardToken(vToken, supplier);\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in all markets\\n * @param holder The address to claim REWARD TOKEN for\\n */\\n function claimRewardToken(address holder) external {\\n return claimRewardToken(holder, comptroller.getAllMarkets());\\n }\\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) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Calculate additional accrued REWARD TOKEN for a contributor since last accrual\\n * @param contributor The address to calculate contributor rewards for\\n */\\n function updateContributorRewards(address contributor) public {\\n uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, lastContributorBlock[contributor]);\\n if (deltaBlocksOrTimestamp > 0 && rewardTokenSpeed > 0) {\\n uint256 newAccrued = mul_(deltaBlocksOrTimestamp, rewardTokenSpeed);\\n uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued);\\n\\n rewardTokenAccrued[contributor] = contributorAccrued;\\n lastContributorBlock[contributor] = blockNumberOrTimestamp;\\n\\n emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]);\\n }\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in the specified markets\\n * @param holder The address to claim REWARD TOKEN for\\n * @param vTokens The list of markets to claim REWARD TOKEN in\\n */\\n function claimRewardToken(address holder, VToken[] memory vTokens) public {\\n uint256 vTokensCount = vTokens.length;\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n VToken vToken = vTokens[i];\\n require(comptroller.isMarketListed(vToken), \\\"market must be listed\\\");\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n _distributeBorrowerRewardToken(address(vToken), holder, borrowIndex);\\n _updateRewardTokenSupplyIndex(address(vToken));\\n _distributeSupplierRewardToken(address(vToken), holder);\\n }\\n rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for a single market.\\n * @param vToken market's whose reward token last rewarding block to be updated\\n * @param supplyLastRewardingBlock New supply-side REWARD TOKEN last rewarding block for market\\n * @param borrowLastRewardingBlock New borrow-side REWARD TOKEN last rewarding block for market\\n */\\n function _setLastRewardingBlock(\\n VToken vToken,\\n uint32 supplyLastRewardingBlock,\\n uint32 borrowLastRewardingBlock\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockNumber = getBlockNumberOrTimestamp();\\n\\n require(supplyLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n require(borrowLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n\\n uint32 currentSupplyLastRewardingBlock = rewardTokenSupplyState[address(vToken)].lastRewardingBlock;\\n uint32 currentBorrowLastRewardingBlock = rewardTokenBorrowState[address(vToken)].lastRewardingBlock;\\n\\n require(\\n currentSupplyLastRewardingBlock == 0 || currentSupplyLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlock == 0 || currentBorrowLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlock != supplyLastRewardingBlock) {\\n rewardTokenSupplyState[address(vToken)].lastRewardingBlock = supplyLastRewardingBlock;\\n emit SupplyLastRewardingBlockUpdated(address(vToken), supplyLastRewardingBlock);\\n }\\n\\n if (currentBorrowLastRewardingBlock != borrowLastRewardingBlock) {\\n rewardTokenBorrowState[address(vToken)].lastRewardingBlock = borrowLastRewardingBlock;\\n emit BorrowLastRewardingBlockUpdated(address(vToken), borrowLastRewardingBlock);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding timestamp for a single market.\\n * @param vToken market's whose reward token last rewarding timestamp to be updated\\n * @param supplyLastRewardingBlockTimestamp New supply-side REWARD TOKEN last rewarding timestamp for market\\n * @param borrowLastRewardingBlockTimestamp New borrow-side REWARD TOKEN last rewarding timestamp for market\\n */\\n function _setLastRewardingBlockTimestamp(\\n VToken vToken,\\n uint256 supplyLastRewardingBlockTimestamp,\\n uint256 borrowLastRewardingBlockTimestamp\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockTimestamp = getBlockNumberOrTimestamp();\\n\\n require(\\n supplyLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"setting last rewarding timestamp in the past is not allowed\\\"\\n );\\n require(\\n borrowLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"setting last rewarding timestamp in the past is not allowed\\\"\\n );\\n\\n uint256 currentSupplyLastRewardingBlockTimestamp = rewardTokenSupplyStateTimeBased[address(vToken)]\\n .lastRewardingTimestamp;\\n uint256 currentBorrowLastRewardingBlockTimestamp = rewardTokenBorrowStateTimeBased[address(vToken)]\\n .lastRewardingTimestamp;\\n\\n require(\\n currentSupplyLastRewardingBlockTimestamp == 0 || currentSupplyLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlockTimestamp == 0 || currentBorrowLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlockTimestamp != supplyLastRewardingBlockTimestamp) {\\n rewardTokenSupplyStateTimeBased[address(vToken)].lastRewardingTimestamp = supplyLastRewardingBlockTimestamp;\\n emit SupplyLastRewardingBlockTimestampUpdated(address(vToken), supplyLastRewardingBlockTimestamp);\\n }\\n\\n if (currentBorrowLastRewardingBlockTimestamp != borrowLastRewardingBlockTimestamp) {\\n rewardTokenBorrowStateTimeBased[address(vToken)].lastRewardingTimestamp = borrowLastRewardingBlockTimestamp;\\n emit BorrowLastRewardingBlockTimestampUpdated(address(vToken), borrowLastRewardingBlockTimestamp);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single market.\\n * @param vToken market's whose reward token rate to be updated\\n * @param supplySpeed New supply-side REWARD TOKEN speed for market\\n * @param borrowSpeed New borrow-side REWARD TOKEN speed for market\\n */\\n function _setRewardTokenSpeed(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n if (rewardTokenSupplySpeeds[address(vToken)] != supplySpeed) {\\n // Supply speed updated so let's update supply state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n _updateRewardTokenSupplyIndex(address(vToken));\\n\\n // Update speed and emit event\\n rewardTokenSupplySpeeds[address(vToken)] = supplySpeed;\\n emit RewardTokenSupplySpeedUpdated(vToken, supplySpeed);\\n }\\n\\n if (rewardTokenBorrowSpeeds[address(vToken)] != borrowSpeed) {\\n // Borrow speed updated so let's update borrow state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n\\n // Update speed and emit event\\n rewardTokenBorrowSpeeds[address(vToken)] = borrowSpeed;\\n emit RewardTokenBorrowSpeedUpdated(vToken, borrowSpeed);\\n }\\n }\\n\\n /**\\n * @notice Calculate REWARD TOKEN 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 REWARD TOKEN to\\n */\\n function _distributeSupplierRewardToken(address vToken, address supplier) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\\n\\n uint256 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\\n uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier];\\n\\n // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenSupplierIndex[vToken][supplier] = supplyIndex;\\n\\n if (supplierIndex == 0 && supplyIndex >= INITIAL_INDEX) {\\n // Covers the case where users supplied tokens before the market's supply state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when supplier rewards were first\\n // set for the market.\\n supplierIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per vToken accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\\n\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerVToken\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n\\n uint256 supplierAccrued = add_(rewardTokenAccrued[supplier], supplierDelta);\\n rewardTokenAccrued[supplier] = supplierAccrued;\\n\\n emit DistributedSupplierRewardToken(VToken(vToken), supplier, supplierDelta, supplierAccrued, supplyIndex);\\n }\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them.\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function _distributeBorrowerRewardToken(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\\n\\n uint256 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\\n uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower];\\n\\n // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenBorrowerIndex[vToken][borrower] = borrowIndex;\\n\\n if (borrowerIndex == 0 && borrowIndex >= INITIAL_INDEX) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when borrower rewards were first\\n // set for the market.\\n borrowerIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per borrowed unit accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\\n\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerBorrowedUnit\\n if (borrowerAmount != 0) {\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n\\n uint256 borrowerAccrued = add_(rewardTokenAccrued[borrower], borrowerDelta);\\n rewardTokenAccrued[borrower] = borrowerAccrued;\\n\\n emit DistributedBorrowerRewardToken(VToken(vToken), borrower, borrowerDelta, borrowerAccrued, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the user.\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all.\\n * @param user The address of the user to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n * @return The amount of REWARD TOKEN which was NOT transferred to the user\\n */\\n function _grantRewardToken(address user, uint256 amount) internal returns (uint256) {\\n uint256 rewardTokenRemaining = rewardToken.balanceOf(address(this));\\n if (amount > 0 && amount <= rewardTokenRemaining) {\\n rewardToken.safeTransfer(user, amount);\\n return 0;\\n }\\n return amount;\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the supply index\\n * @param vToken The market whose supply index to update\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenSupplyIndex(address vToken) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\\n\\n uint256 supplySpeed = rewardTokenSupplySpeeds[vToken];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (!isTimeBased) {\\n safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\");\\n }\\n\\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\\n ? supplyStateTimeBased.lastRewardingTimestamp\\n : uint256(supplyState.lastRewardingBlock);\\n\\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(\\n blockNumberOrTimestamp,\\n (isTimeBased ? supplyStateTimeBased.timestamp : uint256(supplyState.block))\\n );\\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, supplySpeed);\\n Double memory ratio = supplyTokens > 0\\n ? fraction(accruedSinceUpdate, supplyTokens)\\n : Double({ mantissa: 0 });\\n uint224 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\\n uint224 index = safe224(\\n add_(Double({ mantissa: supplyIndex }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n\\n if (isTimeBased) {\\n supplyStateTimeBased.index = index;\\n supplyStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n supplyState.index = index;\\n supplyState.block = uint32(blockNumberOrTimestamp);\\n }\\n } else if (deltaBlocksOrTimestamp > 0) {\\n isTimeBased ? supplyStateTimeBased.timestamp = blockNumberOrTimestamp : supplyState.block = uint32(\\n blockNumberOrTimestamp\\n );\\n }\\n\\n emit RewardTokenSupplyIndexUpdated(vToken);\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the borrow index\\n * @param vToken The market whose borrow index to update\\n * @param marketBorrowIndex The current global borrow index of vToken\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\\n\\n uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (!isTimeBased) {\\n safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\");\\n }\\n\\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\\n ? borrowStateTimeBased.lastRewardingTimestamp\\n : uint256(borrowState.lastRewardingBlock);\\n\\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(\\n blockNumberOrTimestamp,\\n (isTimeBased ? borrowStateTimeBased.timestamp : uint256(borrowState.block))\\n );\\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, borrowSpeed);\\n Double memory ratio = borrowAmount > 0\\n ? fraction(accruedSinceUpdate, borrowAmount)\\n : Double({ mantissa: 0 });\\n uint224 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\\n uint224 index = safe224(\\n add_(Double({ mantissa: borrowIndex }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n\\n if (isTimeBased) {\\n borrowStateTimeBased.index = index;\\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n borrowState.index = index;\\n borrowState.block = uint32(blockNumberOrTimestamp);\\n }\\n } else if (deltaBlocksOrTimestamp > 0) {\\n if (isTimeBased) {\\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n borrowState.block = uint32(blockNumberOrTimestamp);\\n }\\n }\\n\\n emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken called when contract is block-based\\n * @param vToken The address of the vToken to be initialized\\n * @param blockNumber current block number\\n */\\n function _initializeMarketBlockBased(address vToken, uint32 blockNumber) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n RewardToken storage borrowState = rewardTokenBorrowState[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 = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block numbers\\n */\\n supplyState.block = borrowState.block = blockNumber;\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken called when contract is time-based\\n * @param vToken The address of the vToken to be initialized\\n * @param blockTimestamp current block timestamp\\n */\\n function _initializeMarketTimestampBased(address vToken, uint256 blockTimestamp) internal {\\n TimeBasedRewardToken storage supplyState = rewardTokenSupplyStateTimeBased[vToken];\\n TimeBasedRewardToken storage borrowState = rewardTokenBorrowStateTimeBased[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 = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block timestamp\\n */\\n supplyState.timestamp = borrowState.timestamp = blockTimestamp;\\n }\\n}\\n\",\"keccak256\":\"0x3cc824e59c923cfe25c4f1a875959b7e9410cde8e73cd405de13f301298c697f\",\"license\":\"BSD-3-Clause\"},\"contracts/Rewards/RewardsDistributorStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\n\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\n\\n/**\\n * @title RewardsDistributorStorage\\n * @author Venus\\n * @dev Storage for RewardsDistributor\\n */\\ncontract RewardsDistributorStorage {\\n struct RewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number the index was last updated at\\n uint32 block;\\n // The block number at which to stop rewards\\n uint32 lastRewardingBlock;\\n }\\n\\n struct TimeBasedRewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block timestamp the index was last updated at\\n uint256 timestamp;\\n // The block timestamp at which to stop rewards\\n uint256 lastRewardingTimestamp;\\n }\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => RewardToken) public rewardTokenSupplyState;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex;\\n\\n /// @notice The REWARD TOKEN accrued but not yet transferred to each user\\n mapping(address => uint256) public rewardTokenAccrued;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding borrow market per slot (block or second)\\n mapping(address => uint256) public rewardTokenBorrowSpeeds;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding supply market per slot (block or second)\\n mapping(address => uint256) public rewardTokenSupplySpeeds;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => RewardToken) public rewardTokenBorrowState;\\n\\n /// @notice The portion of REWARD TOKEN that each contributor receives per slot (block or second)\\n mapping(address => uint256) public rewardTokenContributorSpeeds;\\n\\n /// @notice Last slot (block or second) at which a contributor's REWARD TOKEN rewards have been allocated\\n mapping(address => uint256) public lastContributorBlock;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex;\\n\\n Comptroller internal comptroller;\\n\\n IERC20Upgradeable public rewardToken;\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => TimeBasedRewardToken) public rewardTokenSupplyStateTimeBased;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => TimeBasedRewardToken) public rewardTokenBorrowStateTimeBased;\\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[37] private __gap;\\n}\\n\",\"keccak256\":\"0x70e5015a78a2acf95277949c8b4796e10b9ac194130be006d5e5217e158070c0\",\"license\":\"BSD-3-Clause\"},\"contracts/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\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 { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"@venusprotocol/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\\\";\\n\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { ComptrollerInterface, ComptrollerViewInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"./ErrorReporter.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title VToken\\n * @author Venus\\n * @notice Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview,\\n * each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of\\n * the pool. The main actions a user regularly interacts with in a market are:\\n\\n- mint/redeem of vTokens;\\n- transfer of vTokens;\\n- borrow/repay a loan on an underlying asset;\\n- liquidate a borrow or liquidate/heal an account.\\n\\n * A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`.\\n * The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted\\n * `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken`\\n * as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that\\n * a user may borrow up to a portion of their collateral determined by the market\\u2019s collateral factor. However, if their borrowed amount exceeds an amount\\n * calculated using the market\\u2019s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also\\n * pay off interest accrued on the borrow.\\n * \\n * The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller`\\n * and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a\\n * total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`.\\n * Both functions settle all of an account\\u2019s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of\\n * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\\n */\\ncontract VToken is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n VTokenInterface,\\n ExponentialNoError,\\n TokenErrorReporter,\\n TimeManagerV8\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5%\\n\\n // Maximum fraction of interest that can be set aside for reserves\\n uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18;\\n\\n // Maximum borrow rate that can ever be applied per slot(block or second)\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n uint256 internal immutable MAX_BORROW_RATE_MANTISSA;\\n\\n /**\\n * Reentrancy Guard **\\n */\\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 * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @param maxBorrowRateMantissa_ The maximum value of borrowing rate mantissa\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(\\n bool timeBased_,\\n uint256 blocksPerYear_,\\n uint256 maxBorrowRateMantissa_\\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n require(maxBorrowRateMantissa_ <= 1e18, \\\"Max borrow rate must be <= 1e18\\\");\\n\\n MAX_BORROW_RATE_MANTISSA = maxBorrowRateMantissa_;\\n _disableInitializers();\\n }\\n\\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_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n */\\n function initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) external initializer {\\n ensureNonzeroAddress(admin_);\\n\\n // Initialize the market\\n _initialize(\\n underlying_,\\n comptroller_,\\n interestRateModel_,\\n initialExchangeRateMantissa_,\\n name_,\\n symbol_,\\n decimals_,\\n admin_,\\n accessControlManager_,\\n riskManagement,\\n reserveFactorMantissa_\\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 * @return success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, msg.sender, dst, amount);\\n return true;\\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 success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, src, dst, amount);\\n return true;\\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 (uint256.max means infinite)\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Increase approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param addedValue The number of additional tokens spender can transfer\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function increaseAllowance(address spender, uint256 addedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 newAllowance = transferAllowances[src][spender];\\n newAllowance += addedValue;\\n transferAllowances[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n return true;\\n }\\n\\n /**\\n * @notice Decreases approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param subtractedValue The number of tokens to remove from total approval\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 currentAllowance = transferAllowances[src][spender];\\n require(currentAllowance >= subtractedValue, \\\"decreased allowance below zero\\\");\\n unchecked {\\n currentAllowance -= subtractedValue;\\n }\\n\\n transferAllowances[src][spender] = currentAllowance;\\n\\n emit Approval(src, spender, currentAllowance);\\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 amount The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint256) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return totalBorrows The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\\n accrueInterest();\\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 borrowBalance The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n return _borrowBalanceStored(account);\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function mint(uint256 mintAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _mintFresh(msg.sender, msg.sender, mintAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param minter User whom the supply will be attributed to\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when minter address is zero\\n */\\n function mintBehalf(address minter, uint256 mintAmount) external override nonReentrant returns (uint256) {\\n ensureNonzeroAddress(minter);\\n\\n accrueInterest();\\n\\n _mintFresh(msg.sender, minter, mintAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function redeem(uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _redeemFresh(msg.sender, msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function redeemBehalf(address redeemer, uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n _ensureSenderIsDelegateOf(redeemer);\\n\\n accrueInterest();\\n\\n _redeemFresh(redeemer, msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\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 receive from redeeming vTokens\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n */\\n function redeemUnderlying(uint256 redeemAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _redeemFresh(msg.sender, msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function redeemUnderlyingBehalf(\\n address redeemer,\\n uint256 redeemAmount\\n ) external override nonReentrant returns (uint256) {\\n _ensureSenderIsDelegateOf(redeemer);\\n\\n accrueInterest();\\n\\n _redeemFresh(redeemer, msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function borrow(uint256 borrowAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _borrowFresh(msg.sender, msg.sender, borrowAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error DelegateNotApproved is thrown if caller is not approved delegate\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function borrowBehalf(address borrower, uint256 borrowAmount) external override returns (uint256) {\\n _ensureSenderIsDelegateOf(borrower);\\n accrueInterest();\\n\\n _borrowFresh(borrower, msg.sender, borrowAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrow(uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n return NO_ERROR;\\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, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _repayBorrowFresh(msg.sender, borrower, repayAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Not restricted\\n */\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external override returns (uint256) {\\n _liquidateBorrow(msg.sender, borrower, repayAmount, vTokenCollateral, false);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice sets protocol share accumulated from liquidations\\n * @dev must be equal or less than liquidation incentive - 1\\n * @param newProtocolSeizeShareMantissa_ new protocol share mantissa\\n * @custom:event Emits NewProtocolSeizeShare event on success\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error ProtocolSeizeShareTooBig is thrown when the new seize share is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa_) external {\\n _checkAccessAllowed(\\\"setProtocolSeizeShare(uint256)\\\");\\n uint256 liquidationIncentive = ComptrollerViewInterface(address(comptroller)).liquidationIncentiveMantissa();\\n if (newProtocolSeizeShareMantissa_ + MANTISSA_ONE > liquidationIncentive) {\\n revert ProtocolSeizeShareTooBig();\\n }\\n\\n uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\\n protocolSeizeShareMantissa = newProtocolSeizeShareMantissa_;\\n emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa_);\\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 * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n * @custom:event Emits NewReserveFactor event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant {\\n _checkAccessAllowed(\\\"setReserveFactor(uint256)\\\");\\n\\n accrueInterest();\\n _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to the protocol reserve contract\\n * @dev Gracefully return if reserves already reduced in accrueInterest\\n * @param reduceAmount Amount of reduction to reserves\\n * @custom:event Emits ReservesReduced event; may emit AccrueInterest\\n * @custom:error ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash\\n * @custom:error ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\\n * @custom:access Not restricted\\n */\\n function reduceReserves(uint256 reduceAmount) external override nonReentrant {\\n accrueInterest();\\n if (reduceReservesBlockNumber == getBlockNumberOrTimestamp()) return;\\n _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice The sender adds to reserves.\\n * @param addAmount The amount of underlying token to add as reserves\\n * @custom:event Emits ReservesAdded event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function addReserves(uint256 addAmount) external override nonReentrant {\\n accrueInterest();\\n _addReservesFresh(addAmount);\\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 * @custom:event Emits NewMarketInterestRateModel event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external override {\\n _checkAccessAllowed(\\\"setInterestRateModel(address)\\\");\\n\\n accrueInterest();\\n _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially\\n * \\\"forgiving\\\" the borrower. Healing is a situation that should rarely happen. However, some pools\\n * may list risky assets or be configured improperly \\u2013 we want to still handle such cases gracefully.\\n * We assume that Comptroller does the seizing, so this function is only available to Comptroller.\\n * @dev This function does not call any Comptroller hooks (like \\\"healAllowed\\\"), because we assume\\n * the Comptroller does all the necessary checks before calling this function.\\n * @param payer account who repays the debt\\n * @param borrower account to heal\\n * @param repayAmount amount to repay\\n * @custom:event Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\\n * @custom:error HealBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:access Only Comptroller\\n */\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external override nonReentrant {\\n if (repayAmount != 0) {\\n comptroller.preRepayHook(address(this), borrower);\\n }\\n\\n if (msg.sender != address(comptroller)) {\\n revert HealBorrowUnauthorized();\\n }\\n\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 totalBorrowsNew = totalBorrows;\\n\\n uint256 actualRepayAmount;\\n if (repayAmount != 0) {\\n // _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // We violate checks-effects-interactions here to account for tokens that take transfer fees\\n actualRepayAmount = _doTransferIn(payer, repayAmount);\\n totalBorrowsNew = totalBorrowsNew - actualRepayAmount;\\n emit RepayBorrow(\\n payer,\\n borrower,\\n actualRepayAmount,\\n accountBorrowsPrev - actualRepayAmount,\\n totalBorrowsNew\\n );\\n }\\n\\n // The transaction will fail if trying to repay too much\\n uint256 badDebtDelta = accountBorrowsPrev - actualRepayAmount;\\n if (badDebtDelta != 0) {\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld + badDebtDelta;\\n totalBorrowsNew = totalBorrowsNew - badDebtDelta;\\n badDebt = badDebtNew;\\n\\n // We treat healing as \\\"repayment\\\", where vToken is the payer\\n emit RepayBorrow(address(this), borrower, badDebtDelta, 0, totalBorrowsNew);\\n emit BadDebtIncreased(borrower, badDebtDelta, badDebtOld, badDebtNew);\\n }\\n\\n accountBorrows[borrower].principal = 0;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n emit HealBorrow(payer, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice The extended version of liquidations, callable only by Comptroller. May skip\\n * the close factor check. The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Only Comptroller\\n */\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) external override {\\n if (msg.sender != address(comptroller)) {\\n revert ForceLiquidateBorrowUnauthorized();\\n }\\n _liquidateBorrow(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\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 * @custom:event Emits Transfer, ReservesAdded events\\n * @custom:error LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:access Not restricted\\n */\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external override nonReentrant {\\n _seize(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Updates bad debt\\n * @dev Called only when bad debt is recovered from auction\\n * @param recoveredAmount_ The amount of bad debt recovered\\n * @custom:event Emits BadDebtRecovered event\\n * @custom:access Only Shortfall contract\\n */\\n function badDebtRecovered(uint256 recoveredAmount_) external {\\n require(msg.sender == shortfall, \\\"only shortfall contract can update bad debt\\\");\\n require(recoveredAmount_ <= badDebt, \\\"more than bad debt recovered from auction\\\");\\n\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld - recoveredAmount_;\\n badDebt = badDebtNew;\\n\\n emit BadDebtRecovered(badDebtOld, badDebtNew);\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protocolShareReserve_ The address of the protocol share reserve contract\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n * @custom:access Only Governance\\n */\\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\\n _setProtocolShareReserve(protocolShareReserve_);\\n }\\n\\n /**\\n * @notice Sets shortfall contract address\\n * @param shortfall_ The address of the shortfall contract\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:access Only Governance\\n */\\n function setShortfallContract(address shortfall_) external onlyOwner {\\n _setShortfallContract(shortfall_);\\n }\\n\\n /**\\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\\n * @param token The address of the ERC-20 token to sweep\\n * @custom:access Only Governance\\n */\\n function sweepToken(IERC20Upgradeable token) external override {\\n require(msg.sender == owner(), \\\"VToken::sweepToken: only admin can sweep tokens\\\");\\n require(address(token) != underlying, \\\"VToken::sweepToken: can not sweep underlying token\\\");\\n uint256 balance = token.balanceOf(address(this));\\n token.safeTransfer(owner(), balance);\\n\\n emit SweepToken(address(token));\\n }\\n\\n /**\\n * @notice A public function to set new threshold of slot(block or second) difference after which funds will be sent to the protocol share reserve\\n * @param _newReduceReservesBlockOrTimestampDelta slot(block or second) difference value\\n * @custom:access Only Governance\\n */\\n function setReduceReservesBlockDelta(uint256 _newReduceReservesBlockOrTimestampDelta) external {\\n _checkAccessAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n require(_newReduceReservesBlockOrTimestampDelta > 0, \\\"Invalid Input\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, _newReduceReservesBlockOrTimestampDelta);\\n reduceReservesBlockDelta = _newReduceReservesBlockOrTimestampDelta;\\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 amount 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 amount 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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return vTokenBalance User's balance of vTokens\\n * @return borrowBalance Amount owed in terms of underlying\\n * @return exchangeRate Stored exchange rate\\n */\\n function getAccountSnapshot(\\n address account\\n )\\n external\\n view\\n override\\n returns (uint256 error, uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRate)\\n {\\n return (NO_ERROR, accountTokens[account], _borrowBalanceStored(account), _exchangeRateStored());\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return cash The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint256) {\\n return _getCashPrior();\\n }\\n\\n /**\\n * @notice Returns the current per slot(block or second) borrow interest rate for this vToken\\n * @return rate The borrow interest rate per slot(block or second), scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint256) {\\n return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt);\\n }\\n\\n /**\\n * @notice Returns the current per-slot(block or second) supply interest rate for this v\\n * @return rate The supply interest rate per slot(block or second), scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint256) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPrior(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa,\\n badDebt\\n );\\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 borrowBalance The calculated balance\\n */\\n function borrowBalanceStored(address account) external view override returns (uint256) {\\n return _borrowBalanceStored(account);\\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 exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() external view override returns (uint256) {\\n return _exchangeRateStored();\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\\n accrueInterest();\\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 slot(block or second)\\n * up to the current slot(block or second) and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentSlot - reduceReservesBlockNumber >= slotDelta\\n * @return Always NO_ERROR\\n * @custom:event Emits AccrueInterest event on success\\n * @custom:access Not restricted\\n */\\n function accrueInterest() public virtual override returns (uint256) {\\n /* Remember the initial block number or timestamp */\\n uint256 currentSlotNumber = getBlockNumberOrTimestamp();\\n uint256 accrualSlotNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualSlotNumberPrior == currentSlotNumber) {\\n return NO_ERROR;\\n }\\n\\n /* Read the previous values out of storage */\\n uint256 cashPrior = _getCashPrior();\\n uint256 borrowsPrior = totalBorrows;\\n uint256 reservesPrior = totalReserves;\\n uint256 borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt);\\n require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of slots elapsed since the last accrual */\\n uint256 slotDelta = currentSlotNumber - accrualSlotNumberPrior;\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * slotDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), slotDelta);\\n uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\\n uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;\\n uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentSlotNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n if (currentSlotNumber - reduceReservesBlockNumber >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentSlotNumber;\\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 NO_ERROR;\\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 or timestamp\\n * @param payer The address of the account which is sending the assets for supply\\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 */\\n function _mintFresh(address payer, address minter, uint256 mintAmount) internal {\\n /* Fail if mint not allowed */\\n comptroller.preMintHook(address(this), minter, mintAmount);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert MintFreshnessCheck();\\n }\\n\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\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 * `_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 uint256 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 uint256 mintTokens = div_(actualMintAmount, exchangeRate);\\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 * And write them into storage\\n */\\n totalSupply = totalSupply + mintTokens;\\n uint256 balanceAfter = accountTokens[minter] + mintTokens;\\n accountTokens[minter] = balanceAfter;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, actualMintAmount, mintTokens, balanceAfter);\\n emit Transfer(address(0), minter, mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, actualMintAmount, mintTokens);\\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 Comptroller.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current slot(block or second)\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the underlying 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 */\\n function _redeemFresh(address redeemer, address receiver, uint256 redeemTokensIn, uint256 redeemAmountIn) internal {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert RedeemFreshnessCheck();\\n }\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n\\n uint256 redeemTokens;\\n uint256 redeemAmount;\\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 */\\n redeemTokens = redeemTokensIn;\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n */\\n redeemTokens = div_(redeemAmountIn, exchangeRate);\\n\\n uint256 _redeemAmount = mul_(redeemTokens, exchangeRate);\\n if (_redeemAmount != 0 && _redeemAmount != redeemAmountIn) redeemTokens++; // round up\\n }\\n\\n // redeemAmount = exchangeRate * redeemTokens\\n redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokens);\\n\\n // Revert if amount is zero\\n if (redeemAmount == 0) {\\n revert(\\\"redeemAmount is zero\\\");\\n }\\n\\n /* Fail if redeem not allowed */\\n comptroller.preRedeemHook(address(this), redeemer, redeemTokens);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (_getCashPrior() - totalReserves < redeemAmount) {\\n revert RedeemTransferOutNotPossible();\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\\n */\\n totalSupply = totalSupply - redeemTokens;\\n uint256 balanceAfter = accountTokens[redeemer] - redeemTokens;\\n accountTokens[redeemer] = balanceAfter;\\n\\n /*\\n * We invoke _doTransferOut for the receiver and the redeemAmount.\\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 _doTransferOut(receiver, redeemAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), redeemTokens);\\n emit Redeem(redeemer, redeemAmount, redeemTokens, balanceAfter);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, redeemAmount, redeemTokens);\\n }\\n\\n /**\\n * @notice Users or their delegates borrow assets from the protocol\\n * @param borrower User who borrows the assets\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param borrowAmount The amount of the underlying asset to borrow\\n */\\n function _borrowFresh(address borrower, address receiver, uint256 borrowAmount) internal {\\n /* Fail if borrow not allowed */\\n comptroller.preBorrowHook(address(this), borrower, borrowAmount);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert BorrowFreshnessCheck();\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (_getCashPrior() - totalReserves < borrowAmount) {\\n revert BorrowCashNotAvailable();\\n }\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowNew = accountBorrow + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;\\n uint256 totalBorrowsNew = totalBorrows + borrowAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\\n `*/\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /*\\n * We invoke _doTransferOut for the receiver and the borrowAmount.\\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, accountBorrowsNew, totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\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 underlying tokens being returned, or type(uint256).max for the full outstanding amount\\n * @return (uint) the actual repayment amount.\\n */\\n function _repayBorrowFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256) {\\n /* Fail if repayBorrow not allowed */\\n comptroller.preRepayHook(address(this), borrower);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert RepayBorrowFreshnessCheck();\\n }\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n\\n uint256 repayAmountFinal = repayAmount >= accountBorrowsPrev ? accountBorrowsPrev : 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 * 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 uint256 actualRepayAmount = _doTransferIn(payer, repayAmountFinal);\\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 uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\\n uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, actualRepayAmount, borrowIndex);\\n\\n return actualRepayAmount;\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal nonReentrant {\\n accrueInterest();\\n\\n uint256 error = vTokenCollateral.accrueInterest();\\n if (error != NO_ERROR) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n revert LiquidateAccrueCollateralInterestFailed(error);\\n }\\n\\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal {\\n /* Fail if liquidate not allowed */\\n comptroller.preLiquidateHook(\\n address(this),\\n address(vTokenCollateral),\\n borrower,\\n repayAmount,\\n skipLiquidityCheck\\n );\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert LiquidateFreshnessCheck();\\n }\\n\\n /* Verify vTokenCollateral market's slot(block or second) number equals current slot(block or second) number */\\n if (vTokenCollateral.accrualBlockNumber() != getBlockNumberOrTimestamp()) {\\n revert LiquidateCollateralFreshnessCheck();\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateLiquidatorIsBorrower();\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n revert LiquidateCloseAmountIsZero();\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n revert LiquidateCloseAmountIsUintMax();\\n }\\n\\n /* Fail if repayBorrow fails */\\n uint256 actualRepayAmount = _repayBorrowFresh(liquidator, borrower, repayAmount);\\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.liquidateCalculateSeizeTokens(\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n require(amountSeizeError == 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, call _seize internally to avoid re-entrancy, otherwise make an external call\\n if (address(vTokenCollateral) == address(this)) {\\n _seize(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\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\\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 * It's absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerContract The contract seizing the collateral (either borrowed vToken or Comptroller)\\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 */\\n function _seize(address seizerContract, address liquidator, address borrower, uint256 seizeTokens) internal {\\n /* Fail if seize not allowed */\\n comptroller.preSeizeHook(address(this), seizerContract, liquidator, borrower);\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateSeizeLiquidatorIsBorrower();\\n }\\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 uint256 liquidationIncentiveMantissa = ComptrollerViewInterface(address(comptroller))\\n .liquidationIncentiveMantissa();\\n uint256 numerator = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));\\n uint256 protocolSeizeTokens = div_(numerator, Exp({ mantissa: liquidationIncentiveMantissa }));\\n uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n uint256 protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the calculated values into storage */\\n totalSupply = totalSupply - protocolSeizeTokens;\\n accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\\n accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\\n\\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, protocolSeizeAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.LIQUIDATION\\n );\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\\n emit ProtocolSeize(borrower, protocolShareReserve, protocolSeizeAmount);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerContract, liquidator, borrower, seizeTokens);\\n }\\n\\n function _setComptroller(ComptrollerInterface newComptroller) internal {\\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\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n */\\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal {\\n // Verify market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert SetReserveFactorFreshCheck();\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > MAX_RESERVE_FACTOR_MANTISSA) {\\n revert SetReserveFactorBoundsCheck();\\n }\\n\\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\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 actualAddAmount The actual amount added, excluding the potential token fees\\n */\\n function _addReservesFresh(uint256 addAmount) internal returns (uint256) {\\n // totalReserves + actualAddAmount\\n uint256 totalReservesNew;\\n uint256 actualAddAmount;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert AddReservesFactorFreshCheck(actualAddAmount);\\n }\\n\\n actualAddAmount = _doTransferIn(msg.sender, addAmount);\\n totalReservesNew = totalReserves + actualAddAmount;\\n totalReserves = totalReservesNew;\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n return actualAddAmount;\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to the protocol reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n */\\n function _reduceReservesFresh(uint256 reduceAmount) internal {\\n if (reduceAmount == 0) {\\n return;\\n }\\n // totalReserves - reduceAmount\\n uint256 totalReservesNew;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert ReduceReservesFreshCheck();\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (_getCashPrior() < reduceAmount) {\\n revert ReduceReservesCashNotAvailable();\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n revert ReduceReservesCashValidation();\\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 // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, reduceAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit SpreadReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal {\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert SetInterestRateModelFreshCheck();\\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\\n /**\\n * Safe Token **\\n */\\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 returns (uint256) {\\n IERC20Upgradeable token = IERC20Upgradeable(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 to, uint256 amount) internal virtual {\\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\\n token.safeTransfer(to, amount);\\n }\\n\\n /**\\n * @notice Transfer `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 */\\n function _transferTokens(address spender, address src, address dst, uint256 tokens) internal {\\n /* Fail if transfer not allowed */\\n comptroller.preTransferHook(address(this), src, dst, tokens);\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n revert TransferNotAllowed();\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint256 startingAllowance;\\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 uint256 allowanceNew = startingAllowance - tokens;\\n uint256 srcTokensNew = accountTokens[src] - tokens;\\n uint256 dstTokensNew = accountTokens[dst] + tokens;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n\\n accountTokens[src] = srcTokensNew;\\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\\n /**\\n * @notice Initialize the 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_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n */\\n function _initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\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 _setComptroller(comptroller_);\\n\\n // Initialize slot(block or second) number and borrow index (slot(block or second) number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumberOrTimestamp();\\n borrowIndex = MANTISSA_ONE;\\n\\n // Set the interest rate model (depends on slot(block or second) number / borrow index)\\n _setInterestRateModelFresh(interestRateModel_);\\n\\n _setReserveFactorFresh(reserveFactorMantissa_);\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n _setShortfallContract(riskManagement.shortfall);\\n _setProtocolShareReserve(riskManagement.protocolShareReserve);\\n protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA;\\n\\n // Set underlying and sanity check it\\n underlying = underlying_;\\n IERC20Upgradeable(underlying).totalSupply();\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n _transferOwnership(admin_);\\n }\\n\\n function _setShortfallContract(address shortfall_) internal {\\n ensureNonzeroAddress(shortfall_);\\n address oldShortfall = shortfall;\\n shortfall = shortfall_;\\n emit NewShortfallContract(oldShortfall, shortfall_);\\n }\\n\\n function _setProtocolShareReserve(address payable protocolShareReserve_) internal {\\n ensureNonzeroAddress(protocolShareReserve_);\\n address oldProtocolShareReserve = address(protocolShareReserve);\\n protocolShareReserve = protocolShareReserve_;\\n emit NewProtocolShareReserve(oldProtocolShareReserve, address(protocolShareReserve_));\\n }\\n\\n function _ensureSenderIsDelegateOf(address user) internal view {\\n if (!ComptrollerViewInterface(address(comptroller)).approvedDelegates(user, msg.sender)) {\\n revert DelegateNotApproved();\\n }\\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 virtual returns (uint256) {\\n return IERC20Upgradeable(underlying).balanceOf(address(this));\\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 borrowBalance the calculated balance\\n */\\n function _borrowBalanceStored(address account) internal view returns (uint256) {\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot memory 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 0;\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;\\n\\n return principalTimesIndex / borrowSnapshot.interestIndex;\\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 exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function _exchangeRateStored() internal view virtual returns (uint256) {\\n uint256 _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return initialExchangeRateMantissa;\\n }\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply\\n */\\n uint256 totalCash = _getCashPrior();\\n uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;\\n uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply;\\n\\n return exchangeRate;\\n }\\n}\\n\",\"keccak256\":\"0xa220ca317fe69b920b86e43f054c43b5f891f12160fd312c9a21668f969ee056\",\"license\":\"BSD-3-Clause\"},\"contracts/VTokenInterfaces.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\\nimport { ComptrollerInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title VTokenStorage\\n * @author Venus\\n * @notice Storage layout used by the `VToken` contract\\n */\\n// solhint-disable-next-line max-states-count\\ncontract VTokenStorage {\\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 uint256 principal;\\n uint256 interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\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 Protocol share Reserve contract address\\n */\\n address payable public protocolShareReserve;\\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 InterestRateModel public interestRateModel;\\n\\n // Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n uint256 internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint256 public reserveFactorMantissa;\\n\\n /**\\n * @notice Slot(block or second) number that interest was last accrued at\\n */\\n uint256 public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint256 public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint256 public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint256 public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint256 public totalSupply;\\n\\n /**\\n * @notice Total bad debt of the market\\n */\\n uint256 public badDebt;\\n\\n // Official record of token balances for each account\\n mapping(address => uint256) internal accountTokens;\\n\\n // Approved token transfer amounts on behalf of others\\n mapping(address => mapping(address => uint256)) internal transferAllowances;\\n\\n // Mapping of account addresses to outstanding borrow balances\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint256 public protocolSeizeShareMantissa;\\n\\n /**\\n * @notice Storage of Shortfall contract address\\n */\\n address public shortfall;\\n\\n /**\\n * @notice delta slot (block or second) after which reserves will be reduced\\n */\\n uint256 public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last slot (block or second) number at which reserves were reduced\\n */\\n uint256 public reduceReservesBlockNumber;\\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\\n/**\\n * @title VTokenInterface\\n * @author Venus\\n * @notice Interface implemented by the `VToken` contract\\n */\\nabstract contract VTokenInterface is VTokenStorage {\\n struct RiskManagementInit {\\n address shortfall;\\n address payable protocolShareReserve;\\n }\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address indexed minter, uint256 mintAmount, uint256 mintTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address indexed borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(\\n address indexed payer,\\n address indexed borrower,\\n uint256 repayAmount,\\n uint256 accountBorrows,\\n uint256 totalBorrows\\n );\\n\\n /**\\n * @notice Event emitted when bad debt is accumulated on a market\\n * @param borrower borrower to \\\"forgive\\\"\\n * @param badDebtDelta amount of new bad debt recorded\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtIncreased(address indexed borrower, uint256 badDebtDelta, uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when bad debt is recovered via an auction\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtRecovered(uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address indexed liquidator,\\n address indexed borrower,\\n uint256 repayAmount,\\n address indexed vTokenCollateral,\\n uint256 seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface indexed oldComptroller, ComptrollerInterface indexed newComptroller);\\n\\n /**\\n * @notice Event emitted when shortfall contract address is changed\\n */\\n event NewShortfallContract(address indexed oldShortfall, address indexed newShortfall);\\n\\n /**\\n * @notice Event emitted when protocol share reserve contract address is changed\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModel indexed oldInterestRateModel,\\n InterestRateModel indexed newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when protocol seize share is changed\\n */\\n event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address indexed benefactor, uint256 addAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the spread reserves are reduced\\n */\\n event SpreadReservesReduced(address indexed protocolShareReserve, uint256 reduceAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /**\\n * @notice Event emitted when healing the borrow\\n */\\n event HealBorrow(address indexed payer, address indexed borrower, uint256 repayAmount);\\n\\n /**\\n * @notice Event emitted when tokens are swept\\n */\\n event SweepToken(address indexed token);\\n\\n /**\\n * @notice Event emitted when reduce reserves slot (block or second) delta is changed\\n */\\n event NewReduceReservesBlockDelta(\\n uint256 oldReduceReservesBlockOrTimestampDelta,\\n uint256 newReduceReservesBlockOrTimestampDelta\\n );\\n\\n /**\\n * @notice Event emitted when liquidation reserves are reduced\\n */\\n event ProtocolSeize(address indexed from, address indexed to, uint256 amount);\\n\\n /*** User Interface ***/\\n\\n function mint(uint256 mintAmount) external virtual returns (uint256);\\n\\n function mintBehalf(address minter, uint256 mintAllowed) external virtual returns (uint256);\\n\\n function redeem(uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemBehalf(address redeemer, uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);\\n\\n function redeemUnderlyingBehalf(address redeemer, uint256 redeemAmount) external virtual returns (uint256);\\n\\n function borrow(uint256 borrowAmount) external virtual returns (uint256);\\n\\n function borrowBehalf(address borrwwer, uint256 borrowAmount) external virtual returns (uint256);\\n\\n function repayBorrow(uint256 repayAmount) external virtual returns (uint256);\\n\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external virtual returns (uint256);\\n\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external virtual;\\n\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipCloseFactorCheck\\n ) external virtual;\\n\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external virtual;\\n\\n function transfer(address dst, uint256 amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint256 amount) external virtual returns (bool);\\n\\n function accrueInterest() external virtual returns (uint256);\\n\\n function sweepToken(IERC20Upgradeable token) external virtual;\\n\\n /*** Admin Functions ***/\\n\\n function setReserveFactor(uint256 newReserveFactorMantissa) external virtual;\\n\\n function reduceReserves(uint256 reduceAmount) external virtual;\\n\\n function exchangeRateCurrent() external virtual returns (uint256);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint256);\\n\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external virtual;\\n\\n function addReserves(uint256 addAmount) external virtual;\\n\\n function totalBorrowsCurrent() external virtual returns (uint256);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint256);\\n\\n function approve(address spender, uint256 amount) external virtual returns (bool);\\n\\n function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool);\\n\\n function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint256);\\n\\n function balanceOf(address owner) external view virtual returns (uint256);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint256, uint256, uint256, uint256);\\n\\n function borrowRatePerBlock() external view virtual returns (uint256);\\n\\n function supplyRatePerBlock() external view virtual returns (uint256);\\n\\n function borrowBalanceStored(address account) external view virtual returns (uint256);\\n\\n function exchangeRateStored() external view virtual returns (uint256);\\n\\n function getCash() external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is a VToken contract (for inspection)\\n * @return Always true\\n */\\n function isVToken() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x7c4cbb879e3a931cfee4fa7a9eb1978eddff18087a1c4f56decedb84c2479f1e\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\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\",\"keccak256\":\"0x54ab3a6f3bc87569ed12370f3470a1ec84cea9796d4d0ccf3d07dd4280c044aa\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/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 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\",\"keccak256\":\"0x93bdd5cfb100f0f9a1d446857e23c3633df6ab12c266333c978428edd96b1367\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x60e060405234801561001057600080fd5b5060405161406e38038061406e83398101604081905261002f916100dc565b81818115801561003d575080155b1561005b576040516302723dfb60e21b815260040160405180910390fd5b81801561006757508015155b156100855760405163ae0fcab360e01b815260040160405180910390fd5b81151560a05281610096578061009c565b6301e133805b608052816100b3576100d460201b611dfb176100be565b6100d860201b611dff175b6001600160401b031660c0525061010f92505050565b4390565b4290565b600080604083850312156100ef57600080fd5b825180151581146100ff57600080fd5b6020939093015192949293505050565b60805160a05160c051613f296101456000396000611dcf0152600081816102a60152611ed0015260006101d10152613f296000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c80637c51b64211610097578063c7ad089511610066578063c7ad0895146102a1578063d77ebf96146102d8578063e0a67f11146102f8578063e1d146fb1461031857600080fd5b80637c51b642146102215780637c84e3b314610241578063aa5dbd2314610261578063b31242391461028157600080fd5b806347d86a81116100d357806347d86a811461018e57806355dd9515146101a15780636857249c146101cc5780637a27db571461020157600080fd5b80630d3ae318146101055780631f884fdf1461012e578063345954dc1461014e5780633e3e399c1461016e575b600080fd5b610118610113366004612f40565b610320565b60405161012591906132ad565b60405180910390f35b61014161013c36600461330b565b610655565b604051610125919061334c565b61016161015c3660046133ac565b61071d565b60405161012591906133c9565b61018161017c3660046133ac565b610850565b604051610125919061342d565b61011861019c3660046134b7565b610bc2565b6101b46101af3660046134f0565b610c49565b6040516001600160a01b039091168152602001610125565b6101f37f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610125565b61021461020f3660046134b7565b610cc9565b604051610125919061353b565b61023461022f366004613617565b610fd6565b60405161012591906136a2565b61025461024f3660046133ac565b61108f565b60405161012591906136f0565b61027461026f3660046133ac565b6111f9565b6040516101259190613710565b61029461028f3660046134b7565b6119b9565b604051610125919061371f565b6102c87f000000000000000000000000000000000000000000000000000000000000000081565b6040519015158152602001610125565b6102eb6102e63660046134b7565b611ca0565b604051610125919061372d565b61030b610306366004613791565b611d13565b604051610125919061382a565b6101f3611dc8565b610328612d07565b6000826040015190506000816001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610371573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610399919081019061386d565b905060006103a682611d13565b60408681015190516328ebbe8b60e21b81526001600160a01b039182166004820152919250879160009183169063a3aefa2c90602401600060405180830381865afa1580156103f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526104219190810190613940565b90506000876040015190506000604051806101a001604052808a6000015181526020018a602001516001600160a01b031681526020018a604001516001600160a01b031681526020018a6060015181526020018a608001518152602001846000015181526020018460200151815260200184604001518152602001836001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104fe91906139f4565b6001600160a01b03168152602001836001600160a01b031663e87554466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561054a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061056e9190613a11565b8152602001836001600160a01b0316634ada90af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d59190613a11565b8152602001836001600160a01b031663db5c65de6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610618573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063c9190613a11565b8152602001959095525092955050505050505b92915050565b6060816000816001600160401b0381111561067257610672612e89565b6040519080825280602002602001820160405280156106b757816020015b60408051808201909152600080825260208201528152602001906001900390816106905790505b50905060005b82811015610714576106ef8686838181106106da576106da613a2a565b905060200201602081019061024f91906133ac565b82828151811061070157610701613a2a565b60209081029190910101526001016106bd565b50949350505050565b606060008290506000816001600160a01b031663d88ff1f46040518163ffffffff1660e01b8152600401600060405180830381865afa158015610764573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261078c9190810190613ac3565b80519091506000816001600160401b038111156107ab576107ab612e89565b6040519080825280602002602001820160405280156107e457816020015b6107d1612d07565b8152602001906001900390816107c95790505b50905060005b8281101561084657600084828151811061080657610806613a2a565b60200260200101519050600061081c8983610320565b90508084848151811061083157610831613a2a565b602090810291909101015250506001016107ea565b5095945050505050565b604080516060808201835260008083526020830152918101919091526000808390506000816001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156108b2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108da919081019061386d565b90506000826001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561091c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094091906139f4565b9050600082516001600160401b0381111561095d5761095d612e89565b6040519080825280602002602001820160405280156109a257816020015b604080518082019091526000808252602082015281526020019060019003908161097b5790505b5090506109d2604051806060016040528060006001600160a01b0316815260200160008152602001606081525090565b6001600160a01b03881681526040810182905260005b8451811015610bae576040805180820190915260008082526020820152858281518110610a1757610a17613a2a565b602002602001015181600001906001600160a01b031690816001600160a01b031681525050670de0b6b3a7640000856001600160a01b031663fc57d4df888581518110610a6657610a66613a2a565b60200260200101516040518263ffffffff1660e01b8152600401610a9991906001600160a01b0391909116815260200190565b602060405180830381865afa158015610ab6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ada9190613a11565b878481518110610aec57610aec613a2a565b60200260200101516001600160a01b031663bbcac5576040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b559190613a11565b610b5f9190613b89565b610b699190613ba0565b60208201526040830151805182919084908110610b8857610b88613a2a565b6020026020010181905250806020015188610ba39190613bc2565b9750506001016109e8565b506020810195909552509295945050505050565b610bca612d07565b604051637aee632d60e01b81526001600160a01b0383811660048301528491610c4191839190821690637aee632d90602401600060405180830381865afa158015610c19573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526101139190810190613bd5565b949350505050565b60405163266e0a7f60e01b81526001600160a01b0383811660048301528281166024830152600091859182169063266e0a7f90604401602060405180830381865afa158015610c9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc091906139f4565b95945050505050565b60606000826001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610d0b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d33919081019061386d565b90506000836001600160a01b03166361252fd16040518163ffffffff1660e01b8152600401600060405180830381865afa158015610d75573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d9d9190810190613c09565b9050600081516001600160401b03811115610dba57610dba612e89565b604051908082528060200260200182016040528015610e0b57816020015b6040805160808101825260008082526020808301829052928201526060808201528252600019909201910181610dd85790505b50905060005b8251811015610846576040805160808101825260008082526020820181905291810191909152606080820152838281518110610e4f57610e4f613a2a565b60209081029190910101516001600160a01b031681528351849083908110610e7957610e79613a2a565b60200260200101516001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ebe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee291906139f4565b6001600160a01b031660208201528351849083908110610f0457610f04613a2a565b6020908102919091010151604051631627ee8960e01b81526001600160a01b038a8116600483015290911690631627ee8990602401602060405180830381865afa158015610f56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7a9190613a11565b816040018181525050610fa78886868581518110610f9a57610f9a613a2a565b6020026020010151611e03565b816060018190525080838381518110610fc257610fc2613a2a565b602090810291909101015250600101610e11565b6060826000816001600160401b03811115610ff357610ff3612e89565b60405190808252806020026020018201604052801561102c57816020015b611019612d8a565b8152602001906001900390816110115790505b50905060005b828110156108465761106a87878381811061104f5761104f613a2a565b905060200201602081019061106491906133ac565b866119b9565b82828151811061107c5761107c613a2a565b6020908102919091010152600101611032565b60408051808201909152600080825260208201526000826001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110e3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110791906139f4565b90506000816001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611149573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116d91906139f4565b6040805180820182526001600160a01b03808816808352925163fc57d4df60e01b815260048101939093529293509160208301919084169063fc57d4df90602401602060405180830381865afa1580156111cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ef9190613a11565b9052949350505050565b611201612dc9565b6000826001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611241573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112659190613a11565b90506000836001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cb91906139f4565b604051638e8f294b60e01b81526001600160a01b03868116600483015291925082916000918291841690638e8f294b906024016040805180830381865afa15801561131a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133e9190613ca7565b915091506000876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a691906139f4565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061140c9190613cd3565b60ff1690506000805b600860ff8216116114d2576000886001600160a01b031663e85a29608d8460ff16600881111561144757611447613cf6565b6040518363ffffffff1660e01b8152600401611464929190613d0c565b602060405180830381865afa158015611481573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a59190613d47565b6114b05760006114b3565b60015b60ff9081169083161b9290921791506114cb81613d62565b9050611415565b506000808b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611514573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115389190613a11565b11156115a3578a6001600160a01b031663ae9d70b06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561157c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a09190613a11565b90505b6040518061022001604052808c6001600160a01b031681526020018a81526020018281526020018c6001600160a01b031663f8f9da286040518163ffffffff1660e01b8152600401602060405180830381865afa158015611608573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061162c9190613a11565b81526020018c6001600160a01b031663173b99046040518163ffffffff1660e01b8152600401602060405180830381865afa15801561166f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116939190613a11565b81526040516302c3bcbb60e01b81526001600160a01b038e811660048301526020909201918a16906302c3bcbb90602401602060405180830381865afa1580156116e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117059190613a11565b815260405163252c221960e11b81526001600160a01b038e811660048301526020909201918a1690634a58443290602401602060405180830381865afa158015611753573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117779190613a11565b81526020018c6001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117de9190613a11565b81526020018c6001600160a01b0316638f840ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611821573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118459190613a11565b81526020018c6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611888573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ac9190613a11565b81526020018c6001600160a01b0316633b1d21a26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119139190613a11565b81526020018715158152602001868152602001856001600160a01b031681526020018c6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611973573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119979190613cd3565b60ff168152602001848152602001838152509950505050505050505050919050565b6119c1612d8a565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908516906370a0823190602401602060405180830381865afa158015611a0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a2f9190613a11565b6040516305eff7ef60e21b81526001600160a01b0385811660048301529192506000918616906317bfdfbc906024016020604051808303816000875af1158015611a7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa19190613a11565b604051633af9e66960e01b81526001600160a01b038681166004830152919250600091871690633af9e669906024016020604051808303816000875af1158015611aef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b139190613a11565b90506000806000886001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b7c91906139f4565b6040516370a0823160e01b81526001600160a01b038a81166004830152919250908216906370a0823190602401602060405180830381865afa158015611bc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bea9190613a11565b604051636eb1769f60e11b81526001600160a01b038a811660048301528b811660248301529194509082169063dd62ed3e90604401602060405180830381865afa158015611c3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c609190613a11565b6040805160c0810182526001600160a01b038c168152602081019890985287019590955250506060840191909152608083015260a0820152905092915050565b604051631e6db74760e31b81526001600160a01b038281166004830152606091849182169063f36dba3890602401600060405180830381865afa158015611ceb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c419190810190613d81565b80516060906000816001600160401b03811115611d3257611d32612e89565b604051908082528060200260200182016040528015611d6b57816020015b611d58612dc9565b815260200190600190039081611d505790505b50905060005b82811015611dc057611d9b858281518110611d8e57611d8e613a2a565b60200260200101516111f9565b828281518110611dad57611dad613a2a565b6020908102919091010152600101611d71565b509392505050565b6000611df67f000000000000000000000000000000000000000000000000000000000000000063ffffffff16565b905090565b4390565b4290565b6060600083516001600160401b03811115611e2057611e20612e89565b604051908082528060200260200182016040528015611e6557816020015b6040805180820190915260008082526020820152815260200190600190039081611e3e5790505b50905060005b845181101561071457611ea1604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b611ece604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b7f00000000000000000000000000000000000000000000000000000000000000001561205157856001600160a01b0316638f693ec7888581518110611f1557611f15613a2a565b60200260200101516040518263ffffffff1660e01b8152600401611f4891906001600160a01b0391909116815260200190565b606060405180830381865afa158015611f65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f899190613e26565b604085015260208401526001600160e01b0316825286516001600160a01b03871690638181494590899086908110611fc357611fc3613a2a565b60200260200101516040518263ffffffff1660e01b8152600401611ff691906001600160a01b0391909116815260200190565b606060405180830381865afa158015612013573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120379190613e26565b604084015260208301526001600160e01b031681526121bc565b856001600160a01b0316632c427b5788858151811061207257612072613a2a565b60200260200101516040518263ffffffff1660e01b81526004016120a591906001600160a01b0391909116815260200190565b606060405180830381865afa1580156120c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e69190613e6f565b63ffffffff90811660408601521660208401526001600160e01b0316825286516001600160a01b038716906392a182359089908690811061212957612129613a2a565b60200260200101516040518263ffffffff1660e01b815260040161215c91906001600160a01b0391909116815260200190565b606060405180830381865afa158015612179573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061219d9190613e6f565b63ffffffff90811660408501521660208301526001600160e01b031681525b600060405180602001604052808986815181106121db576121db613a2a565b60200260200101516001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612220573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122449190613a11565b815250905061226e88858151811061225e5761225e613a2a565b6020026020010151888584612363565b61229288858151811061228357612283613a2a565b60200260200101518884612564565b60006122ba8986815181106122a9576122a9613a2a565b6020026020010151898c878661275b565b905060006122e38a87815181106122d3576122d3613a2a565b60200260200101518a8d8761298b565b60408051808201909152600080825260208201529091508a878151811061230c5761230c613a2a565b60209081029190910101516001600160a01b0316815261232c8284613bc2565b60208201528751819089908990811061234757612347613a2a565b6020026020010181905250505050505050806001019050611e6b565b604051637c05a7c560e01b81526001600160a01b03858116600483015260009190851690637c05a7c590602401602060405180830381865afa1580156123ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123d19190613a11565b905060006123dd611dc8565b9050600084604001511180156123f65750836040015181115b15612402575060408301515b6000612412828660200151612baf565b90506000811180156124245750600083115b1561254d576000612496886001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561246c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124909190613a11565b86612bc2565b905060006124a48386612be0565b905060008083116124c457604051806020016040528060008152506124ce565b6124ce8284612bec565b905060006124f760405180602001604052808b600001516001600160e01b031681525083612c31565b90506125328160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612c5d565b6001600160e01b03168952505050506020850182905261255b565b801561255b57602085018290525b50505050505050565b604051631d31307360e21b81526001600160a01b038481166004830152600091908416906374c4c1cc90602401602060405180830381865afa1580156125ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125d29190613a11565b905060006125de611dc8565b9050600083604001511180156125f75750826040015181115b15612603575060408201515b6000612613828560200151612baf565b90506000811180156126255750600083115b15612745576000866001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561266a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061268e9190613a11565b9050600061269c8386612be0565b905060008083116126bc57604051806020016040528060008152506126c6565b6126c68284612bec565b905060006126ef60405180602001604052808a600001516001600160e01b031681525083612c31565b905061272a8160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612c5d565b6001600160e01b031688525050505060208401829052612753565b801561275357602084018290525b505050505050565b604080516020808201835284516001600160e01b031682528251908101928390526336fe846560e11b9092526001600160a01b0387811660248401528581166044840152600092839181908916636dfd08ca60648301602060405180830381865afa1580156127ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f29190613a11565b905280519091501580156128745750866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa15801561283f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128639190613eb2565b6001600160e01b0316826000015110155b156128e757866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128db9190613eb2565b6001600160e01b031681525b60006128f38383612c99565b6040516395dd919360e01b81526001600160a01b03898116600483015291925060009161296e91908c16906395dd919390602401602060405180830381865afa158015612944573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129689190613a11565b87612bc2565b9050600061297c8284612cc5565b9b9a5050505050505050505050565b604080516020808201835283516001600160e01b0316825282519081019283905263552c097160e01b9092526001600160a01b038681166024840152848116604484015260009283918190881663552c097160648301602060405180830381865afa1580156129fe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a229190613a11565b90528051909150158015612aa45750856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a939190613eb2565b6001600160e01b0316826000015110155b15612b1757856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ae7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b0b9190613eb2565b6001600160e01b031681525b6000612b238383612c99565b6040516370a0823160e01b81526001600160a01b0388811660048301529192506000918a16906370a0823190602401602060405180830381865afa158015612b6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b939190613a11565b90506000612ba18284612cc5565b9a9950505050505050505050565b6000612bbb8284613ecd565b9392505050565b6000612bbb612bd984670de0b6b3a7640000612be0565b8351612cef565b6000612bbb8284613b89565b6040805160208101909152600081526040518060200160405280612c28612c22866ec097ce7bc90715b34b9f1000000000612be0565b85612cef565b90529392505050565b6040805160208101909152600081526040518060200160405280612c2885600001518560000151612cfb565b6000816001600160e01b03841115612c915760405162461bcd60e51b8152600401612c889190613ee0565b60405180910390fd5b509192915050565b6040805160208101909152600081526040518060200160405280612c2885600001518560000151612baf565b60006ec097ce7bc90715b34b9f1000000000612ce5848460000151612be0565b612bbb9190613ba0565b6000612bbb8284613ba0565b6000612bbb8284613bc2565b604051806101a001604052806060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160608152602001606081526020016060815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001606081525090565b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180610220016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b6001600160a01b0381168114612e7657600080fd5b50565b8035612e8481612e61565b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715612ec157612ec1612e89565b60405290565b604051606081016001600160401b0381118282101715612ec157612ec1612e89565b604051601f8201601f191681016001600160401b0381118282101715612f1157612f11612e89565b604052919050565b60006001600160401b03821115612f3257612f32612e89565b50601f01601f191660200190565b60008060408385031215612f5357600080fd5b8235612f5e81612e61565b91506020838101356001600160401b0380821115612f7b57600080fd5b9085019060a08288031215612f8f57600080fd5b612f97612e9f565b823582811115612fa657600080fd5b83019150601f82018813612fb957600080fd5b8135612fcc612fc782612f19565b612ee9565b8181528986838601011115612fe057600080fd5b818685018783013760008683830101528083525050613000848401612e79565b8482015261301060408401612e79565b60408201526060830135606082015260808301356080820152809450505050509250929050565b60005b8381101561305257818101518382015260200161303a565b50506000910152565b60008151808452613073816020860160208601613037565b601f01601f19169290920160200192915050565b80516001600160a01b031682526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e0830152610100808201518184015250610120808201518184015250610140808201518184015250610160808201516131128285018215159052565b505061018081810151908301526101a0808201516001600160a01b0316908301526101c080820151908301526101e0808201519083015261020090810151910152565b60008151808452602080850194506020840160005b838110156131915761317d878351613087565b61022096909601959082019060010161316a565b509495945050505050565b60006101a082518185526131b28286018261305b565b91505060208301516131cf60208601826001600160a01b03169052565b5060408301516131ea60408601826001600160a01b03169052565b50606083015160608501526080830151608085015260a083015184820360a0860152613216828261305b565b91505060c083015184820360c0860152613230828261305b565b91505060e083015184820360e086015261324a828261305b565b91505061010080840151613268828701826001600160a01b03169052565b505061012083810151908501526101408084015190850152610160808401519085015261018080840151858303828701526132a38382613155565b9695505050505050565b602081526000612bbb602083018461319c565b60008083601f8401126132d257600080fd5b5081356001600160401b038111156132e957600080fd5b6020830191508360208260051b850101111561330457600080fd5b9250929050565b6000806020838503121561331e57600080fd5b82356001600160401b0381111561333457600080fd5b613340858286016132c0565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b8281101561339f5761338f84835180516001600160a01b03168252602090810151910152565b9284019290850190600101613369565b5091979650505050505050565b6000602082840312156133be57600080fd5b8135612bbb81612e61565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561342057603f1988860301845261340e85835161319c565b945092850192908501906001016133f2565b5092979650505050505050565b602080825282516001600160a01b03168282015282810151604080840191909152808401516060808501528051608085018190526000939291830191849160a08701905b808410156134ab5761349782865180516001600160a01b03168252602090810151910152565b938501936001939093019290820190613471565b50979650505050505050565b600080604083850312156134ca57600080fd5b82356134d581612e61565b915060208301356134e581612e61565b809150509250929050565b60008060006060848603121561350557600080fd5b833561351081612e61565b9250602084013561352081612e61565b9150604084013561353081612e61565b809150509250925092565b600060208083018184528085518083526040925060408601915060408160051b8701018488016000805b8481101561360857898403603f19018652825180516001600160a01b03908116865289820151168986015287810151888601526060908101516080918601829052805191860182905289019060a086019084905b808210156135f3576135df83855180516001600160a01b03168252602090810151910152565b928b0192918a0191600191909101906135b9565b50509689019694505091870191600101613565565b50919998505050505050505050565b60008060006040848603121561362c57600080fd5b83356001600160401b0381111561364257600080fd5b61364e868287016132c0565b909450925050602084013561353081612e61565b80516001600160a01b031682526020808201519083015260408082015190830152606080820151908301526080808201519083015260a090810151910152565b6020808252825182820181905260009190848201906040850190845b818110156136e4576136d1838551613662565b9284019260c092909201916001016136be565b50909695505050505050565b81516001600160a01b03168152602080830151908201526040810161064f565b610220810161064f8284613087565b60c0810161064f8284613662565b6020808252825182820181905260009190848201906040850190845b818110156136e45783516001600160a01b031683529284019291840191600101613749565b60006001600160401b0382111561378757613787612e89565b5060051b60200190565b600060208083850312156137a457600080fd5b82356001600160401b038111156137ba57600080fd5b8301601f810185136137cb57600080fd5b80356137d9612fc78261376e565b81815260059190911b820183019083810190878311156137f857600080fd5b928401925b8284101561381f57833561381081612e61565b825292840192908401906137fd565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156136e457613859838551613087565b928401926102209290920191600101613846565b6000602080838503121561388057600080fd5b82516001600160401b0381111561389657600080fd5b8301601f810185136138a757600080fd5b80516138b5612fc78261376e565b81815260059190911b820183019083810190878311156138d457600080fd5b928401925b8284101561381f5783516138ec81612e61565b825292840192908401906138d9565b600082601f83011261390c57600080fd5b815161391a612fc782612f19565b81815284602083860101111561392f57600080fd5b610c41826020830160208701613037565b60006020828403121561395257600080fd5b81516001600160401b038082111561396957600080fd5b908301906060828603121561397d57600080fd5b613985612ec7565b82518281111561399457600080fd5b6139a0878286016138fb565b8252506020830151828111156139b557600080fd5b6139c1878286016138fb565b6020830152506040830151828111156139d957600080fd5b6139e5878286016138fb565b60408301525095945050505050565b600060208284031215613a0657600080fd5b8151612bbb81612e61565b600060208284031215613a2357600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600060a08284031215613a5257600080fd5b613a5a612e9f565b905081516001600160401b03811115613a7257600080fd5b613a7e848285016138fb565b8252506020820151613a8f81612e61565b60208201526040820151613aa281612e61565b80604083015250606082015160608201526080820151608082015292915050565b60006020808385031215613ad657600080fd5b82516001600160401b0380821115613aed57600080fd5b818501915085601f830112613b0157600080fd5b8151613b0f612fc78261376e565b81815260059190911b83018401908481019088831115613b2e57600080fd5b8585015b83811015613b6657805185811115613b4a5760008081fd5b613b588b89838a0101613a40565b845250918601918601613b32565b5098975050505050505050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761064f5761064f613b73565b600082613bbd57634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561064f5761064f613b73565b600060208284031215613be757600080fd5b81516001600160401b03811115613bfd57600080fd5b610c4184828501613a40565b60006020808385031215613c1c57600080fd5b82516001600160401b03811115613c3257600080fd5b8301601f81018513613c4357600080fd5b8051613c51612fc78261376e565b81815260059190911b82018301908381019087831115613c7057600080fd5b928401925b8284101561381f578351613c8881612e61565b82529284019290840190613c75565b80518015158114612e8457600080fd5b60008060408385031215613cba57600080fd5b613cc383613c97565b9150602083015190509250929050565b600060208284031215613ce557600080fd5b815160ff81168114612bbb57600080fd5b634e487b7160e01b600052602160045260246000fd5b6001600160a01b03831681526040810160098310613d3a57634e487b7160e01b600052602160045260246000fd5b8260208301529392505050565b600060208284031215613d5957600080fd5b612bbb82613c97565b600060ff821660ff8103613d7857613d78613b73565b60010192915050565b60006020808385031215613d9457600080fd5b82516001600160401b03811115613daa57600080fd5b8301601f81018513613dbb57600080fd5b8051613dc9612fc78261376e565b81815260059190911b82018301908381019087831115613de857600080fd5b928401925b8284101561381f578351613e0081612e61565b82529284019290840190613ded565b80516001600160e01b0381168114612e8457600080fd5b600080600060608486031215613e3b57600080fd5b613e4484613e0f565b925060208401519150604084015190509250925092565b805163ffffffff81168114612e8457600080fd5b600080600060608486031215613e8457600080fd5b613e8d84613e0f565b9250613e9b60208501613e5b565b9150613ea960408501613e5b565b90509250925092565b600060208284031215613ec457600080fd5b612bbb82613e0f565b8181038181111561064f5761064f613b73565b602081526000612bbb602083018461305b56fea26469706673582212208dc9fbc3de84a5eadf5a8d0d7d030c880d5f4a9665121e956562816524e6c89964736f6c63430008190033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101005760003560e01c80637c51b64211610097578063c7ad089511610066578063c7ad0895146102a1578063d77ebf96146102d8578063e0a67f11146102f8578063e1d146fb1461031857600080fd5b80637c51b642146102215780637c84e3b314610241578063aa5dbd2314610261578063b31242391461028157600080fd5b806347d86a81116100d357806347d86a811461018e57806355dd9515146101a15780636857249c146101cc5780637a27db571461020157600080fd5b80630d3ae318146101055780631f884fdf1461012e578063345954dc1461014e5780633e3e399c1461016e575b600080fd5b610118610113366004612f40565b610320565b60405161012591906132ad565b60405180910390f35b61014161013c36600461330b565b610655565b604051610125919061334c565b61016161015c3660046133ac565b61071d565b60405161012591906133c9565b61018161017c3660046133ac565b610850565b604051610125919061342d565b61011861019c3660046134b7565b610bc2565b6101b46101af3660046134f0565b610c49565b6040516001600160a01b039091168152602001610125565b6101f37f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610125565b61021461020f3660046134b7565b610cc9565b604051610125919061353b565b61023461022f366004613617565b610fd6565b60405161012591906136a2565b61025461024f3660046133ac565b61108f565b60405161012591906136f0565b61027461026f3660046133ac565b6111f9565b6040516101259190613710565b61029461028f3660046134b7565b6119b9565b604051610125919061371f565b6102c87f000000000000000000000000000000000000000000000000000000000000000081565b6040519015158152602001610125565b6102eb6102e63660046134b7565b611ca0565b604051610125919061372d565b61030b610306366004613791565b611d13565b604051610125919061382a565b6101f3611dc8565b610328612d07565b6000826040015190506000816001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610371573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610399919081019061386d565b905060006103a682611d13565b60408681015190516328ebbe8b60e21b81526001600160a01b039182166004820152919250879160009183169063a3aefa2c90602401600060405180830381865afa1580156103f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526104219190810190613940565b90506000876040015190506000604051806101a001604052808a6000015181526020018a602001516001600160a01b031681526020018a604001516001600160a01b031681526020018a6060015181526020018a608001518152602001846000015181526020018460200151815260200184604001518152602001836001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104fe91906139f4565b6001600160a01b03168152602001836001600160a01b031663e87554466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561054a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061056e9190613a11565b8152602001836001600160a01b0316634ada90af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d59190613a11565b8152602001836001600160a01b031663db5c65de6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610618573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063c9190613a11565b8152602001959095525092955050505050505b92915050565b6060816000816001600160401b0381111561067257610672612e89565b6040519080825280602002602001820160405280156106b757816020015b60408051808201909152600080825260208201528152602001906001900390816106905790505b50905060005b82811015610714576106ef8686838181106106da576106da613a2a565b905060200201602081019061024f91906133ac565b82828151811061070157610701613a2a565b60209081029190910101526001016106bd565b50949350505050565b606060008290506000816001600160a01b031663d88ff1f46040518163ffffffff1660e01b8152600401600060405180830381865afa158015610764573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261078c9190810190613ac3565b80519091506000816001600160401b038111156107ab576107ab612e89565b6040519080825280602002602001820160405280156107e457816020015b6107d1612d07565b8152602001906001900390816107c95790505b50905060005b8281101561084657600084828151811061080657610806613a2a565b60200260200101519050600061081c8983610320565b90508084848151811061083157610831613a2a565b602090810291909101015250506001016107ea565b5095945050505050565b604080516060808201835260008083526020830152918101919091526000808390506000816001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156108b2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108da919081019061386d565b90506000826001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561091c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094091906139f4565b9050600082516001600160401b0381111561095d5761095d612e89565b6040519080825280602002602001820160405280156109a257816020015b604080518082019091526000808252602082015281526020019060019003908161097b5790505b5090506109d2604051806060016040528060006001600160a01b0316815260200160008152602001606081525090565b6001600160a01b03881681526040810182905260005b8451811015610bae576040805180820190915260008082526020820152858281518110610a1757610a17613a2a565b602002602001015181600001906001600160a01b031690816001600160a01b031681525050670de0b6b3a7640000856001600160a01b031663fc57d4df888581518110610a6657610a66613a2a565b60200260200101516040518263ffffffff1660e01b8152600401610a9991906001600160a01b0391909116815260200190565b602060405180830381865afa158015610ab6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ada9190613a11565b878481518110610aec57610aec613a2a565b60200260200101516001600160a01b031663bbcac5576040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b559190613a11565b610b5f9190613b89565b610b699190613ba0565b60208201526040830151805182919084908110610b8857610b88613a2a565b6020026020010181905250806020015188610ba39190613bc2565b9750506001016109e8565b506020810195909552509295945050505050565b610bca612d07565b604051637aee632d60e01b81526001600160a01b0383811660048301528491610c4191839190821690637aee632d90602401600060405180830381865afa158015610c19573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526101139190810190613bd5565b949350505050565b60405163266e0a7f60e01b81526001600160a01b0383811660048301528281166024830152600091859182169063266e0a7f90604401602060405180830381865afa158015610c9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc091906139f4565b95945050505050565b60606000826001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610d0b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d33919081019061386d565b90506000836001600160a01b03166361252fd16040518163ffffffff1660e01b8152600401600060405180830381865afa158015610d75573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d9d9190810190613c09565b9050600081516001600160401b03811115610dba57610dba612e89565b604051908082528060200260200182016040528015610e0b57816020015b6040805160808101825260008082526020808301829052928201526060808201528252600019909201910181610dd85790505b50905060005b8251811015610846576040805160808101825260008082526020820181905291810191909152606080820152838281518110610e4f57610e4f613a2a565b60209081029190910101516001600160a01b031681528351849083908110610e7957610e79613a2a565b60200260200101516001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ebe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee291906139f4565b6001600160a01b031660208201528351849083908110610f0457610f04613a2a565b6020908102919091010151604051631627ee8960e01b81526001600160a01b038a8116600483015290911690631627ee8990602401602060405180830381865afa158015610f56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7a9190613a11565b816040018181525050610fa78886868581518110610f9a57610f9a613a2a565b6020026020010151611e03565b816060018190525080838381518110610fc257610fc2613a2a565b602090810291909101015250600101610e11565b6060826000816001600160401b03811115610ff357610ff3612e89565b60405190808252806020026020018201604052801561102c57816020015b611019612d8a565b8152602001906001900390816110115790505b50905060005b828110156108465761106a87878381811061104f5761104f613a2a565b905060200201602081019061106491906133ac565b866119b9565b82828151811061107c5761107c613a2a565b6020908102919091010152600101611032565b60408051808201909152600080825260208201526000826001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110e3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110791906139f4565b90506000816001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611149573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116d91906139f4565b6040805180820182526001600160a01b03808816808352925163fc57d4df60e01b815260048101939093529293509160208301919084169063fc57d4df90602401602060405180830381865afa1580156111cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ef9190613a11565b9052949350505050565b611201612dc9565b6000826001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611241573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112659190613a11565b90506000836001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cb91906139f4565b604051638e8f294b60e01b81526001600160a01b03868116600483015291925082916000918291841690638e8f294b906024016040805180830381865afa15801561131a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133e9190613ca7565b915091506000876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a691906139f4565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061140c9190613cd3565b60ff1690506000805b600860ff8216116114d2576000886001600160a01b031663e85a29608d8460ff16600881111561144757611447613cf6565b6040518363ffffffff1660e01b8152600401611464929190613d0c565b602060405180830381865afa158015611481573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a59190613d47565b6114b05760006114b3565b60015b60ff9081169083161b9290921791506114cb81613d62565b9050611415565b506000808b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611514573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115389190613a11565b11156115a3578a6001600160a01b031663ae9d70b06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561157c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a09190613a11565b90505b6040518061022001604052808c6001600160a01b031681526020018a81526020018281526020018c6001600160a01b031663f8f9da286040518163ffffffff1660e01b8152600401602060405180830381865afa158015611608573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061162c9190613a11565b81526020018c6001600160a01b031663173b99046040518163ffffffff1660e01b8152600401602060405180830381865afa15801561166f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116939190613a11565b81526040516302c3bcbb60e01b81526001600160a01b038e811660048301526020909201918a16906302c3bcbb90602401602060405180830381865afa1580156116e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117059190613a11565b815260405163252c221960e11b81526001600160a01b038e811660048301526020909201918a1690634a58443290602401602060405180830381865afa158015611753573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117779190613a11565b81526020018c6001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117de9190613a11565b81526020018c6001600160a01b0316638f840ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611821573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118459190613a11565b81526020018c6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611888573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ac9190613a11565b81526020018c6001600160a01b0316633b1d21a26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119139190613a11565b81526020018715158152602001868152602001856001600160a01b031681526020018c6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611973573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119979190613cd3565b60ff168152602001848152602001838152509950505050505050505050919050565b6119c1612d8a565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908516906370a0823190602401602060405180830381865afa158015611a0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a2f9190613a11565b6040516305eff7ef60e21b81526001600160a01b0385811660048301529192506000918616906317bfdfbc906024016020604051808303816000875af1158015611a7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa19190613a11565b604051633af9e66960e01b81526001600160a01b038681166004830152919250600091871690633af9e669906024016020604051808303816000875af1158015611aef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b139190613a11565b90506000806000886001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b7c91906139f4565b6040516370a0823160e01b81526001600160a01b038a81166004830152919250908216906370a0823190602401602060405180830381865afa158015611bc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bea9190613a11565b604051636eb1769f60e11b81526001600160a01b038a811660048301528b811660248301529194509082169063dd62ed3e90604401602060405180830381865afa158015611c3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c609190613a11565b6040805160c0810182526001600160a01b038c168152602081019890985287019590955250506060840191909152608083015260a0820152905092915050565b604051631e6db74760e31b81526001600160a01b038281166004830152606091849182169063f36dba3890602401600060405180830381865afa158015611ceb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c419190810190613d81565b80516060906000816001600160401b03811115611d3257611d32612e89565b604051908082528060200260200182016040528015611d6b57816020015b611d58612dc9565b815260200190600190039081611d505790505b50905060005b82811015611dc057611d9b858281518110611d8e57611d8e613a2a565b60200260200101516111f9565b828281518110611dad57611dad613a2a565b6020908102919091010152600101611d71565b509392505050565b6000611df67f000000000000000000000000000000000000000000000000000000000000000063ffffffff16565b905090565b4390565b4290565b6060600083516001600160401b03811115611e2057611e20612e89565b604051908082528060200260200182016040528015611e6557816020015b6040805180820190915260008082526020820152815260200190600190039081611e3e5790505b50905060005b845181101561071457611ea1604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b611ece604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b7f00000000000000000000000000000000000000000000000000000000000000001561205157856001600160a01b0316638f693ec7888581518110611f1557611f15613a2a565b60200260200101516040518263ffffffff1660e01b8152600401611f4891906001600160a01b0391909116815260200190565b606060405180830381865afa158015611f65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f899190613e26565b604085015260208401526001600160e01b0316825286516001600160a01b03871690638181494590899086908110611fc357611fc3613a2a565b60200260200101516040518263ffffffff1660e01b8152600401611ff691906001600160a01b0391909116815260200190565b606060405180830381865afa158015612013573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120379190613e26565b604084015260208301526001600160e01b031681526121bc565b856001600160a01b0316632c427b5788858151811061207257612072613a2a565b60200260200101516040518263ffffffff1660e01b81526004016120a591906001600160a01b0391909116815260200190565b606060405180830381865afa1580156120c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e69190613e6f565b63ffffffff90811660408601521660208401526001600160e01b0316825286516001600160a01b038716906392a182359089908690811061212957612129613a2a565b60200260200101516040518263ffffffff1660e01b815260040161215c91906001600160a01b0391909116815260200190565b606060405180830381865afa158015612179573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061219d9190613e6f565b63ffffffff90811660408501521660208301526001600160e01b031681525b600060405180602001604052808986815181106121db576121db613a2a565b60200260200101516001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612220573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122449190613a11565b815250905061226e88858151811061225e5761225e613a2a565b6020026020010151888584612363565b61229288858151811061228357612283613a2a565b60200260200101518884612564565b60006122ba8986815181106122a9576122a9613a2a565b6020026020010151898c878661275b565b905060006122e38a87815181106122d3576122d3613a2a565b60200260200101518a8d8761298b565b60408051808201909152600080825260208201529091508a878151811061230c5761230c613a2a565b60209081029190910101516001600160a01b0316815261232c8284613bc2565b60208201528751819089908990811061234757612347613a2a565b6020026020010181905250505050505050806001019050611e6b565b604051637c05a7c560e01b81526001600160a01b03858116600483015260009190851690637c05a7c590602401602060405180830381865afa1580156123ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123d19190613a11565b905060006123dd611dc8565b9050600084604001511180156123f65750836040015181115b15612402575060408301515b6000612412828660200151612baf565b90506000811180156124245750600083115b1561254d576000612496886001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561246c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124909190613a11565b86612bc2565b905060006124a48386612be0565b905060008083116124c457604051806020016040528060008152506124ce565b6124ce8284612bec565b905060006124f760405180602001604052808b600001516001600160e01b031681525083612c31565b90506125328160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612c5d565b6001600160e01b03168952505050506020850182905261255b565b801561255b57602085018290525b50505050505050565b604051631d31307360e21b81526001600160a01b038481166004830152600091908416906374c4c1cc90602401602060405180830381865afa1580156125ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125d29190613a11565b905060006125de611dc8565b9050600083604001511180156125f75750826040015181115b15612603575060408201515b6000612613828560200151612baf565b90506000811180156126255750600083115b15612745576000866001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561266a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061268e9190613a11565b9050600061269c8386612be0565b905060008083116126bc57604051806020016040528060008152506126c6565b6126c68284612bec565b905060006126ef60405180602001604052808a600001516001600160e01b031681525083612c31565b905061272a8160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612c5d565b6001600160e01b031688525050505060208401829052612753565b801561275357602084018290525b505050505050565b604080516020808201835284516001600160e01b031682528251908101928390526336fe846560e11b9092526001600160a01b0387811660248401528581166044840152600092839181908916636dfd08ca60648301602060405180830381865afa1580156127ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f29190613a11565b905280519091501580156128745750866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa15801561283f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128639190613eb2565b6001600160e01b0316826000015110155b156128e757866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128db9190613eb2565b6001600160e01b031681525b60006128f38383612c99565b6040516395dd919360e01b81526001600160a01b03898116600483015291925060009161296e91908c16906395dd919390602401602060405180830381865afa158015612944573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129689190613a11565b87612bc2565b9050600061297c8284612cc5565b9b9a5050505050505050505050565b604080516020808201835283516001600160e01b0316825282519081019283905263552c097160e01b9092526001600160a01b038681166024840152848116604484015260009283918190881663552c097160648301602060405180830381865afa1580156129fe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a229190613a11565b90528051909150158015612aa45750856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a939190613eb2565b6001600160e01b0316826000015110155b15612b1757856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ae7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b0b9190613eb2565b6001600160e01b031681525b6000612b238383612c99565b6040516370a0823160e01b81526001600160a01b0388811660048301529192506000918a16906370a0823190602401602060405180830381865afa158015612b6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b939190613a11565b90506000612ba18284612cc5565b9a9950505050505050505050565b6000612bbb8284613ecd565b9392505050565b6000612bbb612bd984670de0b6b3a7640000612be0565b8351612cef565b6000612bbb8284613b89565b6040805160208101909152600081526040518060200160405280612c28612c22866ec097ce7bc90715b34b9f1000000000612be0565b85612cef565b90529392505050565b6040805160208101909152600081526040518060200160405280612c2885600001518560000151612cfb565b6000816001600160e01b03841115612c915760405162461bcd60e51b8152600401612c889190613ee0565b60405180910390fd5b509192915050565b6040805160208101909152600081526040518060200160405280612c2885600001518560000151612baf565b60006ec097ce7bc90715b34b9f1000000000612ce5848460000151612be0565b612bbb9190613ba0565b6000612bbb8284613ba0565b6000612bbb8284613bc2565b604051806101a001604052806060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160608152602001606081526020016060815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001606081525090565b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180610220016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b6001600160a01b0381168114612e7657600080fd5b50565b8035612e8481612e61565b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715612ec157612ec1612e89565b60405290565b604051606081016001600160401b0381118282101715612ec157612ec1612e89565b604051601f8201601f191681016001600160401b0381118282101715612f1157612f11612e89565b604052919050565b60006001600160401b03821115612f3257612f32612e89565b50601f01601f191660200190565b60008060408385031215612f5357600080fd5b8235612f5e81612e61565b91506020838101356001600160401b0380821115612f7b57600080fd5b9085019060a08288031215612f8f57600080fd5b612f97612e9f565b823582811115612fa657600080fd5b83019150601f82018813612fb957600080fd5b8135612fcc612fc782612f19565b612ee9565b8181528986838601011115612fe057600080fd5b818685018783013760008683830101528083525050613000848401612e79565b8482015261301060408401612e79565b60408201526060830135606082015260808301356080820152809450505050509250929050565b60005b8381101561305257818101518382015260200161303a565b50506000910152565b60008151808452613073816020860160208601613037565b601f01601f19169290920160200192915050565b80516001600160a01b031682526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e0830152610100808201518184015250610120808201518184015250610140808201518184015250610160808201516131128285018215159052565b505061018081810151908301526101a0808201516001600160a01b0316908301526101c080820151908301526101e0808201519083015261020090810151910152565b60008151808452602080850194506020840160005b838110156131915761317d878351613087565b61022096909601959082019060010161316a565b509495945050505050565b60006101a082518185526131b28286018261305b565b91505060208301516131cf60208601826001600160a01b03169052565b5060408301516131ea60408601826001600160a01b03169052565b50606083015160608501526080830151608085015260a083015184820360a0860152613216828261305b565b91505060c083015184820360c0860152613230828261305b565b91505060e083015184820360e086015261324a828261305b565b91505061010080840151613268828701826001600160a01b03169052565b505061012083810151908501526101408084015190850152610160808401519085015261018080840151858303828701526132a38382613155565b9695505050505050565b602081526000612bbb602083018461319c565b60008083601f8401126132d257600080fd5b5081356001600160401b038111156132e957600080fd5b6020830191508360208260051b850101111561330457600080fd5b9250929050565b6000806020838503121561331e57600080fd5b82356001600160401b0381111561333457600080fd5b613340858286016132c0565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b8281101561339f5761338f84835180516001600160a01b03168252602090810151910152565b9284019290850190600101613369565b5091979650505050505050565b6000602082840312156133be57600080fd5b8135612bbb81612e61565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561342057603f1988860301845261340e85835161319c565b945092850192908501906001016133f2565b5092979650505050505050565b602080825282516001600160a01b03168282015282810151604080840191909152808401516060808501528051608085018190526000939291830191849160a08701905b808410156134ab5761349782865180516001600160a01b03168252602090810151910152565b938501936001939093019290820190613471565b50979650505050505050565b600080604083850312156134ca57600080fd5b82356134d581612e61565b915060208301356134e581612e61565b809150509250929050565b60008060006060848603121561350557600080fd5b833561351081612e61565b9250602084013561352081612e61565b9150604084013561353081612e61565b809150509250925092565b600060208083018184528085518083526040925060408601915060408160051b8701018488016000805b8481101561360857898403603f19018652825180516001600160a01b03908116865289820151168986015287810151888601526060908101516080918601829052805191860182905289019060a086019084905b808210156135f3576135df83855180516001600160a01b03168252602090810151910152565b928b0192918a0191600191909101906135b9565b50509689019694505091870191600101613565565b50919998505050505050505050565b60008060006040848603121561362c57600080fd5b83356001600160401b0381111561364257600080fd5b61364e868287016132c0565b909450925050602084013561353081612e61565b80516001600160a01b031682526020808201519083015260408082015190830152606080820151908301526080808201519083015260a090810151910152565b6020808252825182820181905260009190848201906040850190845b818110156136e4576136d1838551613662565b9284019260c092909201916001016136be565b50909695505050505050565b81516001600160a01b03168152602080830151908201526040810161064f565b610220810161064f8284613087565b60c0810161064f8284613662565b6020808252825182820181905260009190848201906040850190845b818110156136e45783516001600160a01b031683529284019291840191600101613749565b60006001600160401b0382111561378757613787612e89565b5060051b60200190565b600060208083850312156137a457600080fd5b82356001600160401b038111156137ba57600080fd5b8301601f810185136137cb57600080fd5b80356137d9612fc78261376e565b81815260059190911b820183019083810190878311156137f857600080fd5b928401925b8284101561381f57833561381081612e61565b825292840192908401906137fd565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156136e457613859838551613087565b928401926102209290920191600101613846565b6000602080838503121561388057600080fd5b82516001600160401b0381111561389657600080fd5b8301601f810185136138a757600080fd5b80516138b5612fc78261376e565b81815260059190911b820183019083810190878311156138d457600080fd5b928401925b8284101561381f5783516138ec81612e61565b825292840192908401906138d9565b600082601f83011261390c57600080fd5b815161391a612fc782612f19565b81815284602083860101111561392f57600080fd5b610c41826020830160208701613037565b60006020828403121561395257600080fd5b81516001600160401b038082111561396957600080fd5b908301906060828603121561397d57600080fd5b613985612ec7565b82518281111561399457600080fd5b6139a0878286016138fb565b8252506020830151828111156139b557600080fd5b6139c1878286016138fb565b6020830152506040830151828111156139d957600080fd5b6139e5878286016138fb565b60408301525095945050505050565b600060208284031215613a0657600080fd5b8151612bbb81612e61565b600060208284031215613a2357600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600060a08284031215613a5257600080fd5b613a5a612e9f565b905081516001600160401b03811115613a7257600080fd5b613a7e848285016138fb565b8252506020820151613a8f81612e61565b60208201526040820151613aa281612e61565b80604083015250606082015160608201526080820151608082015292915050565b60006020808385031215613ad657600080fd5b82516001600160401b0380821115613aed57600080fd5b818501915085601f830112613b0157600080fd5b8151613b0f612fc78261376e565b81815260059190911b83018401908481019088831115613b2e57600080fd5b8585015b83811015613b6657805185811115613b4a5760008081fd5b613b588b89838a0101613a40565b845250918601918601613b32565b5098975050505050505050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761064f5761064f613b73565b600082613bbd57634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561064f5761064f613b73565b600060208284031215613be757600080fd5b81516001600160401b03811115613bfd57600080fd5b610c4184828501613a40565b60006020808385031215613c1c57600080fd5b82516001600160401b03811115613c3257600080fd5b8301601f81018513613c4357600080fd5b8051613c51612fc78261376e565b81815260059190911b82018301908381019087831115613c7057600080fd5b928401925b8284101561381f578351613c8881612e61565b82529284019290840190613c75565b80518015158114612e8457600080fd5b60008060408385031215613cba57600080fd5b613cc383613c97565b9150602083015190509250929050565b600060208284031215613ce557600080fd5b815160ff81168114612bbb57600080fd5b634e487b7160e01b600052602160045260246000fd5b6001600160a01b03831681526040810160098310613d3a57634e487b7160e01b600052602160045260246000fd5b8260208301529392505050565b600060208284031215613d5957600080fd5b612bbb82613c97565b600060ff821660ff8103613d7857613d78613b73565b60010192915050565b60006020808385031215613d9457600080fd5b82516001600160401b03811115613daa57600080fd5b8301601f81018513613dbb57600080fd5b8051613dc9612fc78261376e565b81815260059190911b82018301908381019087831115613de857600080fd5b928401925b8284101561381f578351613e0081612e61565b82529284019290840190613ded565b80516001600160e01b0381168114612e8457600080fd5b600080600060608486031215613e3b57600080fd5b613e4484613e0f565b925060208401519150604084015190509250925092565b805163ffffffff81168114612e8457600080fd5b600080600060608486031215613e8457600080fd5b613e8d84613e0f565b9250613e9b60208501613e5b565b9150613ea960408501613e5b565b90509250925092565b600060208284031215613ec457600080fd5b612bbb82613e0f565b8181038181111561064f5761064f613b73565b602081526000612bbb602083018461305b56fea26469706673582212208dc9fbc3de84a5eadf5a8d0d7d030c880d5f4a9665121e956562816524e6c89964736f6c63430008190033", + "args": [false, 2628000, "0x687a01ecF6d3907658f7A7c714749fAC32336D1B"], + "numDeployments": 5, + "solcInputHash": "09f8b2889a382752688c03578bc27f8d", + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"timeBased_\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"blocksPerYear_\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"corePoolComptroller_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidBlocksPerYear\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTimeBasedConfiguration\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"blocksOrSecondsPerYear\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"corePoolComptroller\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"}],\"name\":\"getAllPools\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockNumberOrTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getPendingRewards\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"distributorAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"rewardTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalRewards\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.PendingReward[]\",\"name\":\"pendingRewards\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.RewardSummary[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getPoolBadDebt\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalBadDebtUsd\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"badDebtUsd\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.BadDebt[]\",\"name\":\"badDebts\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.BadDebtSummary\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolByComptroller\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolRegistryInterface.VenusPool\",\"name\":\"venusPool\",\"type\":\"tuple\"}],\"name\":\"getPoolDataFromVenusPool\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getPoolsSupportedByAsset\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getVTokenForAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isTimeBased\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"vTokenBalances\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalanceCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balanceOfUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenAllowance\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenBalances\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"vTokenBalancesAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalanceCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balanceOfUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenAllowance\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenBalances[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"vTokenMetadata\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"vTokenMetadataAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"vTokenUnderlyingPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"underlyingPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenUnderlyingPrice\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"vTokenUnderlyingPriceAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"underlyingPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenUnderlyingPrice[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"params\":{\"blocksPerYear_\":\"The number of blocks per year\",\"corePoolComptroller_\":\"The address of the core pool comptroller\",\"timeBased_\":\"A boolean indicating whether the contract is based on time or block.\"}},\"getAllPools(address)\":{\"details\":\"This function is not designed to be called in a transaction: it is too gas-intensive\",\"params\":{\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"Arrays of all Venus pools' data\"}},\"getBlockNumberOrTimestamp()\":{\"details\":\"Function to simply retrieve block number or block timestamp\",\"returns\":{\"_0\":\"Current block number or block timestamp\"}},\"getPendingRewards(address,address)\":{\"params\":{\"account\":\"The user account.\",\"comptrollerAddress\":\"address\"},\"returns\":{\"_0\":\"Pending rewards array\"}},\"getPoolBadDebt(address)\":{\"params\":{\"comptrollerAddress\":\"Address of the comptroller\"},\"returns\":{\"_0\":\"badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and a break down of bad debt by market\"}},\"getPoolByComptroller(address,address)\":{\"params\":{\"comptroller\":\"The Comptroller implementation address\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"PoolData structure containing the details of the pool\"}},\"getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))\":{\"params\":{\"poolRegistryAddress\":\"Address of the PoolRegistry\",\"venusPool\":\"The VenusPool Object from PoolRegistry\"},\"returns\":{\"_0\":\"Enriched PoolData\"}},\"getPoolsSupportedByAsset(address,address)\":{\"params\":{\"asset\":\"The underlying asset of vToken\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"A list of Comptroller contracts\"}},\"getVTokenForAsset(address,address,address)\":{\"params\":{\"asset\":\"The underlyingAsset of VToken\",\"comptroller\":\"The pool comptroller\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"Address of the vToken\"}},\"vTokenBalances(address,address)\":{\"params\":{\"account\":\"The user Account\",\"vToken\":\"vToken address\"},\"returns\":{\"_0\":\"A struct containing the balances data\"}},\"vTokenBalancesAll(address[],address)\":{\"params\":{\"account\":\"The user Account\",\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"A list of structs containing balances data\"}},\"vTokenMetadata(address)\":{\"params\":{\"vToken\":\"The address of vToken\"},\"returns\":{\"_0\":\"VTokenMetadata struct\"}},\"vTokenMetadataAll(address[])\":{\"params\":{\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"An array of VTokenMetadata structs\"}},\"vTokenUnderlyingPrice(address)\":{\"params\":{\"vToken\":\"vToken address\"},\"returns\":{\"_0\":\"The price data for each asset\"}},\"vTokenUnderlyingPriceAll(address[])\":{\"params\":{\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"An array containing the price data for each asset\"}}},\"title\":\"PoolLens\",\"version\":1},\"userdoc\":{\"errors\":{\"InvalidBlocksPerYear()\":[{\"notice\":\"Thrown when blocks per year is invalid\"}],\"InvalidTimeBasedConfiguration()\":[{\"notice\":\"Thrown when time based but blocks per year is provided\"}]},\"kind\":\"user\",\"methods\":{\"blocksOrSecondsPerYear()\":{\"notice\":\"Stores blocksPerYear if isTimeBased is true else secondsPerYear is stored\"},\"corePoolComptroller()\":{\"notice\":\"Address of the core pool comptroller (all markets are returned for this pool, including paused ones)\"},\"getAllPools(address)\":{\"notice\":\"Queries all pools with addtional details for each of them\"},\"getPendingRewards(address,address)\":{\"notice\":\"Returns the pending rewards for a user for a given pool.\"},\"getPoolBadDebt(address)\":{\"notice\":\"Returns a summary of a pool's bad debt broken down by market\"},\"getPoolByComptroller(address,address)\":{\"notice\":\"Queries the details of a pool identified by Comptroller address\"},\"getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))\":{\"notice\":\"Queries additional information for the pool\"},\"getPoolsSupportedByAsset(address,address)\":{\"notice\":\"Returns all pools that support the specified underlying asset\"},\"getVTokenForAsset(address,address,address)\":{\"notice\":\"Returns vToken holding the specified underlying asset in the specified pool\"},\"isTimeBased()\":{\"notice\":\"Acknowledges if a contract is time based or not\"},\"vTokenBalances(address,address)\":{\"notice\":\"Queries the user's supply/borrow balances in the specified vToken\"},\"vTokenBalancesAll(address[],address)\":{\"notice\":\"Queries the user's supply/borrow balances in vTokens\"},\"vTokenMetadata(address)\":{\"notice\":\"Returns the metadata of VToken\"},\"vTokenMetadataAll(address[])\":{\"notice\":\"Returns the metadata of all VTokens\"},\"vTokenUnderlyingPrice(address)\":{\"notice\":\"Returns the price data for the underlying asset of the specified vToken\"},\"vTokenUnderlyingPriceAll(address[])\":{\"notice\":\"Returns the price data for the underlying assets of the specified vTokens\"}},\"notice\":\"The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be looked up for specific pools and markets: - the vToken balance of a given user; - the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address; - the vToken address in a pool for a given asset; - a list of all pools that support an asset; - the underlying asset price of a vToken; - the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Lens/PoolLens.sol\":\"PoolLens\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"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\",\"keccak256\":\"0x9140dabc466abab21b48b72dbda26736b1183a310d0e677d3719d201df026510\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x359a1ab89b46b9aba7bcad3fb651924baf4893d15153049b9976b0fc9be1358e\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x07e881de3b9f6d2c07909f193f24b96c7fe4ea60013260f3f25aecd8bab3c2f8\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x75097e35253e7fb282ee4d7f27a80eaacfa759923185bf17302a89cbc059c5ef\",\"license\":\"MIT\"},\"@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\"},\"@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\",\"keccak256\":\"0xfe0fd441c84ac907cabc88db69ef04f6d7532d770c7e6a1dfe6e7d6305debb49\",\"license\":\"BSD-3-Clause\"},\"@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 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/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface IProtocolShareReserve {\\n /// @notice it represents the type of vToken income\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(\\n address comptroller,\\n address asset,\\n IncomeType incomeType\\n ) external;\\n}\\n\",\"keccak256\":\"0x0f341bbef8f12885d79b7acaad7aaf11b84809e8f6b059ef4efc011c8f6c39a5\",\"license\":\"BSD-3-Clause\"},\"@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\",\"keccak256\":\"0x57a2bbb9b8e02b1c0a5c0e305fef1328a22db56c3d4b148c362010a6e767243c\",\"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\"},\"@venusprotocol/venus-protocol/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\",\"keccak256\":\"0xd112f60183416ad796093b4a83a80ddc1b8b655965f02ae55ca82e2a0c68f97d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/venus-protocol/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\",\"keccak256\":\"0x5285c875114db2ea2be0b81b65722d5761806217022db733323c4e03365a95e7\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IPrime } from \\\"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\\\";\\n\\nimport { ComptrollerInterface, Action } from \\\"./ComptrollerInterface.sol\\\";\\nimport { ComptrollerStorage } from \\\"./ComptrollerStorage.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"./MaxLoopsLimitHelper.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title Comptroller\\n * @author Venus\\n * @notice The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating,\\n * and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts\\n * with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows\\n * or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing\\n * liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow,\\n * as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the\\n * markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market\\u2019s corresponding liquidation threshold,\\n * the borrow is eligible for liquidation.\\n *\\n * The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed\\n * the `minLiquidatableCollateral` for the `Comptroller`:\\n *\\n * - `healAccount()`: This function is called to seize all of a given user\\u2019s collateral, requiring the `msg.sender` repay a certain percentage\\n * of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed\\n * 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt\\n * and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool.\\n * - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation\\n * incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic\\n * verifying that the repay amount does not exceed the close factor.\\n */\\ncontract Comptroller is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n ComptrollerStorage,\\n ComptrollerInterface,\\n ExponentialNoError,\\n MaxLoopsLimitHelper\\n{\\n // PoolRegistry, immutable to save on gas\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable poolRegistry;\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(VToken indexed vToken, address indexed account);\\n\\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(VToken vToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa);\\n\\n /// @notice Emitted when liquidation threshold is changed by admin\\n event NewLiquidationThreshold(\\n VToken vToken,\\n uint256 oldLiquidationThresholdMantissa,\\n uint256 newLiquidationThresholdMantissa\\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 an action is paused on a market\\n event ActionPausedMarket(VToken vToken, Action action, bool pauseState);\\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 the collateral threshold (in USD) for non-batch liquidations is changed\\n event NewMinLiquidatableCollateral(uint256 oldMinLiquidatableCollateral, uint256 newMinLiquidatableCollateral);\\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 a rewards distributor is added\\n event NewRewardsDistributor(address indexed rewardsDistributor, address indexed rewardToken);\\n\\n /// @notice Emitted when a market is supported\\n event MarketSupported(VToken vToken);\\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 a market\\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\\n\\n /// @notice Emitted when a market is unlisted\\n event MarketUnlisted(address indexed vToken);\\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 Thrown when collateral factor exceeds the upper bound\\n error InvalidCollateralFactor();\\n\\n /// @notice Thrown when liquidation threshold exceeds the collateral factor\\n error InvalidLiquidationThreshold();\\n\\n /// @notice Thrown when the action is only available to specific sender, but the real sender was different\\n error UnexpectedSender(address expectedSender, address actualSender);\\n\\n /// @notice Thrown when the oracle returns an invalid price for some asset\\n error PriceError(address vToken);\\n\\n /// @notice Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\\n error SnapshotError(address vToken, address user);\\n\\n /// @notice Thrown when the market is not listed\\n error MarketNotListed(address market);\\n\\n /// @notice Thrown when a market has an unexpected comptroller\\n error ComptrollerMismatch();\\n\\n /// @notice Thrown when user is not member of market\\n error MarketNotCollateral(address vToken, address user);\\n\\n /// @notice Thrown when borrow action is not paused\\n error BorrowActionNotPaused();\\n\\n /// @notice Thrown when mint action is not paused\\n error MintActionNotPaused();\\n\\n /// @notice Thrown when redeem action is not paused\\n error RedeemActionNotPaused();\\n\\n /// @notice Thrown when repay action is not paused\\n error RepayActionNotPaused();\\n\\n /// @notice Thrown when seize action is not paused\\n error SeizeActionNotPaused();\\n\\n /// @notice Thrown when exit market action is not paused\\n error ExitMarketActionNotPaused();\\n\\n /// @notice Thrown when transfer action is not paused\\n error TransferActionNotPaused();\\n\\n /// @notice Thrown when enter market action is not paused\\n error EnterMarketActionNotPaused();\\n\\n /// @notice Thrown when liquidate action is not paused\\n error LiquidateActionNotPaused();\\n\\n /// @notice Thrown when borrow cap is not zero\\n error BorrowCapIsNotZero();\\n\\n /// @notice Thrown when supply cap is not zero\\n error SupplyCapIsNotZero();\\n\\n /// @notice Thrown when collateral factor is not zero\\n error CollateralFactorIsNotZero();\\n\\n /**\\n * @notice Thrown during the liquidation if user's total collateral amount is lower than\\n * a predefined threshold. In this case only batch liquidations (either liquidateAccount\\n * or healAccount) are available.\\n */\\n error MinimalCollateralViolated(uint256 expectedGreaterThan, uint256 actual);\\n error CollateralExceedsThreshold(uint256 expectedLessThanOrEqualTo, uint256 actual);\\n error InsufficientCollateral(uint256 collateralToSeize, uint256 availableCollateral);\\n\\n /// @notice Thrown when the account doesn't have enough liquidity to redeem or borrow\\n error InsufficientLiquidity();\\n\\n /// @notice Thrown when trying to liquidate a healthy account\\n error InsufficientShortfall();\\n\\n /// @notice Thrown when trying to repay more than allowed by close factor\\n error TooMuchRepay();\\n\\n /// @notice Thrown if the user is trying to exit a market in which they have an outstanding debt\\n error NonzeroBorrowBalance();\\n\\n /// @notice Thrown when trying to perform an action that is paused\\n error ActionPaused(address market, Action action);\\n\\n /// @notice Thrown when trying to add a market that is already listed\\n error MarketAlreadyListed(address market);\\n\\n /// @notice Thrown if the supply cap is exceeded\\n error SupplyCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if the borrow cap is exceeded\\n error BorrowCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if delegate approval status is already set to the requested value\\n error DelegationStatusUnchanged();\\n\\n /// @param poolRegistry_ Pool registry address\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n constructor(address poolRegistry_) {\\n ensureNonzeroAddress(poolRegistry_);\\n\\n poolRegistry = poolRegistry_;\\n _disableInitializers();\\n }\\n\\n /**\\n * @param loopLimit Limit for the loops can iterate to avoid the DOS\\n * @param accessControlManager Access control manager contract address\\n */\\n function initialize(uint256 loopLimit, address accessControlManager) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager);\\n\\n _setMaxLoopsLimit(loopLimit);\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation; enabling them to be used as collateral\\n * @param vTokens The list of addresses of the vToken markets to be enabled\\n * @return errors An array of NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketEntered is emitted for each market on success\\n * @custom:error ActionPaused error is thrown if entering any of the markets is paused\\n * @custom:error MarketNotListed error is thrown if any of the markets is not listed\\n * @custom:access Not restricted\\n */\\n function enterMarkets(address[] memory vTokens) external override returns (uint256[] memory) {\\n uint256 len = vTokens.length;\\n\\n uint256[] memory results = new uint256[](len);\\n for (uint256 i; i < len; ++i) {\\n VToken vToken = VToken(vTokens[i]);\\n\\n _addToMarket(vToken, msg.sender);\\n results[i] = NO_ERROR;\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Unlist a market by setting isListed to false\\n * @dev Checks if all actions are paused, borrow/supply caps is set to 0 and collateral factor is to 0.\\n * @param market The address of the market (token) to unlist\\n * @return uint256 Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketUnlisted is emitted on success\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error BorrowActionNotPaused error is thrown if borrow action is not paused\\n * @custom:error MintActionNotPaused error is thrown if mint action is not paused\\n * @custom:error RedeemActionNotPaused error is thrown if redeem action is not paused\\n * @custom:error RepayActionNotPaused error is thrown if repay action is not paused\\n * @custom:error EnterMarketActionNotPaused error is thrown if enter market action is not paused\\n * @custom:error LiquidateActionNotPaused error is thrown if liquidate action is not paused\\n * @custom:error BorrowCapIsNotZero error is thrown if borrow cap is not zero\\n * @custom:error SupplyCapIsNotZero error is thrown if supply cap is not zero\\n * @custom:error CollateralFactorIsNotZero error is thrown if collateral factor is not zero\\n */\\n function unlistMarket(address market) external returns (uint256) {\\n _checkAccessAllowed(\\\"unlistMarket(address)\\\");\\n\\n Market storage _market = markets[market];\\n\\n if (!_market.isListed) {\\n revert MarketNotListed(market);\\n }\\n\\n if (!actionPaused(market, Action.BORROW)) {\\n revert BorrowActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.MINT)) {\\n revert MintActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.REDEEM)) {\\n revert RedeemActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.REPAY)) {\\n revert RepayActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.SEIZE)) {\\n revert SeizeActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.ENTER_MARKET)) {\\n revert EnterMarketActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.LIQUIDATE)) {\\n revert LiquidateActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.TRANSFER)) {\\n revert TransferActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.EXIT_MARKET)) {\\n revert ExitMarketActionNotPaused();\\n }\\n\\n if (borrowCaps[market] != 0) {\\n revert BorrowCapIsNotZero();\\n }\\n\\n if (supplyCaps[market] != 0) {\\n revert SupplyCapIsNotZero();\\n }\\n\\n if (_market.collateralFactorMantissa != 0) {\\n revert CollateralFactorIsNotZero();\\n }\\n\\n _market.isListed = false;\\n emit MarketUnlisted(market);\\n\\n return NO_ERROR;\\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 * @custom:event DelegateUpdated emits on success\\n * @custom:error ZeroAddressNotAllowed is thrown when delegate address is zero\\n * @custom:error DelegationStatusUnchanged is thrown if approval status is already set to the requested value\\n * @custom:access Not restricted\\n */\\n function updateDelegate(address delegate, bool approved) external {\\n ensureNonzeroAddress(delegate);\\n if (approvedDelegates[msg.sender][delegate] == approved) {\\n revert DelegationStatusUnchanged();\\n }\\n\\n approvedDelegates[msg.sender][delegate] = approved;\\n emit DelegateUpdated(msg.sender, delegate, approved);\\n }\\n\\n /**\\n * @notice Removes asset from sender's account liquidity calculation; disabling them as collateral\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketExited is emitted on success\\n * @custom:error ActionPaused error is thrown if exiting the market is paused\\n * @custom:error NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function exitMarket(address vTokenAddress) external override returns (uint256) {\\n _checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\\n VToken vToken = VToken(vTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\\n (uint256 tokensHeld, uint256 amountOwed, ) = _safeGetAccountSnapshot(vToken, msg.sender);\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n revert NonzeroBorrowBalance();\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n _checkRedeemAllowed(vTokenAddress, msg.sender, tokensHeld);\\n\\n Market storage marketToExit = markets[address(vToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return 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 // load into memory for faster iteration\\n VToken[] memory userAssetList = accountAssets[msg.sender];\\n uint256 len = userAssetList.length;\\n\\n uint256 assetIndex = len;\\n for (uint256 i; i < len; ++i) {\\n if (userAssetList[i] == vToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n VToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.pop();\\n\\n emit MarketExited(vToken, msg.sender);\\n\\n return NO_ERROR;\\n }\\n\\n /*** Policy Hooks ***/\\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 * @custom:error ActionPaused error is thrown if supplying to this market is paused\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\\n * @custom:access Not restricted\\n */\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external override {\\n _checkActionPauseState(vToken, Action.MINT);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n uint256 supplyCap = supplyCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (supplyCap != type(uint256).max) {\\n uint256 vTokenSupply = VToken(vToken).totalSupply();\\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\\n if (nextTotalSupply > supplyCap) {\\n revert SupplyCapExceeded(vToken, supplyCap);\\n }\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, minter);\\n }\\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external override {\\n _checkActionPauseState(vToken, Action.REDEEM);\\n\\n _checkRedeemAllowed(vToken, redeemer, redeemTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, redeemer);\\n }\\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 if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(redeemer, vToken);\\n }\\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 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 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 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 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 * @custom:error ActionPaused error is thrown if borrowing is paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if there is not enough collateral to borrow\\n * @custom:error BorrowCapExceeded is thrown if the borrow cap will be exceeded should this borrow succeed\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted if vToken is enabled as collateral, otherwise only vToken\\n */\\n /// disable-eslint\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external override {\\n _checkActionPauseState(vToken, Action.BORROW);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (!markets[vToken].accountMembership[borrower]) {\\n // only vTokens may call borrowAllowed if borrower not in market\\n _checkSenderIs(vToken);\\n\\n // attempt to add borrower to the market or revert\\n _addToMarket(VToken(msg.sender), borrower);\\n }\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (oracle.getUnderlyingPrice(vToken) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 borrowCap = borrowCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (borrowCap != type(uint256).max) {\\n uint256 totalBorrows = VToken(vToken).totalBorrows();\\n uint256 badDebt = VToken(vToken).badDebt();\\n uint256 nextTotalBorrows = totalBorrows + borrowAmount + badDebt;\\n if (nextTotalBorrows > borrowCap) {\\n revert BorrowCapExceeded(vToken, borrowCap);\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n borrower,\\n VToken(vToken),\\n 0,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\n }\\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 borrower The account which would borrowed the asset\\n * @custom:error ActionPaused error is thrown if repayments are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:access Not restricted\\n */\\n function preRepayHook(address vToken, address borrower) external override {\\n _checkActionPauseState(vToken, Action.REPAY);\\n\\n oracle.updatePrice(vToken);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\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 borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n * @param skipLiquidityCheck Allows the borrow to be liquidated regardless of the account liquidity\\n * @custom:error ActionPaused error is thrown if liquidations are paused in this market\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor\\n * @custom:error MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations\\n * @custom:error InsufficientShortfall is thrown when trying to liquidate a healthy account\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n */\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external override {\\n // Pause Action.LIQUIDATE on BORROWED TOKEN to prevent liquidating it.\\n // If we want to pause liquidating to vTokenCollateral, we should pause\\n // Action.SEIZE on it\\n _checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(address(vTokenBorrowed));\\n }\\n if (!markets[vTokenCollateral].isListed) {\\n revert MarketNotListed(address(vTokenCollateral));\\n }\\n\\n uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\\n\\n /* Allow accounts to be liquidated if it is a forced liquidation */\\n if (skipLiquidityCheck || isForcedLiquidationEnabled[vTokenBorrowed]) {\\n if (repayAmount > borrowBalance) {\\n revert TooMuchRepay();\\n }\\n return;\\n }\\n\\n /* The borrower must have shortfall and collateral > threshold in order to be liquidatable */\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral <= minLiquidatableCollateral) {\\n /* The liquidator should use either liquidateAccount or healAccount */\\n revert MinimalCollateralViolated(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint256 maxClose = mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance);\\n if (repayAmount > maxClose) {\\n revert TooMuchRepay();\\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 seizerContract Contract that tries to seize the asset (either borrowed vToken or Comptroller)\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @custom:error ActionPaused error is thrown if seizing this type of collateral is paused\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error ComptrollerMismatch error is when seizer contract or seized asset belong to different pools\\n * @custom:access Not restricted\\n */\\n function preSeizeHook(\\n address vTokenCollateral,\\n address seizerContract,\\n address liquidator,\\n address borrower\\n ) external override {\\n // Pause Action.SEIZE on COLLATERAL to prevent seizing it.\\n // If we want to pause liquidating vTokenBorrowed, we should pause\\n // Action.LIQUIDATE on it\\n _checkActionPauseState(vTokenCollateral, Action.SEIZE);\\n\\n Market storage market = markets[vTokenCollateral];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(vTokenCollateral);\\n }\\n\\n if (seizerContract == address(this)) {\\n // If Comptroller is the seizer, just check if collateral's comptroller\\n // is equal to the current address\\n if (address(VToken(vTokenCollateral).comptroller()) != address(this)) {\\n revert ComptrollerMismatch();\\n }\\n } else {\\n // If the seizer is not the Comptroller, check that the seizer is a\\n // listed market, and that the markets' comptrollers match\\n if (!markets[seizerContract].isListed) {\\n revert MarketNotListed(seizerContract);\\n }\\n if (VToken(vTokenCollateral).comptroller() != VToken(seizerContract).comptroller()) {\\n revert ComptrollerMismatch();\\n }\\n }\\n\\n if (!market.accountMembership[borrower]) {\\n revert MarketNotCollateral(vTokenCollateral, borrower);\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vTokenCollateral);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, borrower);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, liquidator);\\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external override {\\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 _checkRedeemAllowed(vToken, src, transferTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, src);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, dst);\\n }\\n }\\n\\n /*** Pool-level operations ***/\\n\\n /**\\n * @notice Seizes all the remaining collateral, makes msg.sender repay the existing\\n * borrows, and treats the rest of the debt as bad debt (for each market).\\n * The sender has to repay a certain percentage of the debt, computed as\\n * collateral / (borrows * liquidationIncentive).\\n * @param user account to heal\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for healing\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function healAccount(address user) external {\\n VToken[] memory userAssets = getAssetsIn(user);\\n uint256 userAssetsCount = userAssets.length;\\n\\n address liquidator = msg.sender;\\n {\\n ResilientOracleInterface oracle_ = oracle;\\n // We need all user's markets to be fresh for the computations to be correct\\n for (uint256 i; i < userAssetsCount; ++i) {\\n userAssets[i].accrueInterest();\\n oracle_.updatePrice(address(userAssets[i]));\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(user, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n // percentage = collateral / (borrows * liquidation incentive)\\n Exp memory collateral = Exp({ mantissa: snapshot.totalCollateral });\\n Exp memory scaledBorrows = mul_(\\n Exp({ mantissa: snapshot.borrows }),\\n Exp({ mantissa: liquidationIncentiveMantissa })\\n );\\n\\n Exp memory percentage = div_(collateral, scaledBorrows);\\n if (lessThanExp(Exp({ mantissa: MANTISSA_ONE }), percentage)) {\\n revert CollateralExceedsThreshold(scaledBorrows.mantissa, collateral.mantissa);\\n }\\n\\n for (uint256 i; i < userAssetsCount; ++i) {\\n VToken market = userAssets[i];\\n\\n (uint256 tokens, uint256 borrowBalance, ) = _safeGetAccountSnapshot(market, user);\\n uint256 repaymentAmount = mul_ScalarTruncate(percentage, borrowBalance);\\n\\n // Seize the entire collateral\\n if (tokens != 0) {\\n market.seize(liquidator, user, tokens);\\n }\\n // Repay a certain percentage of the borrow, forgive the rest\\n if (borrowBalance != 0) {\\n market.healBorrow(liquidator, user, repaymentAmount);\\n }\\n }\\n }\\n\\n /**\\n * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than\\n * a predefined threshold, and the account collateral can be seized to cover all borrows. If\\n * the collateral is higher than the threshold, use regular liquidations. If the collateral is\\n * below the threshold, and the account is insolvent, use healAccount.\\n * @param borrower the borrower address\\n * @param orders an array of liquidation orders\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation\\n * @custom:error InsufficientCollateral error is thrown when there is not enough collateral to cover the debt\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function liquidateAccount(address borrower, LiquidationOrder[] calldata orders) external {\\n // We will accrue interest and update the oracle prices later during the liquidation\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n // You should use the regular vToken.liquidateBorrow(...) call\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n uint256 collateralToSeize = mul_ScalarTruncate(\\n Exp({ mantissa: liquidationIncentiveMantissa }),\\n snapshot.borrows\\n );\\n if (collateralToSeize >= snapshot.totalCollateral) {\\n // There is not enough collateral to seize. Use healBorrow to repay some part of the borrow\\n // and record bad debt.\\n revert InsufficientCollateral(collateralToSeize, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n uint256 ordersCount = orders.length;\\n\\n _ensureMaxLoops(ordersCount / 2);\\n\\n for (uint256 i; i < ordersCount; ++i) {\\n if (!markets[address(orders[i].vTokenBorrowed)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenBorrowed));\\n }\\n if (!markets[address(orders[i].vTokenCollateral)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenCollateral));\\n }\\n\\n LiquidationOrder calldata order = orders[i];\\n order.vTokenBorrowed.forceLiquidateBorrow(\\n msg.sender,\\n borrower,\\n order.repayAmount,\\n order.vTokenCollateral,\\n true\\n );\\n }\\n\\n VToken[] memory borrowMarkets = getAssetsIn(borrower);\\n uint256 marketsCount = borrowMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower);\\n require(borrowBalance == 0, \\\"Nonzero borrow balance after liquidation\\\");\\n }\\n }\\n\\n /**\\n * @notice Sets the closeFactor to use when liquidating borrows\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @custom:event Emits NewCloseFactor on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCloseFactor(uint256 newCloseFactorMantissa) external {\\n _checkAccessAllowed(\\\"setCloseFactor(uint256)\\\");\\n require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, \\\"Close factor greater than maximum close factor\\\");\\n require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, \\\"Close factor smaller than minimum close factor\\\");\\n\\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev This function is restricted by the AccessControlManager\\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 * @custom:event Emits NewCollateralFactor when collateral factor is updated\\n * and NewLiquidationThreshold when liquidation threshold is updated\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InvalidCollateralFactor error is thrown when collateral factor is too high\\n * @custom:error InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor\\n * @custom:error PriceError is thrown when the oracle returns an invalid price for the asset\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCollateralFactor(\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external {\\n _checkAccessAllowed(\\\"setCollateralFactor(address,uint256,uint256)\\\");\\n\\n // Verify market is listed\\n Market storage market = markets[address(vToken)];\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Check collateral factor <= 0.9\\n if (newCollateralFactorMantissa > MAX_COLLATERAL_FACTOR_MANTISSA) {\\n revert InvalidCollateralFactor();\\n }\\n\\n // Ensure that liquidation threshold <= 1\\n if (newLiquidationThresholdMantissa > MANTISSA_ONE) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // Ensure that liquidation threshold >= CF\\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n }\\n\\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\\n emit NewLiquidationThreshold(vToken, oldLiquidationThresholdMantissa, newLiquidationThresholdMantissa);\\n }\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev This function is restricted by the AccessControlManager\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @custom:event Emits NewLiquidationIncentive on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external {\\n require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, \\\"liquidation incentive should be greater than 1e18\\\");\\n\\n _checkAccessAllowed(\\\"setLiquidationIncentive(uint256)\\\");\\n\\n // Save current value for use in log\\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\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\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Only callable by the PoolRegistry\\n * @param vToken The address of the market (token) to list\\n * @custom:error MarketAlreadyListed is thrown if the market is already listed in this pool\\n * @custom:access Only PoolRegistry\\n */\\n function supportMarket(VToken vToken) external {\\n _checkSenderIs(poolRegistry);\\n\\n if (markets[address(vToken)].isListed) {\\n revert MarketAlreadyListed(address(vToken));\\n }\\n\\n require(vToken.isVToken(), \\\"Comptroller: Invalid vToken\\\"); // Sanity check to make sure its really a VToken\\n\\n Market storage newMarket = markets[address(vToken)];\\n newMarket.isListed = true;\\n newMarket.collateralFactorMantissa = 0;\\n newMarket.liquidationThresholdMantissa = 0;\\n\\n _addMarket(address(vToken));\\n\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n rewardsDistributors[i].initializeMarket(address(vToken));\\n }\\n\\n emit MarketSupported(vToken);\\n }\\n\\n /**\\n * @notice Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A borrow cap of type(uint256).max corresponds to unlimited borrowing.\\n * @dev Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed\\n until the total borrows amount goes below the new borrow cap\\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 type(uint256).max corresponds to unlimited borrowing.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\\n _checkAccessAllowed(\\\"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 _ensureMaxLoops(numMarkets);\\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 * @notice Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A supply cap of type(uint256).max corresponds to unlimited supply.\\n * @dev Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed\\n until the total supplies amount goes below the new supply cap\\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 type(uint256).max corresponds to unlimited supply.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\\n _checkAccessAllowed(\\\"setMarketSupplyCaps(address[],uint256[])\\\");\\n uint256 vTokensCount = vTokens.length;\\n\\n require(vTokensCount != 0, \\\"invalid number of markets\\\");\\n require(vTokensCount == newSupplyCaps.length, \\\"invalid number of markets\\\");\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Pause/unpause specified actions\\n * @dev This function is restricted by the AccessControlManager\\n * @param marketsList Markets to pause/unpause the actions on\\n * @param actionsList List of action ids to pause/unpause\\n * @param paused The new paused state (true=paused, false=unpaused)\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setActionsPaused(VToken[] calldata marketsList, Action[] calldata actionsList, bool paused) external {\\n _checkAccessAllowed(\\\"setActionsPaused(address[],uint256[],bool)\\\");\\n\\n uint256 marketsCount = marketsList.length;\\n uint256 actionsCount = actionsList.length;\\n\\n _ensureMaxLoops(marketsCount * actionsCount);\\n\\n for (uint256 marketIdx; marketIdx < marketsCount; ++marketIdx) {\\n for (uint256 actionIdx; actionIdx < actionsCount; ++actionIdx) {\\n _setActionPaused(address(marketsList[marketIdx]), actionsList[actionIdx], paused);\\n }\\n }\\n }\\n\\n /**\\n * @notice Set the given collateral threshold for non-batch liquidations. Regular liquidations\\n * will fail if the collateral amount is less than this threshold. Liquidators should use batch\\n * operations like liquidateAccount or healAccount.\\n * @dev This function is restricted by the AccessControlManager\\n * @param newMinLiquidatableCollateral The new min liquidatable collateral (in USD).\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external {\\n _checkAccessAllowed(\\\"setMinLiquidatableCollateral(uint256)\\\");\\n\\n uint256 oldMinLiquidatableCollateral = minLiquidatableCollateral;\\n minLiquidatableCollateral = newMinLiquidatableCollateral;\\n emit NewMinLiquidatableCollateral(oldMinLiquidatableCollateral, newMinLiquidatableCollateral);\\n }\\n\\n /**\\n * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor\\n * contracts with the same rewardToken, and there could be overlaping among them considering the last reward slot (block or second)\\n * @dev Only callable by the admin\\n * @param _rewardsDistributor Address of the RewardDistributor contract to add\\n * @custom:access Only Governance\\n * @custom:event Emits NewRewardsDistributor with distributor address\\n */\\n function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner {\\n require(!rewardsDistributorExists[address(_rewardsDistributor)], \\\"already exists\\\");\\n\\n uint256 rewardsDistributorsLen = rewardsDistributors.length;\\n _ensureMaxLoops(rewardsDistributorsLen + 1);\\n\\n rewardsDistributors.push(_rewardsDistributor);\\n rewardsDistributorExists[address(_rewardsDistributor)] = true;\\n\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n _rewardsDistributor.initializeMarket(address(allMarkets[i]));\\n }\\n\\n emit NewRewardsDistributor(address(_rewardsDistributor), address(_rewardsDistributor.rewardToken()));\\n }\\n\\n /**\\n * @notice Sets a new price oracle for the Comptroller\\n * @dev Only callable by the admin\\n * @param newOracle Address of the new price oracle to set\\n * @custom:event Emits NewPriceOracle on success\\n * @custom:error ZeroAddressNotAllowed is thrown when the new oracle address is zero\\n */\\n function setPriceOracle(ResilientOracleInterface newOracle) external onlyOwner {\\n ensureNonzeroAddress(address(newOracle));\\n\\n ResilientOracleInterface oldOracle = oracle;\\n oracle = newOracle;\\n emit NewPriceOracle(oldOracle, newOracle);\\n }\\n\\n /**\\n * @notice Set the for loop iteration limit to avoid DOS\\n * @param limit Limit for the max loops can execute at a time\\n */\\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Sets the prime token contract for the comptroller\\n * @param _prime Address of the Prime contract\\n */\\n function setPrimeToken(IPrime _prime) external onlyOwner {\\n ensureNonzeroAddress(address(_prime));\\n\\n emit NewPrimeToken(prime, _prime);\\n prime = _prime;\\n }\\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 * @param vTokenBorrowed Borrowed vToken\\n * @param enable Whether to enable forced liquidations\\n */\\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\\n _checkAccessAllowed(\\\"setForcedLiquidation(address,bool)\\\");\\n ensureNonzeroAddress(vTokenBorrowed);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(vTokenBorrowed);\\n }\\n\\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to liquidation threshold requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of liquidation threshold requirements,\\n * @return shortfall Account shortfall below liquidation threshold requirements\\n */\\n function getAccountLiquidity(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getLiquidationThreshold);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to collateral requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of collateral requirements,\\n * @return shortfall Account shortfall below collateral requirements\\n */\\n function getBorrowingPower(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getCollateralFactor);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Hypothetical account liquidity in excess of collateral requirements,\\n * @return shortfall 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 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n account,\\n VToken(vTokenModify),\\n redeemTokens,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\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 markets The list of market addresses\\n */\\n function getAllMarkets() external view override returns (VToken[] memory) {\\n return allMarkets;\\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 /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns whether the given account is entered in a given market\\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 market specified, 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 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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return tokensToSeize Number of vTokenCollateral tokens to be seized in a liquidation\\n * @custom:error PriceError if the oracle returns an invalid price\\n */\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view override returns (uint256 error, uint256 tokensToSeize) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint256 priceBorrowedMantissa = _safeGetUnderlyingPrice(VToken(vTokenBorrowed));\\n uint256 priceCollateralMantissa = _safeGetUnderlyingPrice(VToken(vTokenCollateral));\\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 uint256 exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint256 seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n\\n numerator = mul_(Exp({ mantissa: liquidationIncentiveMantissa }), Exp({ mantissa: priceBorrowedMantissa }));\\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\\n ratio = div_(numerator, denominator);\\n\\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\\n\\n return (NO_ERROR, seizeTokens);\\n }\\n\\n /**\\n * @notice Returns reward speed given a vToken\\n * @param vToken The vToken to get the reward speeds for\\n * @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors\\n */\\n function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {\\n uint256 rewardsDistributorsLength = rewardsDistributors.length;\\n rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);\\n for (uint256 i; i < rewardsDistributorsLength; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n address rewardToken = address(rewardsDistributor.rewardToken());\\n rewardSpeeds[i] = RewardSpeeds({\\n rewardToken: rewardToken,\\n supplySpeed: rewardsDistributor.rewardTokenSupplySpeeds(vToken),\\n borrowSpeed: rewardsDistributor.rewardTokenBorrowSpeeds(vToken)\\n });\\n }\\n return rewardSpeeds;\\n }\\n\\n /**\\n * @notice Return all reward distributors for this pool\\n * @return Array of RewardDistributor addresses\\n */\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory) {\\n return rewardsDistributors;\\n }\\n\\n /**\\n * @notice A marker method that returns true for a valid Comptroller contract\\n * @return Always true\\n */\\n function isComptroller() external pure override returns (bool) {\\n return true;\\n }\\n\\n /**\\n * @notice Update the prices of all the tokens associated with the provided account\\n * @param account Address of the account to get associated tokens with\\n */\\n function updatePrices(address account) public {\\n VToken[] memory vTokens = getAssetsIn(account);\\n uint256 vTokensCount = vTokens.length;\\n\\n ResilientOracleInterface oracle_ = oracle;\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n oracle_.updatePrice(address(vTokens[i]));\\n }\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param market vToken address\\n * @param action Action to check\\n * @return paused True if the action is paused otherwise false\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][action];\\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 list with the assets the account has entered\\n */\\n function getAssetsIn(address account) public 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 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 */\\n function _addToMarket(VToken vToken, address borrower) internal {\\n _checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = markets[address(vToken)];\\n\\n if (!marketToJoin.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return;\\n }\\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\\n /**\\n * @notice Internal function to validate that a market hasn't already been added\\n * and if it hasn't adds it\\n * @param vToken The market to support\\n */\\n function _addMarket(address vToken) internal {\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n if (allMarkets[i] == VToken(vToken)) {\\n revert MarketAlreadyListed(vToken);\\n }\\n }\\n allMarkets.push(VToken(vToken));\\n marketsCount = allMarkets.length;\\n _ensureMaxLoops(marketsCount);\\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 _setActionPaused(address market, Action action, bool paused) internal {\\n require(markets[market].isListed, \\\"cannot pause a market that is not listed\\\");\\n _actionPaused[market][action] = paused;\\n emit ActionPausedMarket(VToken(market), action, paused);\\n }\\n\\n /**\\n * @dev Internal function to check that vTokens can be safely redeemed for the underlying asset.\\n * @param vToken Address of the vTokens to redeem\\n * @param redeemer Account redeeming the tokens\\n * @param redeemTokens The number of tokens to redeem\\n */\\n function _checkRedeemAllowed(address vToken, address redeemer, uint256 redeemTokens) internal {\\n Market storage market = markets[vToken];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!market.accountMembership[redeemer]) {\\n return;\\n }\\n\\n // Update the prices of tokens\\n updatePrices(redeemer);\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n _getCollateralFactor\\n );\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n }\\n\\n /**\\n * @notice Get the total collateral, weighted collateral, borrow balance, liquidity, shortfall\\n * @param account The account to get the snapshot for\\n * @param weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n * liquidation threshold. Accepts the address of the vToken and returns the weight as Exp.\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getCurrentLiquiditySnapshot(\\n address account,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n return _getHypotheticalLiquiditySnapshot(account, VToken(address(0)), 0, 0, weight);\\n }\\n\\n /**\\n * @notice Determine what the supply/borrow balances 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 weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n liquidation threshold. Accepts the address of the VToken and returns the weight\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getHypotheticalLiquiditySnapshot(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n // For each asset the account is in\\n VToken[] memory assets = getAssetsIn(account);\\n uint256 assetsCount = assets.length;\\n\\n for (uint256 i; i < assetsCount; ++i) {\\n VToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the vToken\\n (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) = _safeGetAccountSnapshot(\\n asset,\\n account\\n );\\n\\n // Get the normalized price of the asset\\n Exp memory oraclePrice = Exp({ mantissa: _safeGetUnderlyingPrice(asset) });\\n\\n // Pre-compute conversion factors from vTokens -> usd\\n Exp memory vTokenPrice = mul_(Exp({ mantissa: exchangeRateMantissa }), oraclePrice);\\n Exp memory weightedVTokenPrice = mul_(weight(asset), vTokenPrice);\\n\\n // weightedCollateral += weightedVTokenPrice * vTokenBalance\\n snapshot.weightedCollateral = mul_ScalarTruncateAddUInt(\\n weightedVTokenPrice,\\n vTokenBalance,\\n snapshot.weightedCollateral\\n );\\n\\n // totalCollateral += vTokenPrice * vTokenBalance\\n snapshot.totalCollateral = mul_ScalarTruncateAddUInt(vTokenPrice, vTokenBalance, snapshot.totalCollateral);\\n\\n // borrows += oraclePrice * borrowBalance\\n snapshot.borrows = mul_ScalarTruncateAddUInt(oraclePrice, borrowBalance, snapshot.borrows);\\n\\n // Calculate effects of interacting with vTokenModify\\n if (asset == vTokenModify) {\\n // redeem effect\\n // effects += tokensToDenom * redeemTokens\\n snapshot.effects = mul_ScalarTruncateAddUInt(weightedVTokenPrice, redeemTokens, snapshot.effects);\\n\\n // borrow effect\\n // effects += oraclePrice * borrowAmount\\n snapshot.effects = mul_ScalarTruncateAddUInt(oraclePrice, borrowAmount, snapshot.effects);\\n }\\n }\\n\\n uint256 borrowPlusEffects = snapshot.borrows + snapshot.effects;\\n // These are safe, as the underflow condition is checked first\\n unchecked {\\n if (snapshot.weightedCollateral > borrowPlusEffects) {\\n snapshot.liquidity = snapshot.weightedCollateral - borrowPlusEffects;\\n snapshot.shortfall = 0;\\n } else {\\n snapshot.liquidity = 0;\\n snapshot.shortfall = borrowPlusEffects - snapshot.weightedCollateral;\\n }\\n }\\n\\n return snapshot;\\n }\\n\\n /**\\n * @dev Retrieves price from oracle for an asset and checks it is nonzero\\n * @param asset Address for asset to query price\\n * @return Underlying price\\n */\\n function _safeGetUnderlyingPrice(VToken asset) internal view returns (uint256) {\\n uint256 oraclePriceMantissa = oracle.getUnderlyingPrice(address(asset));\\n if (oraclePriceMantissa == 0) {\\n revert PriceError(address(asset));\\n }\\n return oraclePriceMantissa;\\n }\\n\\n /**\\n * @dev Return collateral factor for a market\\n * @param asset Address for asset\\n * @return Collateral factor as exponential\\n */\\n function _getCollateralFactor(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].collateralFactorMantissa });\\n }\\n\\n /**\\n * @dev Retrieves liquidation threshold for a market as an exponential\\n * @param asset Address for asset to liquidation threshold\\n * @return Liquidation threshold as exponential\\n */\\n function _getLiquidationThreshold(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].liquidationThresholdMantissa });\\n }\\n\\n /**\\n * @dev Returns supply and borrow balances of user in vToken, reverts on failure\\n * @param vToken Market to query\\n * @param user Account address\\n * @return vTokenBalance Balance of vTokens, the same as vToken.balanceOf(user)\\n * @return borrowBalance Borrowed amount, including the interest\\n * @return exchangeRateMantissa Stored exchange rate\\n */\\n function _safeGetAccountSnapshot(\\n VToken vToken,\\n address user\\n ) internal view returns (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) {\\n uint256 err;\\n (err, vTokenBalance, borrowBalance, exchangeRateMantissa) = vToken.getAccountSnapshot(user);\\n if (err != 0) {\\n revert SnapshotError(address(vToken), user);\\n }\\n return (vTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /// @notice Reverts if the call is not from expectedSender\\n /// @param expectedSender Expected transaction sender\\n function _checkSenderIs(address expectedSender) internal view {\\n if (msg.sender != expectedSender) {\\n revert UnexpectedSender(expectedSender, msg.sender);\\n }\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n /// @param market Market to check\\n /// @param action Action to check\\n function _checkActionPauseState(address market, Action action) private view {\\n if (actionPaused(market, action)) {\\n revert ActionPaused(market, action);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7c6e1c6264e4681f82a9ac1bcd9155197a930033291ee5561ad97a56006f5e9c\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.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\\n/**\\n * @title ComptrollerInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract.\\n */\\ninterface ComptrollerInterface {\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\\n\\n function exitMarket(address vToken) external returns (uint256);\\n\\n /*** Policy Hooks ***/\\n\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external;\\n\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external;\\n\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external;\\n\\n function preRepayHook(address vToken, address borrower) external;\\n\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external;\\n\\n function preSeizeHook(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower\\n ) external;\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\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 seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external;\\n\\n function isComptroller() external view returns (bool);\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 repayAmount\\n ) external view returns (uint256, uint256);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n}\\n\\n/**\\n * @title ComptrollerViewInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract, including only some util view functions.\\n */\\ninterface ComptrollerViewInterface {\\n function markets(address) external view returns (bool, uint256);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function closeFactorMantissa() external view returns (uint256);\\n\\n function liquidationIncentiveMantissa() external view returns (uint256);\\n\\n function minLiquidatableCollateral() external view returns (uint256);\\n\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function borrowCaps(address) external view returns (uint256);\\n\\n function supplyCaps(address) external view returns (uint256);\\n\\n function approvedDelegates(address user, address delegate) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xcbf7f9977472650c61345b7cbde23e81f626e1f8863bab4c6ce3dacfc7604919\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { IPrime } from \\\"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\\\";\\nimport { Action } from \\\"./ComptrollerInterface.sol\\\";\\n\\n/**\\n * @title ComptrollerStorage\\n * @author Venus\\n * @notice Storage layout for the `Comptroller` contract.\\n */\\ncontract ComptrollerStorage {\\n struct LiquidationOrder {\\n VToken vTokenCollateral;\\n VToken vTokenBorrowed;\\n uint256 repayAmount;\\n }\\n\\n struct AccountLiquiditySnapshot {\\n uint256 totalCollateral;\\n uint256 weightedCollateral;\\n uint256 borrows;\\n uint256 effects;\\n uint256 liquidity;\\n uint256 shortfall;\\n }\\n\\n struct RewardSpeeds {\\n address rewardToken;\\n uint256 supplySpeed;\\n uint256 borrowSpeed;\\n }\\n\\n struct Market {\\n // Whether or not this market is listed\\n bool isListed;\\n // 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 uint256 collateralFactorMantissa;\\n // 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 uint256 liquidationThresholdMantissa;\\n // Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n }\\n\\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 Per-account mapping of \\\"assets you are in\\\"\\n */\\n mapping(address => VToken[]) public accountAssets;\\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 /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\\n mapping(address => uint256) public borrowCaps;\\n\\n /// @notice Minimal collateral required for regular (non-batch) liquidations\\n uint256 public minLiquidatableCollateral;\\n\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\\n mapping(address => uint256) public supplyCaps;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(Action => bool)) internal _actionPaused;\\n\\n // List of Reward Distributors added\\n RewardsDistributor[] internal rewardsDistributors;\\n\\n // Used to check if rewards distributor is added\\n mapping(address => bool) internal rewardsDistributorExists;\\n\\n /// @notice Flag indicating whether forced liquidation enabled for a market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n\\n uint256 internal constant NO_ERROR = 0;\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant MIN_CLOSE_FACTOR_MANTISSA = 0.05e18; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant MAX_CLOSE_FACTOR_MANTISSA = 0.9e18; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.95e18; // 0.95\\n\\n /// Prime token address\\n IPrime public prime;\\n\\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 /**\\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[47] private __gap;\\n}\\n\",\"keccak256\":\"0x4df44cb65ac152bac2be4b4545430e703005a74a55b72e144100b16421bd8bfd\",\"license\":\"BSD-3-Clause\"},\"contracts/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title TokenErrorReporter\\n * @author Venus\\n * @notice Errors that can be thrown by the `VToken` contract.\\n */\\ncontract TokenErrorReporter {\\n uint256 public constant NO_ERROR = 0; // support legacy return codes\\n\\n error TransferNotAllowed();\\n\\n error MintFreshnessCheck();\\n\\n error RedeemFreshnessCheck();\\n error RedeemTransferOutNotPossible();\\n\\n error BorrowFreshnessCheck();\\n error BorrowCashNotAvailable();\\n error DelegateNotApproved();\\n\\n error RepayBorrowFreshnessCheck();\\n\\n error HealBorrowUnauthorized();\\n error ForceLiquidateBorrowUnauthorized();\\n\\n error LiquidateFreshnessCheck();\\n error LiquidateCollateralFreshnessCheck();\\n error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\\n error LiquidateLiquidatorIsBorrower();\\n error LiquidateCloseAmountIsZero();\\n error LiquidateCloseAmountIsUintMax();\\n\\n error LiquidateSeizeLiquidatorIsBorrower();\\n\\n error ProtocolSeizeShareTooBig();\\n\\n error SetReserveFactorFreshCheck();\\n error SetReserveFactorBoundsCheck();\\n\\n error AddReservesFactorFreshCheck(uint256 actualAddAmount);\\n\\n error ReduceReservesFreshCheck();\\n error ReduceReservesCashNotAvailable();\\n error ReduceReservesCashValidation();\\n\\n error SetInterestRateModelFreshCheck();\\n}\\n\",\"keccak256\":\"0x7a7ced1caaac2d9242659ebd50b99f308c725ce958ac9e11f7ada404b1d97a7b\",\"license\":\"BSD-3-Clause\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from \\\"./lib/constants.sol\\\";\\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 struct Exp {\\n uint256 mantissa;\\n }\\n\\n struct Double {\\n uint256 mantissa;\\n }\\n\\n uint256 internal constant EXP_SCALE = EXP_SCALE_;\\n uint256 internal constant DOUBLE_SCALE = 1e36;\\n uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;\\n uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint256) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / EXP_SCALE;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\\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 // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint256 scalar, uint256 addend) internal pure returns (uint256) {\\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 function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\\n require(n <= type(uint224).max, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\\n require(n <= type(uint32).max, 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_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a + b;\\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_(uint256 a, uint256 b) internal pure returns (uint256) {\\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) / EXP_SCALE });\\n }\\n\\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / EXP_SCALE;\\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) / DOUBLE_SCALE });\\n }\\n\\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / DOUBLE_SCALE;\\n }\\n\\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a * b;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return div_(mul_(a, EXP_SCALE), 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, DOUBLE_SCALE), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return div_(mul_(a, DOUBLE_SCALE), b.mantissa);\\n }\\n\\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a / b;\\n }\\n\\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });\\n }\\n}\\n\",\"keccak256\":\"0x8afbe8a24fe3539c124e718681ed3dcebd24c40dd53095786c0155998213b9b0\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModel.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\nabstract contract InterestRateModel {\\n /**\\n * @notice Calculates the current borrow interest rate per slot (block or second)\\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 amount of reserves the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per slot (block or second)\\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 amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\\n * @return Always true\\n */\\n function isInterestRateModel() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xc4fda1ab75ebe4b187b707c4f10c58780f343cf343c537f641dc75d3cd28ab51\",\"license\":\"BSD-3-Clause\"},\"contracts/Lens/PoolLens.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { IERC20Metadata } from \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Action, ComptrollerInterface, ComptrollerViewInterface } from \\\"../ComptrollerInterface.sol\\\";\\nimport { PoolRegistryInterface } from \\\"../Pool/PoolRegistryInterface.sol\\\";\\nimport { PoolRegistry } from \\\"../Pool/PoolRegistry.sol\\\";\\nimport { RewardsDistributor } from \\\"../Rewards/RewardsDistributor.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\n\\n/**\\n * @title PoolLens\\n * @author Venus\\n * @notice The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information\\n * for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be\\n * looked up for specific pools and markets:\\n- the vToken balance of a given user;\\n- the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address;\\n- the vToken address in a pool for a given asset;\\n- a list of all pools that support an asset;\\n- the underlying asset price of a vToken;\\n- the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\\n */\\ncontract PoolLens is ExponentialNoError, TimeManagerV8 {\\n /**\\n * @dev Struct for PoolDetails.\\n */\\n struct PoolData {\\n string name;\\n address creator;\\n address comptroller;\\n uint256 blockPosted;\\n uint256 timestampPosted;\\n string category;\\n string logoURL;\\n string description;\\n address priceOracle;\\n uint256 closeFactor;\\n uint256 liquidationIncentive;\\n uint256 minLiquidatableCollateral;\\n VTokenMetadata[] vTokens;\\n }\\n\\n /**\\n * @dev Struct for VToken.\\n */\\n struct VTokenMetadata {\\n address vToken;\\n uint256 exchangeRateCurrent;\\n uint256 supplyRatePerBlockOrTimestamp;\\n uint256 borrowRatePerBlockOrTimestamp;\\n uint256 reserveFactorMantissa;\\n uint256 supplyCaps;\\n uint256 borrowCaps;\\n uint256 totalBorrows;\\n uint256 totalReserves;\\n uint256 totalSupply;\\n uint256 totalCash;\\n bool isListed;\\n uint256 collateralFactorMantissa;\\n address underlyingAssetAddress;\\n uint256 vTokenDecimals;\\n uint256 underlyingDecimals;\\n uint256 pausedActions;\\n }\\n\\n /**\\n * @dev Struct for VTokenBalance.\\n */\\n struct VTokenBalances {\\n address vToken;\\n uint256 balanceOf;\\n uint256 borrowBalanceCurrent;\\n uint256 balanceOfUnderlying;\\n uint256 tokenBalance;\\n uint256 tokenAllowance;\\n }\\n\\n /**\\n * @dev Struct for underlyingPrice of VToken.\\n */\\n struct VTokenUnderlyingPrice {\\n address vToken;\\n uint256 underlyingPrice;\\n }\\n\\n /**\\n * @dev Struct with pending reward info for a market.\\n */\\n struct PendingReward {\\n address vTokenAddress;\\n uint256 amount;\\n }\\n\\n /**\\n * @dev Struct with reward distribution totals for a single reward token and distributor.\\n */\\n struct RewardSummary {\\n address distributorAddress;\\n address rewardTokenAddress;\\n uint256 totalRewards;\\n PendingReward[] pendingRewards;\\n }\\n\\n /**\\n * @dev Struct used in RewardDistributor to save last updated market state.\\n */\\n struct RewardTokenState {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number or timestamp the index was last updated at\\n uint256 blockOrTimestamp;\\n // The block number or timestamp at which to stop rewards\\n uint256 lastRewardingBlockOrTimestamp;\\n }\\n\\n /**\\n * @dev Struct with bad debt of a market denominated\\n */\\n struct BadDebt {\\n address vTokenAddress;\\n uint256 badDebtUsd;\\n }\\n\\n /**\\n * @dev Struct with bad debt total denominated in usd for a pool and an array of BadDebt structs for each market\\n */\\n struct BadDebtSummary {\\n address comptroller;\\n uint256 totalBadDebtUsd;\\n BadDebt[] badDebts;\\n }\\n\\n /// @notice Address of the core pool comptroller (all markets are returned for this pool, including paused ones)\\n address public immutable corePoolComptroller;\\n\\n /**\\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @param corePoolComptroller_ The address of the core pool comptroller\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(\\n bool timeBased_,\\n uint256 blocksPerYear_,\\n address corePoolComptroller_\\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\\n corePoolComptroller = corePoolComptroller_;\\n }\\n\\n /**\\n * @notice Queries the user's supply/borrow balances in vTokens\\n * @param vTokens The list of vToken addresses\\n * @param account The user Account\\n * @return A list of structs containing balances data\\n */\\n function vTokenBalancesAll(VToken[] calldata vTokens, address account) external returns (VTokenBalances[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenBalances[] memory res = new VTokenBalances[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenBalances(vTokens[i], account);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Queries all pools with addtional details for each of them\\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @return Arrays of all Venus pools' data\\n */\\n function getAllPools(address poolRegistryAddress) external view returns (PoolData[] memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n PoolRegistry.VenusPool[] memory venusPools = poolRegistryInterface.getAllPools();\\n uint256 poolLength = venusPools.length;\\n\\n PoolData[] memory poolDataItems = new PoolData[](poolLength);\\n\\n for (uint256 i; i < poolLength; ++i) {\\n PoolRegistry.VenusPool memory venusPool = venusPools[i];\\n PoolData memory poolData = getPoolDataFromVenusPool(poolRegistryAddress, venusPool);\\n poolDataItems[i] = poolData;\\n }\\n\\n return poolDataItems;\\n }\\n\\n /**\\n * @notice Queries the details of a pool identified by Comptroller address\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param comptroller The Comptroller implementation address\\n * @return PoolData structure containing the details of the pool\\n */\\n function getPoolByComptroller(\\n address poolRegistryAddress,\\n address comptroller\\n ) external view returns (PoolData memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return getPoolDataFromVenusPool(poolRegistryAddress, poolRegistryInterface.getPoolByComptroller(comptroller));\\n }\\n\\n /**\\n * @notice Returns vToken holding the specified underlying asset in the specified pool\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param comptroller The pool comptroller\\n * @param asset The underlyingAsset of VToken\\n * @return Address of the vToken\\n */\\n function getVTokenForAsset(\\n address poolRegistryAddress,\\n address comptroller,\\n address asset\\n ) external view returns (address) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return poolRegistryInterface.getVTokenForAsset(comptroller, asset);\\n }\\n\\n /**\\n * @notice Returns all pools that support the specified underlying asset\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param asset The underlying asset of vToken\\n * @return A list of Comptroller contracts\\n */\\n function getPoolsSupportedByAsset(\\n address poolRegistryAddress,\\n address asset\\n ) external view returns (address[] memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return poolRegistryInterface.getPoolsSupportedByAsset(asset);\\n }\\n\\n /**\\n * @notice Returns the price data for the underlying assets of the specified vTokens\\n * @param vTokens The list of vToken addresses\\n * @return An array containing the price data for each asset\\n */\\n function vTokenUnderlyingPriceAll(\\n VToken[] calldata vTokens\\n ) external view returns (VTokenUnderlyingPrice[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenUnderlyingPrice[] memory res = new VTokenUnderlyingPrice[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenUnderlyingPrice(vTokens[i]);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Returns the pending rewards for a user for a given pool.\\n * @param account The user account.\\n * @param comptrollerAddress address\\n * @return Pending rewards array\\n */\\n function getPendingRewards(\\n address account,\\n address comptrollerAddress\\n ) external view returns (RewardSummary[] memory) {\\n VToken[] memory markets = _getMarkets(ComptrollerInterface(comptrollerAddress));\\n RewardsDistributor[] memory rewardsDistributors = ComptrollerViewInterface(comptrollerAddress)\\n .getRewardDistributors();\\n RewardSummary[] memory rewardSummary = new RewardSummary[](rewardsDistributors.length);\\n for (uint256 i; i < rewardsDistributors.length; ++i) {\\n RewardSummary memory reward;\\n reward.distributorAddress = address(rewardsDistributors[i]);\\n reward.rewardTokenAddress = address(rewardsDistributors[i].rewardToken());\\n reward.totalRewards = rewardsDistributors[i].rewardTokenAccrued(account);\\n reward.pendingRewards = _calculateNotDistributedAwards(account, markets, rewardsDistributors[i]);\\n rewardSummary[i] = reward;\\n }\\n return rewardSummary;\\n }\\n\\n /**\\n * @notice Returns a summary of a pool's bad debt broken down by market\\n *\\n * @param comptrollerAddress Address of the comptroller\\n *\\n * @return badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and\\n * a break down of bad debt by market\\n */\\n function getPoolBadDebt(address comptrollerAddress) external view returns (BadDebtSummary memory) {\\n uint256 totalBadDebtUsd;\\n\\n // Get every listed market in the pool\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\\n VToken[] memory markets = _getMarkets(ComptrollerInterface(comptrollerAddress));\\n ResilientOracleInterface priceOracle = comptroller.oracle();\\n\\n BadDebt[] memory badDebts = new BadDebt[](markets.length);\\n\\n BadDebtSummary memory badDebtSummary;\\n badDebtSummary.comptroller = comptrollerAddress;\\n badDebtSummary.badDebts = badDebts;\\n\\n // // Calculate the bad debt is USD per market\\n for (uint256 i; i < markets.length; ++i) {\\n BadDebt memory badDebt;\\n badDebt.vTokenAddress = address(markets[i]);\\n badDebt.badDebtUsd =\\n (VToken(address(markets[i])).badDebt() * priceOracle.getUnderlyingPrice(address(markets[i]))) /\\n EXP_SCALE;\\n badDebtSummary.badDebts[i] = badDebt;\\n totalBadDebtUsd = totalBadDebtUsd + badDebt.badDebtUsd;\\n }\\n\\n badDebtSummary.totalBadDebtUsd = totalBadDebtUsd;\\n\\n return badDebtSummary;\\n }\\n\\n /**\\n * @notice Queries the user's supply/borrow balances in the specified vToken\\n * @param vToken vToken address\\n * @param account The user Account\\n * @return A struct containing the balances data\\n */\\n function vTokenBalances(VToken vToken, address account) public returns (VTokenBalances memory) {\\n uint256 balanceOf = vToken.balanceOf(account);\\n uint256 borrowBalanceCurrent = vToken.borrowBalanceCurrent(account);\\n uint256 balanceOfUnderlying = vToken.balanceOfUnderlying(account);\\n uint256 tokenBalance;\\n uint256 tokenAllowance;\\n\\n IERC20 underlying = IERC20(vToken.underlying());\\n tokenBalance = underlying.balanceOf(account);\\n tokenAllowance = underlying.allowance(account, address(vToken));\\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 Queries additional information for the pool\\n * @param poolRegistryAddress Address of the PoolRegistry\\n * @param venusPool The VenusPool Object from PoolRegistry\\n * @return Enriched PoolData\\n */\\n function getPoolDataFromVenusPool(\\n address poolRegistryAddress,\\n PoolRegistry.VenusPool memory venusPool\\n ) public view returns (PoolData memory) {\\n // Get tokens in the Pool\\n ComptrollerInterface comptrollerInstance = ComptrollerInterface(venusPool.comptroller);\\n\\n VToken[] memory vTokens = _getMarkets(comptrollerInstance);\\n\\n VTokenMetadata[] memory vTokenMetadataItems = vTokenMetadataAll(vTokens);\\n\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n\\n PoolRegistry.VenusPoolMetaData memory venusPoolMetaData = poolRegistryInterface.getVenusPoolMetadata(\\n venusPool.comptroller\\n );\\n\\n ComptrollerViewInterface comptrollerViewInstance = ComptrollerViewInterface(venusPool.comptroller);\\n\\n PoolData memory poolData = PoolData({\\n name: venusPool.name,\\n creator: venusPool.creator,\\n comptroller: venusPool.comptroller,\\n blockPosted: venusPool.blockPosted,\\n timestampPosted: venusPool.timestampPosted,\\n category: venusPoolMetaData.category,\\n logoURL: venusPoolMetaData.logoURL,\\n description: venusPoolMetaData.description,\\n vTokens: vTokenMetadataItems,\\n priceOracle: address(comptrollerViewInstance.oracle()),\\n closeFactor: comptrollerViewInstance.closeFactorMantissa(),\\n liquidationIncentive: comptrollerViewInstance.liquidationIncentiveMantissa(),\\n minLiquidatableCollateral: comptrollerViewInstance.minLiquidatableCollateral()\\n });\\n\\n return poolData;\\n }\\n\\n /**\\n * @notice Returns the metadata of VToken\\n * @param vToken The address of vToken\\n * @return VTokenMetadata struct\\n */\\n function vTokenMetadata(VToken vToken) public view returns (VTokenMetadata memory) {\\n uint256 exchangeRateCurrent = vToken.exchangeRateStored();\\n address comptrollerAddress = address(vToken.comptroller());\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\\n (bool isListed, uint256 collateralFactorMantissa) = comptroller.markets(address(vToken));\\n\\n address underlyingAssetAddress = vToken.underlying();\\n uint256 underlyingDecimals = IERC20Metadata(underlyingAssetAddress).decimals();\\n\\n uint256 pausedActions;\\n for (uint8 i; i <= uint8(type(Action).max); ++i) {\\n uint256 paused = ComptrollerInterface(comptrollerAddress).actionPaused(address(vToken), Action(i)) ? 1 : 0;\\n pausedActions |= paused << i;\\n }\\n\\n uint256 supplyRatePerBlock;\\n\\n if (vToken.totalSupply() > 0) {\\n supplyRatePerBlock = vToken.supplyRatePerBlock();\\n }\\n\\n return\\n VTokenMetadata({\\n vToken: address(vToken),\\n exchangeRateCurrent: exchangeRateCurrent,\\n supplyRatePerBlockOrTimestamp: supplyRatePerBlock,\\n borrowRatePerBlockOrTimestamp: vToken.borrowRatePerBlock(),\\n reserveFactorMantissa: vToken.reserveFactorMantissa(),\\n supplyCaps: comptroller.supplyCaps(address(vToken)),\\n borrowCaps: comptroller.borrowCaps(address(vToken)),\\n totalBorrows: vToken.totalBorrows(),\\n totalReserves: vToken.totalReserves(),\\n totalSupply: vToken.totalSupply(),\\n totalCash: vToken.getCash(),\\n isListed: isListed,\\n collateralFactorMantissa: collateralFactorMantissa,\\n underlyingAssetAddress: underlyingAssetAddress,\\n vTokenDecimals: vToken.decimals(),\\n underlyingDecimals: underlyingDecimals,\\n pausedActions: pausedActions\\n });\\n }\\n\\n /**\\n * @notice Returns the metadata of all VTokens\\n * @param vTokens The list of vToken addresses\\n * @return An array of VTokenMetadata structs\\n */\\n function vTokenMetadataAll(VToken[] memory vTokens) public view returns (VTokenMetadata[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenMetadata[] memory res = new VTokenMetadata[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenMetadata(vTokens[i]);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Returns the price data for the underlying asset of the specified vToken\\n * @param vToken vToken address\\n * @return The price data for each asset\\n */\\n function vTokenUnderlyingPrice(VToken vToken) public view returns (VTokenUnderlyingPrice memory) {\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(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 Returns markets from a comptroller. For the core pool, all markets are returned.\\n * For other pools, markets with zero internalCash are filtered.\\n * @param comptroller The comptroller to query\\n * @return An array of VToken addresses\\n */\\n function _getMarkets(ComptrollerInterface comptroller) internal view returns (VToken[] memory) {\\n VToken[] memory allMarkets = comptroller.getAllMarkets();\\n\\n if (address(comptroller) == corePoolComptroller) {\\n return allMarkets;\\n }\\n\\n // Single-loop filter: pack active markets to the front of allMarkets\\n uint256 count;\\n uint256 len = allMarkets.length;\\n for (uint256 i; i < len; ++i) {\\n if (allMarkets[i].internalCash() > 0) {\\n allMarkets[count] = allMarkets[i];\\n ++count;\\n }\\n }\\n\\n // Trim the array to the active count\\n assembly {\\n mstore(allMarkets, count)\\n }\\n\\n return allMarkets;\\n }\\n\\n function _calculateNotDistributedAwards(\\n address account,\\n VToken[] memory markets,\\n RewardsDistributor rewardsDistributor\\n ) internal view returns (PendingReward[] memory) {\\n PendingReward[] memory pendingRewards = new PendingReward[](markets.length);\\n\\n for (uint256 i; i < markets.length; ++i) {\\n // Market borrow and supply state we will modify update in-memory, in order to not modify storage\\n RewardTokenState memory borrowState;\\n RewardTokenState memory supplyState;\\n\\n if (isTimeBased) {\\n (\\n borrowState.index,\\n borrowState.blockOrTimestamp,\\n borrowState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenBorrowStateTimeBased(address(markets[i]));\\n (\\n supplyState.index,\\n supplyState.blockOrTimestamp,\\n supplyState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenSupplyStateTimeBased(address(markets[i]));\\n } else {\\n (\\n borrowState.index,\\n borrowState.blockOrTimestamp,\\n borrowState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenBorrowState(address(markets[i]));\\n (\\n supplyState.index,\\n supplyState.blockOrTimestamp,\\n supplyState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenSupplyState(address(markets[i]));\\n }\\n\\n Exp memory marketBorrowIndex = Exp({ mantissa: markets[i].borrowIndex() });\\n\\n // Update market supply and borrow index in-memory\\n updateMarketBorrowIndex(address(markets[i]), rewardsDistributor, borrowState, marketBorrowIndex);\\n updateMarketSupplyIndex(address(markets[i]), rewardsDistributor, supplyState);\\n\\n // Calculate pending rewards\\n uint256 borrowReward = calculateBorrowerReward(\\n address(markets[i]),\\n rewardsDistributor,\\n account,\\n borrowState,\\n marketBorrowIndex\\n );\\n uint256 supplyReward = calculateSupplierReward(\\n address(markets[i]),\\n rewardsDistributor,\\n account,\\n supplyState\\n );\\n\\n PendingReward memory pendingReward;\\n pendingReward.vTokenAddress = address(markets[i]);\\n pendingReward.amount = borrowReward + supplyReward;\\n pendingRewards[i] = pendingReward;\\n }\\n return pendingRewards;\\n }\\n\\n function updateMarketBorrowIndex(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n RewardTokenState memory borrowState,\\n Exp memory marketBorrowIndex\\n ) internal view {\\n uint256 borrowSpeed = rewardsDistributor.rewardTokenBorrowSpeeds(vToken);\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (\\n borrowState.lastRewardingBlockOrTimestamp > 0 &&\\n blockNumberOrTimestamp > borrowState.lastRewardingBlockOrTimestamp\\n ) {\\n blockNumberOrTimestamp = borrowState.lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, borrowState.blockOrTimestamp);\\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\\n // Remove the total earned interest rate since the opening of the market from total borrows\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, borrowSpeed);\\n Double memory ratio = borrowAmount > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\\n } else if (deltaBlocksOrTimestamp > 0) {\\n borrowState.blockOrTimestamp = blockNumberOrTimestamp;\\n }\\n }\\n\\n function updateMarketSupplyIndex(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n RewardTokenState memory supplyState\\n ) internal view {\\n uint256 supplySpeed = rewardsDistributor.rewardTokenSupplySpeeds(vToken);\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (\\n supplyState.lastRewardingBlockOrTimestamp > 0 &&\\n blockNumberOrTimestamp > supplyState.lastRewardingBlockOrTimestamp\\n ) {\\n blockNumberOrTimestamp = supplyState.lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, supplyState.blockOrTimestamp);\\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, supplySpeed);\\n Double memory ratio = supplyTokens > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\\n } else if (deltaBlocksOrTimestamp > 0) {\\n supplyState.blockOrTimestamp = blockNumberOrTimestamp;\\n }\\n }\\n\\n function calculateBorrowerReward(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n address borrower,\\n RewardTokenState memory borrowState,\\n Exp memory marketBorrowIndex\\n ) internal view returns (uint256) {\\n Double memory borrowIndex = Double({ mantissa: borrowState.index });\\n Double memory borrowerIndex = Double({\\n mantissa: rewardsDistributor.rewardTokenBorrowerIndex(vToken, borrower)\\n });\\n if (borrowerIndex.mantissa == 0 && borrowIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set\\n borrowerIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\\n }\\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n return borrowerDelta;\\n }\\n\\n function calculateSupplierReward(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n address supplier,\\n RewardTokenState memory supplyState\\n ) internal view returns (uint256) {\\n Double memory supplyIndex = Double({ mantissa: supplyState.index });\\n Double memory supplierIndex = Double({\\n mantissa: rewardsDistributor.rewardTokenSupplierIndex(vToken, supplier)\\n });\\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\\n // Covers the case where users supplied tokens before the market's supply state index was set\\n supplierIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\\n }\\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n return supplierDelta;\\n }\\n}\\n\",\"keccak256\":\"0xfe3f00ebb7f0b5c98ee03cf1cfa1a013a56984cf6879373c70a74b3d9d0db399\",\"license\":\"BSD-3-Clause\"},\"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\",\"keccak256\":\"0x4c25e30635485d162177effa384eee51768b0141a567a0da16ff6ad673274166\",\"license\":\"BSD-3-Clause\"},\"contracts/Pool/PoolRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\nimport { PoolRegistryInterface } from \\\"./PoolRegistryInterface.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"../lib/validators.sol\\\";\\n\\n/**\\n * @title PoolRegistry\\n * @author Venus\\n * @notice The Isolated Pools architecture centers around the `PoolRegistry` contract. The `PoolRegistry` maintains a directory of isolated lending\\n * pools and can perform actions like creating and registering new pools, adding new markets to existing pools, setting and updating the pool's required\\n * metadata, and providing the getter methods to get information on the pools.\\n *\\n * Isolated lending has three main components: PoolRegistry, pools, and markets. The PoolRegistry is responsible for managing pools.\\n * It can create new pools, update pool metadata and manage markets within pools. PoolRegistry contains getter methods to get the details of\\n * any existing pool like `getVTokenForAsset` and `getPoolsSupportedByAsset`. It also contains methods for updating pool metadata (`updatePoolMetadata`)\\n * and setting pool name (`setPoolName`).\\n *\\n * The directory of pools is managed through two mappings: `_poolByComptroller` which is a hashmap with the comptroller address as the key and `VenusPool` as\\n * the value and `_poolsByID` which is an array of comptroller addresses. Individual pools can be accessed by calling `getPoolByComptroller` with the pool's\\n * comptroller address. `_poolsByID` is used to iterate through all of the pools.\\n *\\n * PoolRegistry also contains a map of asset addresses called `_supportedPools` that maps to an array of assets suppored by each pool. This array of pools by\\n * asset is retrieved by calling `getPoolsSupportedByAsset`.\\n *\\n * PoolRegistry registers new isolated pools in the directory with the `createRegistryPool` method. Isolated pools are composed of independent markets with\\n * specific assets and custom risk management configurations according to their markets.\\n */\\ncontract PoolRegistry is Ownable2StepUpgradeable, AccessControlledV8, PoolRegistryInterface {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n struct AddMarketInput {\\n VToken vToken;\\n uint256 collateralFactor;\\n uint256 liquidationThreshold;\\n uint256 initialSupply;\\n address vTokenReceiver;\\n uint256 supplyCap;\\n uint256 borrowCap;\\n }\\n\\n uint256 internal constant MAX_POOL_NAME_LENGTH = 100;\\n\\n /**\\n * @notice Maps pool's comptroller address to metadata.\\n */\\n mapping(address => VenusPoolMetaData) public metadata;\\n\\n /**\\n * @dev Maps pool ID to pool's comptroller address\\n */\\n mapping(uint256 => address) private _poolsByID;\\n\\n /**\\n * @dev Total number of pools created.\\n */\\n uint256 private _numberOfPools;\\n\\n /**\\n * @dev Maps comptroller address to Venus pool Index.\\n */\\n mapping(address => VenusPool) private _poolByComptroller;\\n\\n /**\\n * @dev Maps pool's comptroller address to asset to vToken.\\n */\\n mapping(address => mapping(address => address)) private _vTokens;\\n\\n /**\\n * @dev Maps asset to list of supported pools.\\n */\\n mapping(address => address[]) private _supportedPools;\\n\\n /**\\n * @notice Emitted when a new Venus pool is added to the directory.\\n */\\n event PoolRegistered(address indexed comptroller, VenusPool pool);\\n\\n /**\\n * @notice Emitted when a pool name is set.\\n */\\n event PoolNameSet(address indexed comptroller, string oldName, string newName);\\n\\n /**\\n * @notice Emitted when a pool metadata is updated.\\n */\\n event PoolMetadataUpdated(\\n address indexed comptroller,\\n VenusPoolMetaData oldMetadata,\\n VenusPoolMetaData newMetadata\\n );\\n\\n /**\\n * @notice Emitted when a Market is added to the pool.\\n */\\n event MarketAdded(address indexed comptroller, address indexed vTokenAddress);\\n\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor() {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializes the deployer to owner\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(address accessControlManager_) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n /**\\n * @notice Adds a new Venus pool to the directory\\n * @dev Price oracle must be configured before adding a pool\\n * @param name The name of the pool\\n * @param comptroller Pool's Comptroller contract\\n * @param closeFactor The pool's close factor (scaled by 1e18)\\n * @param liquidationIncentive The pool's liquidation incentive (scaled by 1e18)\\n * @param minLiquidatableCollateral Minimal collateral for regular (non-batch) liquidations flow\\n * @return index The index of the registered Venus pool\\n * @custom:error ZeroAddressNotAllowed is thrown when Comptroller address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\\n */\\n function addPool(\\n string calldata name,\\n Comptroller comptroller,\\n uint256 closeFactor,\\n uint256 liquidationIncentive,\\n uint256 minLiquidatableCollateral\\n ) external virtual returns (uint256 index) {\\n _checkAccessAllowed(\\\"addPool(string,address,uint256,uint256,uint256)\\\");\\n // Input validation\\n ensureNonzeroAddress(address(comptroller));\\n ensureNonzeroAddress(address(comptroller.oracle()));\\n\\n uint256 poolId = _registerPool(name, address(comptroller));\\n\\n // Set Venus pool parameters\\n comptroller.setCloseFactor(closeFactor);\\n comptroller.setLiquidationIncentive(liquidationIncentive);\\n comptroller.setMinLiquidatableCollateral(minLiquidatableCollateral);\\n\\n return poolId;\\n }\\n\\n /**\\n * @notice Add a market to an existing pool and then mint to provide initial supply\\n * @param input The structure describing the parameters for adding a market to a pool\\n * @custom:error ZeroAddressNotAllowed is thrown when vToken address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when vTokenReceiver address is zero\\n */\\n function addMarket(AddMarketInput memory input) external {\\n _checkAccessAllowed(\\\"addMarket(AddMarketInput)\\\");\\n ensureNonzeroAddress(address(input.vToken));\\n ensureNonzeroAddress(input.vTokenReceiver);\\n require(input.initialSupply > 0, \\\"PoolRegistry: initialSupply is zero\\\");\\n\\n VToken vToken = input.vToken;\\n address vTokenAddress = address(vToken);\\n address comptrollerAddress = address(vToken.comptroller());\\n Comptroller comptroller = Comptroller(comptrollerAddress);\\n address underlyingAddress = vToken.underlying();\\n IERC20Upgradeable underlying = IERC20Upgradeable(underlyingAddress);\\n\\n require(_poolByComptroller[comptrollerAddress].creator != address(0), \\\"PoolRegistry: Pool not registered\\\");\\n // solhint-disable-next-line reason-string\\n require(\\n _vTokens[comptrollerAddress][underlyingAddress] == address(0),\\n \\\"PoolRegistry: Market already added for asset comptroller combination\\\"\\n );\\n\\n comptroller.supportMarket(vToken);\\n comptroller.setCollateralFactor(vToken, input.collateralFactor, input.liquidationThreshold);\\n\\n uint256[] memory newSupplyCaps = new uint256[](1);\\n uint256[] memory newBorrowCaps = new uint256[](1);\\n VToken[] memory vTokens = new VToken[](1);\\n\\n newSupplyCaps[0] = input.supplyCap;\\n newBorrowCaps[0] = input.borrowCap;\\n vTokens[0] = vToken;\\n\\n comptroller.setMarketSupplyCaps(vTokens, newSupplyCaps);\\n comptroller.setMarketBorrowCaps(vTokens, newBorrowCaps);\\n\\n _vTokens[comptrollerAddress][underlyingAddress] = vTokenAddress;\\n _supportedPools[underlyingAddress].push(comptrollerAddress);\\n\\n uint256 amountToSupply = _transferIn(underlying, msg.sender, input.initialSupply);\\n underlying.forceApprove(vTokenAddress, 0);\\n underlying.forceApprove(vTokenAddress, amountToSupply);\\n vToken.mintBehalf(input.vTokenReceiver, amountToSupply);\\n\\n emit MarketAdded(comptrollerAddress, vTokenAddress);\\n }\\n\\n /**\\n * @notice Modify existing Venus pool name\\n * @param comptroller Pool's Comptroller\\n * @param name New pool name\\n */\\n function setPoolName(address comptroller, string calldata name) external {\\n _checkAccessAllowed(\\\"setPoolName(address,string)\\\");\\n _ensureValidName(name);\\n VenusPool storage pool = _poolByComptroller[comptroller];\\n string memory oldName = pool.name;\\n pool.name = name;\\n emit PoolNameSet(comptroller, oldName, name);\\n }\\n\\n /**\\n * @notice Update metadata of an existing pool\\n * @param comptroller Pool's Comptroller\\n * @param metadata_ New pool metadata\\n */\\n function updatePoolMetadata(address comptroller, VenusPoolMetaData calldata metadata_) external {\\n _checkAccessAllowed(\\\"updatePoolMetadata(address,VenusPoolMetaData)\\\");\\n VenusPoolMetaData memory oldMetadata = metadata[comptroller];\\n metadata[comptroller] = metadata_;\\n emit PoolMetadataUpdated(comptroller, oldMetadata, metadata_);\\n }\\n\\n /**\\n * @notice Returns arrays of all Venus pools' data\\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\\n * @return A list of all pools within PoolRegistry, with details for each pool\\n */\\n function getAllPools() external view override returns (VenusPool[] memory) {\\n uint256 numberOfPools_ = _numberOfPools; // storage load to save gas\\n VenusPool[] memory _pools = new VenusPool[](numberOfPools_);\\n for (uint256 i = 1; i <= numberOfPools_; ++i) {\\n address comptroller = _poolsByID[i];\\n _pools[i - 1] = (_poolByComptroller[comptroller]);\\n }\\n return _pools;\\n }\\n\\n /**\\n * @param comptroller The comptroller proxy address associated to the pool\\n * @return Returns Venus pool\\n */\\n function getPoolByComptroller(address comptroller) external view override returns (VenusPool memory) {\\n return _poolByComptroller[comptroller];\\n }\\n\\n /**\\n * @param comptroller comptroller of Venus pool\\n * @return Returns Metadata of Venus pool\\n */\\n function getVenusPoolMetadata(address comptroller) external view override returns (VenusPoolMetaData memory) {\\n return metadata[comptroller];\\n }\\n\\n function getVTokenForAsset(address comptroller, address asset) external view override returns (address) {\\n return _vTokens[comptroller][asset];\\n }\\n\\n function getPoolsSupportedByAsset(address asset) external view override returns (address[] memory) {\\n return _supportedPools[asset];\\n }\\n\\n /**\\n * @dev Adds a new Venus pool to the directory (without checking msg.sender).\\n * @param name The name of the pool\\n * @param comptroller The pool's Comptroller proxy contract address\\n * @return The index of the registered Venus pool\\n */\\n function _registerPool(string calldata name, address comptroller) internal returns (uint256) {\\n VenusPool storage storedPool = _poolByComptroller[comptroller];\\n\\n require(storedPool.creator == address(0), \\\"PoolRegistry: Pool already exists in the directory.\\\");\\n _ensureValidName(name);\\n\\n ++_numberOfPools;\\n uint256 numberOfPools_ = _numberOfPools; // cache on stack to save storage read gas\\n\\n VenusPool memory pool = VenusPool(name, msg.sender, comptroller, block.number, block.timestamp);\\n\\n _poolsByID[numberOfPools_] = comptroller;\\n _poolByComptroller[comptroller] = pool;\\n\\n emit PoolRegistered(comptroller, pool);\\n return numberOfPools_;\\n }\\n\\n function _transferIn(IERC20Upgradeable token, address from, uint256 amount) internal returns (uint256) {\\n uint256 balanceBefore = token.balanceOf(address(this));\\n token.safeTransferFrom(from, address(this), amount);\\n uint256 balanceAfter = token.balanceOf(address(this));\\n return balanceAfter - balanceBefore;\\n }\\n\\n function _ensureValidName(string calldata name) internal pure {\\n require(bytes(name).length <= MAX_POOL_NAME_LENGTH, \\\"Pool's name is too large\\\");\\n }\\n}\\n\",\"keccak256\":\"0xafbb871f7b4db3ef439d846baa5f18a136192f9b43ea695c81262a77b06c4b25\",\"license\":\"BSD-3-Clause\"},\"contracts/Pool/PoolRegistryInterface.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 /**\\n * @notice Struct for a Venus interest rate pool metadata.\\n */\\n struct VenusPoolMetaData {\\n string category;\\n string logoURL;\\n string description;\\n }\\n\\n /// @notice Get all pools in PoolRegistry\\n function getAllPools() external view returns (VenusPool[] memory);\\n\\n /// @notice Get a pool by comptroller address\\n function getPoolByComptroller(address comptroller) external view returns (VenusPool memory);\\n\\n /// @notice Get the address of the VToken contract in the Pool where the underlying token is the provided 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 /// @notice Get the metadata of a Pool by comptroller address\\n function getVenusPoolMetadata(address comptroller) external view returns (VenusPoolMetaData memory);\\n}\\n\",\"keccak256\":\"0x7b39cda3b372a686501ce3c2aad288c6af410148110318249d75d4516729c92c\",\"license\":\"BSD-3-Clause\"},\"contracts/Rewards/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\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 { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"../MaxLoopsLimitHelper.sol\\\";\\nimport { RewardsDistributorStorage } from \\\"./RewardsDistributorStorage.sol\\\";\\n\\n/**\\n * @title `RewardsDistributor`\\n * @author Venus\\n * @notice Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol.\\n * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward\\n * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool.\\n * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward\\n * token to be released each slot (block or second) for borrowers and suppliers, which is distributed based on a user\\u2019s percentage of the borrows or supplies\\n * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting\\n * their contributor reward token speed, which similarly allocates a fixed amount of reward token per slot (block or second).\\n *\\n * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed\\n * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized\\n * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\\n */\\ncontract RewardsDistributor is\\n ExponentialNoError,\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n MaxLoopsLimitHelper,\\n RewardsDistributorStorage,\\n TimeManagerV8\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice The initial REWARD TOKEN index for a market\\n uint224 public constant INITIAL_INDEX = 1e36;\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a supplier\\n event DistributedSupplierRewardToken(\\n VToken indexed vToken,\\n address indexed supplier,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenSupplyIndex\\n );\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a borrower\\n event DistributedBorrowerRewardToken(\\n VToken indexed vToken,\\n address indexed borrower,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenBorrowIndex\\n );\\n\\n /// @notice Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when REWARD TOKEN is granted by admin\\n event RewardTokenGranted(address indexed recipient, uint256 amount);\\n\\n /// @notice Emitted when a new REWARD TOKEN speed is set for a contributor\\n event ContributorRewardTokenSpeedUpdated(address indexed contributor, uint256 newSpeed);\\n\\n /// @notice Emitted when a market is initialized\\n event MarketInitialized(address indexed vToken);\\n\\n /// @notice Emitted when a reward token supply index is updated\\n event RewardTokenSupplyIndexUpdated(address indexed vToken);\\n\\n /// @notice Emitted when a reward token borrow index is updated\\n event RewardTokenBorrowIndexUpdated(address indexed vToken, Exp marketBorrowIndex);\\n\\n /// @notice Emitted when a reward for contributor is updated\\n event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued);\\n\\n /// @notice Emitted when a reward token last rewarding block for supply is updated\\n event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding block for borrow is updated\\n event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding timestamp for supply is updated\\n event SupplyLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\\n\\n /// @notice Emitted when a reward token last rewarding timestamp for borrow is updated\\n event BorrowLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\\n\\n modifier onlyComptroller() {\\n require(address(comptroller) == msg.sender, \\\"Only comptroller can call this function\\\");\\n _;\\n }\\n\\n /**\\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice RewardsDistributor initializer\\n * @dev Initializes the deployer to owner\\n * @param comptroller_ Comptroller to attach the reward distributor to\\n * @param rewardToken_ Reward token to distribute\\n * @param loopsLimit_ Maximum number of iterations for the loops in this contract\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(\\n Comptroller comptroller_,\\n IERC20Upgradeable rewardToken_,\\n uint256 loopsLimit_,\\n address accessControlManager_\\n ) external initializer {\\n comptroller = comptroller_;\\n rewardToken = rewardToken_;\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n\\n _setMaxLoopsLimit(loopsLimit_);\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken\\n * @param vToken The address of the vToken to be initialized\\n * @custom:event MarketInitialized emits on success\\n * @custom:access Only Comptroller\\n */\\n function initializeMarket(address vToken) external onlyComptroller {\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n isTimeBased\\n ? _initializeMarketTimestampBased(vToken, blockNumberOrTimestamp)\\n : _initializeMarketBlockBased(vToken, safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\"));\\n\\n emit MarketInitialized(vToken);\\n }\\n\\n /*** Reward Token Distribution ***/\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them\\n * Borrowers will begin to accrue after the first interaction with the protocol.\\n * @dev This function should only be called when the user has a borrow position in the market\\n * (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook)\\n * We avoid an external call to check if they are in the market to save gas because this function is called in many places\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function distributeBorrowerRewardToken(\\n address vToken,\\n address borrower,\\n Exp memory marketBorrowIndex\\n ) external onlyComptroller {\\n _distributeBorrowerRewardToken(vToken, borrower, marketBorrowIndex);\\n }\\n\\n function updateRewardTokenSupplyIndex(address vToken) external onlyComptroller {\\n _updateRewardTokenSupplyIndex(vToken);\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the recipient\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\\n * @param recipient The address of the recipient to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n */\\n function grantRewardToken(address recipient, uint256 amount) external onlyOwner {\\n uint256 amountLeft = _grantRewardToken(recipient, amount);\\n require(amountLeft == 0, \\\"insufficient rewardToken for grant\\\");\\n emit RewardTokenGranted(recipient, amount);\\n }\\n\\n function updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) external onlyComptroller {\\n _updateRewardTokenBorrowIndex(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN borrow and supply speeds for the specified markets\\n * @param vTokens The markets whose REWARD TOKEN speed to update\\n * @param supplySpeeds New supply-side REWARD TOKEN speed for the corresponding market\\n * @param borrowSpeeds New borrow-side REWARD TOKEN speed for the corresponding market\\n */\\n function setRewardTokenSpeeds(\\n VToken[] memory vTokens,\\n uint256[] memory supplySpeeds,\\n uint256[] memory borrowSpeeds\\n ) external {\\n _checkAccessAllowed(\\\"setRewardTokenSpeeds(address[],uint256[],uint256[])\\\");\\n uint256 numTokens = vTokens.length;\\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \\\"invalid setRewardTokenSpeeds\\\");\\n\\n for (uint256 i; i < numTokens; ++i) {\\n _setRewardTokenSpeed(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for the specified markets, used when contract is block based\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market\\n * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market\\n */\\n function setLastRewardingBlocks(\\n VToken[] calldata vTokens,\\n uint32[] calldata supplyLastRewardingBlocks,\\n uint32[] calldata borrowLastRewardingBlocks\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlocks(address[],uint32[],uint32[])\\\");\\n require(!isTimeBased, \\\"Block-based operation only\\\");\\n\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length,\\n \\\"RewardsDistributor::setLastRewardingBlocks invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlock(vTokens[i], supplyLastRewardingBlocks[i], borrowLastRewardingBlocks[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block timestamp for the specified markets, used when contract is time based\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlockTimestamps New supply-side REWARD TOKEN last rewarding block timestamp for the corresponding market\\n * @param borrowLastRewardingBlockTimestamps New borrow-side REWARD TOKEN last rewarding block timestamp for the corresponding market\\n */\\n function setLastRewardingBlockTimestamps(\\n VToken[] calldata vTokens,\\n uint256[] calldata supplyLastRewardingBlockTimestamps,\\n uint256[] calldata borrowLastRewardingBlockTimestamps\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlockTimestamps(address[],uint256[],uint256[])\\\");\\n require(isTimeBased, \\\"Time-based operation only\\\");\\n\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlockTimestamps.length &&\\n numTokens == borrowLastRewardingBlockTimestamps.length,\\n \\\"RewardsDistributor::setLastRewardingBlockTimestamps invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlockTimestamp(\\n vTokens[i],\\n supplyLastRewardingBlockTimestamps[i],\\n borrowLastRewardingBlockTimestamps[i]\\n );\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single contributor\\n * @param contributor The contributor whose REWARD TOKEN speed to update\\n * @param rewardTokenSpeed New REWARD TOKEN speed for contributor\\n */\\n function setContributorRewardTokenSpeed(address contributor, uint256 rewardTokenSpeed) external onlyOwner {\\n // note that REWARD TOKEN speed could be set to 0 to halt liquidity rewards for a contributor\\n updateContributorRewards(contributor);\\n if (rewardTokenSpeed == 0) {\\n // release storage\\n delete lastContributorBlock[contributor];\\n } else {\\n lastContributorBlock[contributor] = getBlockNumberOrTimestamp();\\n }\\n rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed;\\n\\n emit ContributorRewardTokenSpeedUpdated(contributor, rewardTokenSpeed);\\n }\\n\\n function distributeSupplierRewardToken(address vToken, address supplier) external onlyComptroller {\\n _distributeSupplierRewardToken(vToken, supplier);\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in all markets\\n * @param holder The address to claim REWARD TOKEN for\\n */\\n function claimRewardToken(address holder) external {\\n return claimRewardToken(holder, comptroller.getAllMarkets());\\n }\\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) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Calculate additional accrued REWARD TOKEN for a contributor since last accrual\\n * @param contributor The address to calculate contributor rewards for\\n */\\n function updateContributorRewards(address contributor) public {\\n uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, lastContributorBlock[contributor]);\\n if (deltaBlocksOrTimestamp > 0 && rewardTokenSpeed > 0) {\\n uint256 newAccrued = mul_(deltaBlocksOrTimestamp, rewardTokenSpeed);\\n uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued);\\n\\n rewardTokenAccrued[contributor] = contributorAccrued;\\n lastContributorBlock[contributor] = blockNumberOrTimestamp;\\n\\n emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]);\\n }\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in the specified markets\\n * @param holder The address to claim REWARD TOKEN for\\n * @param vTokens The list of markets to claim REWARD TOKEN in\\n */\\n function claimRewardToken(address holder, VToken[] memory vTokens) public {\\n uint256 vTokensCount = vTokens.length;\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n VToken vToken = vTokens[i];\\n require(comptroller.isMarketListed(vToken), \\\"market must be listed\\\");\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n _distributeBorrowerRewardToken(address(vToken), holder, borrowIndex);\\n _updateRewardTokenSupplyIndex(address(vToken));\\n _distributeSupplierRewardToken(address(vToken), holder);\\n }\\n rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for a single market.\\n * @param vToken market's whose reward token last rewarding block to be updated\\n * @param supplyLastRewardingBlock New supply-side REWARD TOKEN last rewarding block for market\\n * @param borrowLastRewardingBlock New borrow-side REWARD TOKEN last rewarding block for market\\n */\\n function _setLastRewardingBlock(\\n VToken vToken,\\n uint32 supplyLastRewardingBlock,\\n uint32 borrowLastRewardingBlock\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockNumber = getBlockNumberOrTimestamp();\\n\\n require(supplyLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n require(borrowLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n\\n uint32 currentSupplyLastRewardingBlock = rewardTokenSupplyState[address(vToken)].lastRewardingBlock;\\n uint32 currentBorrowLastRewardingBlock = rewardTokenBorrowState[address(vToken)].lastRewardingBlock;\\n\\n require(\\n currentSupplyLastRewardingBlock == 0 || currentSupplyLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlock == 0 || currentBorrowLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlock != supplyLastRewardingBlock) {\\n rewardTokenSupplyState[address(vToken)].lastRewardingBlock = supplyLastRewardingBlock;\\n emit SupplyLastRewardingBlockUpdated(address(vToken), supplyLastRewardingBlock);\\n }\\n\\n if (currentBorrowLastRewardingBlock != borrowLastRewardingBlock) {\\n rewardTokenBorrowState[address(vToken)].lastRewardingBlock = borrowLastRewardingBlock;\\n emit BorrowLastRewardingBlockUpdated(address(vToken), borrowLastRewardingBlock);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding timestamp for a single market.\\n * @param vToken market's whose reward token last rewarding timestamp to be updated\\n * @param supplyLastRewardingBlockTimestamp New supply-side REWARD TOKEN last rewarding timestamp for market\\n * @param borrowLastRewardingBlockTimestamp New borrow-side REWARD TOKEN last rewarding timestamp for market\\n */\\n function _setLastRewardingBlockTimestamp(\\n VToken vToken,\\n uint256 supplyLastRewardingBlockTimestamp,\\n uint256 borrowLastRewardingBlockTimestamp\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockTimestamp = getBlockNumberOrTimestamp();\\n\\n require(\\n supplyLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"setting last rewarding timestamp in the past is not allowed\\\"\\n );\\n require(\\n borrowLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"setting last rewarding timestamp in the past is not allowed\\\"\\n );\\n\\n uint256 currentSupplyLastRewardingBlockTimestamp = rewardTokenSupplyStateTimeBased[address(vToken)]\\n .lastRewardingTimestamp;\\n uint256 currentBorrowLastRewardingBlockTimestamp = rewardTokenBorrowStateTimeBased[address(vToken)]\\n .lastRewardingTimestamp;\\n\\n require(\\n currentSupplyLastRewardingBlockTimestamp == 0 || currentSupplyLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlockTimestamp == 0 || currentBorrowLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlockTimestamp != supplyLastRewardingBlockTimestamp) {\\n rewardTokenSupplyStateTimeBased[address(vToken)].lastRewardingTimestamp = supplyLastRewardingBlockTimestamp;\\n emit SupplyLastRewardingBlockTimestampUpdated(address(vToken), supplyLastRewardingBlockTimestamp);\\n }\\n\\n if (currentBorrowLastRewardingBlockTimestamp != borrowLastRewardingBlockTimestamp) {\\n rewardTokenBorrowStateTimeBased[address(vToken)].lastRewardingTimestamp = borrowLastRewardingBlockTimestamp;\\n emit BorrowLastRewardingBlockTimestampUpdated(address(vToken), borrowLastRewardingBlockTimestamp);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single market.\\n * @param vToken market's whose reward token rate to be updated\\n * @param supplySpeed New supply-side REWARD TOKEN speed for market\\n * @param borrowSpeed New borrow-side REWARD TOKEN speed for market\\n */\\n function _setRewardTokenSpeed(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n if (rewardTokenSupplySpeeds[address(vToken)] != supplySpeed) {\\n // Supply speed updated so let's update supply state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n _updateRewardTokenSupplyIndex(address(vToken));\\n\\n // Update speed and emit event\\n rewardTokenSupplySpeeds[address(vToken)] = supplySpeed;\\n emit RewardTokenSupplySpeedUpdated(vToken, supplySpeed);\\n }\\n\\n if (rewardTokenBorrowSpeeds[address(vToken)] != borrowSpeed) {\\n // Borrow speed updated so let's update borrow state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n\\n // Update speed and emit event\\n rewardTokenBorrowSpeeds[address(vToken)] = borrowSpeed;\\n emit RewardTokenBorrowSpeedUpdated(vToken, borrowSpeed);\\n }\\n }\\n\\n /**\\n * @notice Calculate REWARD TOKEN 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 REWARD TOKEN to\\n */\\n function _distributeSupplierRewardToken(address vToken, address supplier) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\\n\\n uint256 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\\n uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier];\\n\\n // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenSupplierIndex[vToken][supplier] = supplyIndex;\\n\\n if (supplierIndex == 0 && supplyIndex >= INITIAL_INDEX) {\\n // Covers the case where users supplied tokens before the market's supply state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when supplier rewards were first\\n // set for the market.\\n supplierIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per vToken accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\\n\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerVToken\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n\\n uint256 supplierAccrued = add_(rewardTokenAccrued[supplier], supplierDelta);\\n rewardTokenAccrued[supplier] = supplierAccrued;\\n\\n emit DistributedSupplierRewardToken(VToken(vToken), supplier, supplierDelta, supplierAccrued, supplyIndex);\\n }\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them.\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function _distributeBorrowerRewardToken(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\\n\\n uint256 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\\n uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower];\\n\\n // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenBorrowerIndex[vToken][borrower] = borrowIndex;\\n\\n if (borrowerIndex == 0 && borrowIndex >= INITIAL_INDEX) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when borrower rewards were first\\n // set for the market.\\n borrowerIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per borrowed unit accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\\n\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerBorrowedUnit\\n if (borrowerAmount != 0) {\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n\\n uint256 borrowerAccrued = add_(rewardTokenAccrued[borrower], borrowerDelta);\\n rewardTokenAccrued[borrower] = borrowerAccrued;\\n\\n emit DistributedBorrowerRewardToken(VToken(vToken), borrower, borrowerDelta, borrowerAccrued, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the user.\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all.\\n * @param user The address of the user to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n * @return The amount of REWARD TOKEN which was NOT transferred to the user\\n */\\n function _grantRewardToken(address user, uint256 amount) internal returns (uint256) {\\n uint256 rewardTokenRemaining = rewardToken.balanceOf(address(this));\\n if (amount > 0 && amount <= rewardTokenRemaining) {\\n rewardToken.safeTransfer(user, amount);\\n return 0;\\n }\\n return amount;\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the supply index\\n * @param vToken The market whose supply index to update\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenSupplyIndex(address vToken) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\\n\\n uint256 supplySpeed = rewardTokenSupplySpeeds[vToken];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (!isTimeBased) {\\n safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\");\\n }\\n\\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\\n ? supplyStateTimeBased.lastRewardingTimestamp\\n : uint256(supplyState.lastRewardingBlock);\\n\\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(\\n blockNumberOrTimestamp,\\n (isTimeBased ? supplyStateTimeBased.timestamp : uint256(supplyState.block))\\n );\\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, supplySpeed);\\n Double memory ratio = supplyTokens > 0\\n ? fraction(accruedSinceUpdate, supplyTokens)\\n : Double({ mantissa: 0 });\\n uint224 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\\n uint224 index = safe224(\\n add_(Double({ mantissa: supplyIndex }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n\\n if (isTimeBased) {\\n supplyStateTimeBased.index = index;\\n supplyStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n supplyState.index = index;\\n supplyState.block = uint32(blockNumberOrTimestamp);\\n }\\n } else if (deltaBlocksOrTimestamp > 0) {\\n isTimeBased ? supplyStateTimeBased.timestamp = blockNumberOrTimestamp : supplyState.block = uint32(\\n blockNumberOrTimestamp\\n );\\n }\\n\\n emit RewardTokenSupplyIndexUpdated(vToken);\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the borrow index\\n * @param vToken The market whose borrow index to update\\n * @param marketBorrowIndex The current global borrow index of vToken\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\\n\\n uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (!isTimeBased) {\\n safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\");\\n }\\n\\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\\n ? borrowStateTimeBased.lastRewardingTimestamp\\n : uint256(borrowState.lastRewardingBlock);\\n\\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(\\n blockNumberOrTimestamp,\\n (isTimeBased ? borrowStateTimeBased.timestamp : uint256(borrowState.block))\\n );\\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, borrowSpeed);\\n Double memory ratio = borrowAmount > 0\\n ? fraction(accruedSinceUpdate, borrowAmount)\\n : Double({ mantissa: 0 });\\n uint224 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\\n uint224 index = safe224(\\n add_(Double({ mantissa: borrowIndex }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n\\n if (isTimeBased) {\\n borrowStateTimeBased.index = index;\\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n borrowState.index = index;\\n borrowState.block = uint32(blockNumberOrTimestamp);\\n }\\n } else if (deltaBlocksOrTimestamp > 0) {\\n if (isTimeBased) {\\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n borrowState.block = uint32(blockNumberOrTimestamp);\\n }\\n }\\n\\n emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken called when contract is block-based\\n * @param vToken The address of the vToken to be initialized\\n * @param blockNumber current block number\\n */\\n function _initializeMarketBlockBased(address vToken, uint32 blockNumber) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n RewardToken storage borrowState = rewardTokenBorrowState[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 = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block numbers\\n */\\n supplyState.block = borrowState.block = blockNumber;\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken called when contract is time-based\\n * @param vToken The address of the vToken to be initialized\\n * @param blockTimestamp current block timestamp\\n */\\n function _initializeMarketTimestampBased(address vToken, uint256 blockTimestamp) internal {\\n TimeBasedRewardToken storage supplyState = rewardTokenSupplyStateTimeBased[vToken];\\n TimeBasedRewardToken storage borrowState = rewardTokenBorrowStateTimeBased[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 = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block timestamp\\n */\\n supplyState.timestamp = borrowState.timestamp = blockTimestamp;\\n }\\n}\\n\",\"keccak256\":\"0x3cc824e59c923cfe25c4f1a875959b7e9410cde8e73cd405de13f301298c697f\",\"license\":\"BSD-3-Clause\"},\"contracts/Rewards/RewardsDistributorStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\n\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\n\\n/**\\n * @title RewardsDistributorStorage\\n * @author Venus\\n * @dev Storage for RewardsDistributor\\n */\\ncontract RewardsDistributorStorage {\\n struct RewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number the index was last updated at\\n uint32 block;\\n // The block number at which to stop rewards\\n uint32 lastRewardingBlock;\\n }\\n\\n struct TimeBasedRewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block timestamp the index was last updated at\\n uint256 timestamp;\\n // The block timestamp at which to stop rewards\\n uint256 lastRewardingTimestamp;\\n }\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => RewardToken) public rewardTokenSupplyState;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex;\\n\\n /// @notice The REWARD TOKEN accrued but not yet transferred to each user\\n mapping(address => uint256) public rewardTokenAccrued;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding borrow market per slot (block or second)\\n mapping(address => uint256) public rewardTokenBorrowSpeeds;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding supply market per slot (block or second)\\n mapping(address => uint256) public rewardTokenSupplySpeeds;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => RewardToken) public rewardTokenBorrowState;\\n\\n /// @notice The portion of REWARD TOKEN that each contributor receives per slot (block or second)\\n mapping(address => uint256) public rewardTokenContributorSpeeds;\\n\\n /// @notice Last slot (block or second) at which a contributor's REWARD TOKEN rewards have been allocated\\n mapping(address => uint256) public lastContributorBlock;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex;\\n\\n Comptroller internal comptroller;\\n\\n IERC20Upgradeable public rewardToken;\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => TimeBasedRewardToken) public rewardTokenSupplyStateTimeBased;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => TimeBasedRewardToken) public rewardTokenBorrowStateTimeBased;\\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[37] private __gap;\\n}\\n\",\"keccak256\":\"0x70e5015a78a2acf95277949c8b4796e10b9ac194130be006d5e5217e158070c0\",\"license\":\"BSD-3-Clause\"},\"contracts/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\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 { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"@venusprotocol/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\\\";\\n\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { ComptrollerInterface, ComptrollerViewInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"./ErrorReporter.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title VToken\\n * @author Venus\\n * @notice Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview,\\n * each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of\\n * the pool. The main actions a user regularly interacts with in a market are:\\n\\n- mint/redeem of vTokens;\\n- transfer of vTokens;\\n- borrow/repay a loan on an underlying asset;\\n- liquidate a borrow or liquidate/heal an account.\\n\\n * A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`.\\n * The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted\\n * `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken`\\n * as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that\\n * a user may borrow up to a portion of their collateral determined by the market\\u2019s collateral factor. However, if their borrowed amount exceeds an amount\\n * calculated using the market\\u2019s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also\\n * pay off interest accrued on the borrow.\\n * \\n * The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller`\\n * and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a\\n * total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`.\\n * Both functions settle all of an account\\u2019s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of\\n * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\\n */\\ncontract VToken is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n VTokenInterface,\\n ExponentialNoError,\\n TokenErrorReporter,\\n TimeManagerV8\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5%\\n\\n // Maximum fraction of interest that can be set aside for reserves\\n uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18;\\n\\n // Maximum borrow rate that can ever be applied per slot(block or second)\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n uint256 internal immutable MAX_BORROW_RATE_MANTISSA;\\n\\n /**\\n * Reentrancy Guard **\\n */\\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 * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @param maxBorrowRateMantissa_ The maximum value of borrowing rate mantissa\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(\\n bool timeBased_,\\n uint256 blocksPerYear_,\\n uint256 maxBorrowRateMantissa_\\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n require(maxBorrowRateMantissa_ <= 1e18, \\\"Max borrow rate must be <= 1e18\\\");\\n\\n MAX_BORROW_RATE_MANTISSA = maxBorrowRateMantissa_;\\n _disableInitializers();\\n }\\n\\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_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n */\\n function initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) external initializer {\\n ensureNonzeroAddress(admin_);\\n\\n // Initialize the market\\n _initialize(\\n underlying_,\\n comptroller_,\\n interestRateModel_,\\n initialExchangeRateMantissa_,\\n name_,\\n symbol_,\\n decimals_,\\n admin_,\\n accessControlManager_,\\n riskManagement,\\n reserveFactorMantissa_\\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 * @return success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, msg.sender, dst, amount);\\n return true;\\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 success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, src, dst, amount);\\n return true;\\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 (uint256.max means infinite)\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Increase approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param addedValue The number of additional tokens spender can transfer\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function increaseAllowance(address spender, uint256 addedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 newAllowance = transferAllowances[src][spender];\\n newAllowance += addedValue;\\n transferAllowances[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n return true;\\n }\\n\\n /**\\n * @notice Decreases approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param subtractedValue The number of tokens to remove from total approval\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 currentAllowance = transferAllowances[src][spender];\\n require(currentAllowance >= subtractedValue, \\\"decreased allowance below zero\\\");\\n unchecked {\\n currentAllowance -= subtractedValue;\\n }\\n\\n transferAllowances[src][spender] = currentAllowance;\\n\\n emit Approval(src, spender, currentAllowance);\\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 amount The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint256) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return totalBorrows The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\\n accrueInterest();\\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 borrowBalance The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n return _borrowBalanceStored(account);\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function mint(uint256 mintAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _mintFresh(msg.sender, msg.sender, mintAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param minter User whom the supply will be attributed to\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when minter address is zero\\n */\\n function mintBehalf(address minter, uint256 mintAmount) external override nonReentrant returns (uint256) {\\n ensureNonzeroAddress(minter);\\n\\n accrueInterest();\\n\\n _mintFresh(msg.sender, minter, mintAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function redeem(uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _redeemFresh(msg.sender, msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function redeemBehalf(address redeemer, uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n _ensureSenderIsDelegateOf(redeemer);\\n\\n accrueInterest();\\n\\n _redeemFresh(redeemer, msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\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 receive from redeeming vTokens\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n */\\n function redeemUnderlying(uint256 redeemAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _redeemFresh(msg.sender, msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function redeemUnderlyingBehalf(\\n address redeemer,\\n uint256 redeemAmount\\n ) external override nonReentrant returns (uint256) {\\n _ensureSenderIsDelegateOf(redeemer);\\n\\n accrueInterest();\\n\\n _redeemFresh(redeemer, msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function borrow(uint256 borrowAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _borrowFresh(msg.sender, msg.sender, borrowAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error DelegateNotApproved is thrown if caller is not approved delegate\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function borrowBehalf(address borrower, uint256 borrowAmount) external override returns (uint256) {\\n _ensureSenderIsDelegateOf(borrower);\\n accrueInterest();\\n\\n _borrowFresh(borrower, msg.sender, borrowAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrow(uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n return NO_ERROR;\\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, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _repayBorrowFresh(msg.sender, borrower, repayAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Not restricted\\n */\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external override returns (uint256) {\\n _liquidateBorrow(msg.sender, borrower, repayAmount, vTokenCollateral, false);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice sets protocol share accumulated from liquidations\\n * @dev must be equal or less than liquidation incentive - 1\\n * @param newProtocolSeizeShareMantissa_ new protocol share mantissa\\n * @custom:event Emits NewProtocolSeizeShare event on success\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error ProtocolSeizeShareTooBig is thrown when the new seize share is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa_) external {\\n _checkAccessAllowed(\\\"setProtocolSeizeShare(uint256)\\\");\\n uint256 liquidationIncentive = ComptrollerViewInterface(address(comptroller)).liquidationIncentiveMantissa();\\n if (newProtocolSeizeShareMantissa_ + MANTISSA_ONE > liquidationIncentive) {\\n revert ProtocolSeizeShareTooBig();\\n }\\n\\n uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\\n protocolSeizeShareMantissa = newProtocolSeizeShareMantissa_;\\n emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa_);\\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 * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n * @custom:event Emits NewReserveFactor event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant {\\n _checkAccessAllowed(\\\"setReserveFactor(uint256)\\\");\\n\\n accrueInterest();\\n _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to the protocol reserve contract\\n * @dev Gracefully return if reserves already reduced in accrueInterest\\n * @param reduceAmount Amount of reduction to reserves\\n * @custom:event Emits ReservesReduced event; may emit AccrueInterest\\n * @custom:error ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash\\n * @custom:error ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\\n * @custom:access Not restricted\\n */\\n function reduceReserves(uint256 reduceAmount) external override nonReentrant {\\n accrueInterest();\\n if (reduceReservesBlockNumber == getBlockNumberOrTimestamp()) return;\\n _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice The sender adds to reserves.\\n * @param addAmount The amount of underlying token to add as reserves\\n * @custom:event Emits ReservesAdded event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function addReserves(uint256 addAmount) external override nonReentrant {\\n accrueInterest();\\n _addReservesFresh(addAmount);\\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 * @custom:event Emits NewMarketInterestRateModel event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external override {\\n _checkAccessAllowed(\\\"setInterestRateModel(address)\\\");\\n\\n accrueInterest();\\n _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially\\n * \\\"forgiving\\\" the borrower. Healing is a situation that should rarely happen. However, some pools\\n * may list risky assets or be configured improperly \\u2013 we want to still handle such cases gracefully.\\n * We assume that Comptroller does the seizing, so this function is only available to Comptroller.\\n * @dev This function does not call any Comptroller hooks (like \\\"healAllowed\\\"), because we assume\\n * the Comptroller does all the necessary checks before calling this function.\\n * @param payer account who repays the debt\\n * @param borrower account to heal\\n * @param repayAmount amount to repay\\n * @custom:event Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\\n * @custom:error HealBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:access Only Comptroller\\n */\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external override nonReentrant {\\n if (repayAmount != 0) {\\n comptroller.preRepayHook(address(this), borrower);\\n }\\n\\n if (msg.sender != address(comptroller)) {\\n revert HealBorrowUnauthorized();\\n }\\n\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 totalBorrowsNew = totalBorrows;\\n\\n uint256 actualRepayAmount;\\n if (repayAmount != 0) {\\n // _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // We violate checks-effects-interactions here to account for tokens that take transfer fees\\n actualRepayAmount = _doTransferIn(payer, repayAmount);\\n totalBorrowsNew = totalBorrowsNew - actualRepayAmount;\\n emit RepayBorrow(\\n payer,\\n borrower,\\n actualRepayAmount,\\n accountBorrowsPrev - actualRepayAmount,\\n totalBorrowsNew\\n );\\n }\\n\\n // The transaction will fail if trying to repay too much\\n uint256 badDebtDelta = accountBorrowsPrev - actualRepayAmount;\\n if (badDebtDelta != 0) {\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld + badDebtDelta;\\n totalBorrowsNew = totalBorrowsNew - badDebtDelta;\\n badDebt = badDebtNew;\\n\\n // We treat healing as \\\"repayment\\\", where vToken is the payer\\n emit RepayBorrow(address(this), borrower, badDebtDelta, 0, totalBorrowsNew);\\n emit BadDebtIncreased(borrower, badDebtDelta, badDebtOld, badDebtNew);\\n }\\n\\n accountBorrows[borrower].principal = 0;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n emit HealBorrow(payer, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice The extended version of liquidations, callable only by Comptroller. May skip\\n * the close factor check. The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Only Comptroller\\n */\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) external override {\\n if (msg.sender != address(comptroller)) {\\n revert ForceLiquidateBorrowUnauthorized();\\n }\\n _liquidateBorrow(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\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 * @custom:event Emits Transfer, ReservesAdded events\\n * @custom:error LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:access Not restricted\\n */\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external override nonReentrant {\\n _seize(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Updates bad debt\\n * @dev Called only when bad debt is recovered from auction. Updates internal cash balance.\\n * @param recoveredAmount_ The amount of bad debt recovered\\n * @custom:event Emits BadDebtRecovered event\\n * @custom:access Only Shortfall contract\\n */\\n function badDebtRecovered(uint256 recoveredAmount_) external {\\n require(msg.sender == shortfall, \\\"only shortfall contract can update bad debt\\\");\\n require(recoveredAmount_ <= badDebt, \\\"more than bad debt recovered from auction\\\");\\n\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld - recoveredAmount_;\\n badDebt = badDebtNew;\\n internalCash += recoveredAmount_;\\n\\n emit BadDebtRecovered(badDebtOld, badDebtNew);\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protocolShareReserve_ The address of the protocol share reserve contract\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n * @custom:access Only Governance\\n */\\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\\n _setProtocolShareReserve(protocolShareReserve_);\\n }\\n\\n /**\\n * @notice Sets shortfall contract address\\n * @param shortfall_ The address of the shortfall contract\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:access Only Governance\\n */\\n function setShortfallContract(address shortfall_) external onlyOwner {\\n _setShortfallContract(shortfall_);\\n }\\n\\n /**\\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\\n * @param token The address of the ERC-20 token to sweep\\n * @custom:access Only Governance\\n */\\n function sweepToken(IERC20Upgradeable token) external override {\\n require(msg.sender == owner(), \\\"VToken::sweepToken: only admin can sweep tokens\\\");\\n require(address(token) != underlying, \\\"VToken::sweepToken: can not sweep underlying token\\\");\\n uint256 balance = token.balanceOf(address(this));\\n token.safeTransfer(owner(), balance);\\n\\n emit SweepToken(address(token));\\n }\\n\\n /**\\n * @notice Sync internalCash with the actual underlying token balance\\n * @dev Used for one-time migration after upgrade to initialize internalCash\\n * @custom:event Emits CashSynced\\n * @custom:access Controlled by AccessControlManager\\n */\\n function syncCash() external override nonReentrant {\\n _checkAccessAllowed(\\\"syncCash()\\\");\\n uint256 oldInternalCash = internalCash;\\n uint256 actualCash = IERC20Upgradeable(underlying).balanceOf(address(this));\\n internalCash = actualCash;\\n emit CashSynced(oldInternalCash, actualCash);\\n }\\n\\n /**\\n * @notice A public function to set new threshold of slot(block or second) difference after which funds will be sent to the protocol share reserve\\n * @param _newReduceReservesBlockOrTimestampDelta slot(block or second) difference value\\n * @custom:access Only Governance\\n */\\n function setReduceReservesBlockDelta(uint256 _newReduceReservesBlockOrTimestampDelta) external {\\n _checkAccessAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n require(_newReduceReservesBlockOrTimestampDelta > 0, \\\"Invalid Input\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, _newReduceReservesBlockOrTimestampDelta);\\n reduceReservesBlockDelta = _newReduceReservesBlockOrTimestampDelta;\\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 amount 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 amount 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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return vTokenBalance User's balance of vTokens\\n * @return borrowBalance Amount owed in terms of underlying\\n * @return exchangeRate Stored exchange rate\\n */\\n function getAccountSnapshot(\\n address account\\n )\\n external\\n view\\n override\\n returns (uint256 error, uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRate)\\n {\\n return (NO_ERROR, accountTokens[account], _borrowBalanceStored(account), _exchangeRateStored());\\n }\\n\\n /**\\n * @notice Get the internally tracked cash balance of this vToken in the underlying asset\\n * @return cash The quantity of underlying asset tracked internally by this contract\\n */\\n function getCash() external view override returns (uint256) {\\n return _getCashPrior();\\n }\\n\\n /**\\n * @notice Returns the current per slot(block or second) borrow interest rate for this vToken\\n * @return rate The borrow interest rate per slot(block or second), scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint256) {\\n return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt);\\n }\\n\\n /**\\n * @notice Returns the current per-slot(block or second) supply interest rate for this v\\n * @return rate The supply interest rate per slot(block or second), scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint256) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPrior(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa,\\n badDebt\\n );\\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 borrowBalance The calculated balance\\n */\\n function borrowBalanceStored(address account) external view override returns (uint256) {\\n return _borrowBalanceStored(account);\\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 exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() external view override returns (uint256) {\\n return _exchangeRateStored();\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\\n accrueInterest();\\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 slot(block or second)\\n * up to the current slot(block or second) and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentSlot - reduceReservesBlockNumber >= slotDelta\\n * @return Always NO_ERROR\\n * @custom:event Emits AccrueInterest event on success\\n * @custom:access Not restricted\\n */\\n function accrueInterest() public virtual override returns (uint256) {\\n /* Remember the initial block number or timestamp */\\n uint256 currentSlotNumber = getBlockNumberOrTimestamp();\\n uint256 accrualSlotNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualSlotNumberPrior == currentSlotNumber) {\\n return NO_ERROR;\\n }\\n\\n /* Read the previous values out of storage */\\n uint256 cashPrior = _getCashPrior();\\n uint256 borrowsPrior = totalBorrows;\\n uint256 reservesPrior = totalReserves;\\n uint256 borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt);\\n require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of slots elapsed since the last accrual */\\n uint256 slotDelta = currentSlotNumber - accrualSlotNumberPrior;\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * slotDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), slotDelta);\\n uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\\n uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;\\n uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentSlotNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n if (currentSlotNumber - reduceReservesBlockNumber >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentSlotNumber;\\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 NO_ERROR;\\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 or timestamp\\n * @param payer The address of the account which is sending the assets for supply\\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 */\\n function _mintFresh(address payer, address minter, uint256 mintAmount) internal {\\n /* Fail if mint not allowed */\\n comptroller.preMintHook(address(this), minter, mintAmount);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert MintFreshnessCheck();\\n }\\n\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\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 * `_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 uint256 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 uint256 mintTokens = div_(actualMintAmount, exchangeRate);\\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 * And write them into storage\\n */\\n totalSupply = totalSupply + mintTokens;\\n uint256 balanceAfter = accountTokens[minter] + mintTokens;\\n accountTokens[minter] = balanceAfter;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, actualMintAmount, mintTokens, balanceAfter);\\n emit Transfer(address(0), minter, mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, actualMintAmount, mintTokens);\\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 Comptroller.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current slot(block or second)\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the underlying 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 */\\n function _redeemFresh(address redeemer, address receiver, uint256 redeemTokensIn, uint256 redeemAmountIn) internal {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert RedeemFreshnessCheck();\\n }\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n\\n uint256 redeemTokens;\\n uint256 redeemAmount;\\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 */\\n redeemTokens = redeemTokensIn;\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n */\\n redeemTokens = div_(redeemAmountIn, exchangeRate);\\n\\n uint256 _redeemAmount = mul_(redeemTokens, exchangeRate);\\n if (_redeemAmount != 0 && _redeemAmount != redeemAmountIn) redeemTokens++; // round up\\n }\\n\\n // redeemAmount = exchangeRate * redeemTokens\\n redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokens);\\n\\n // Revert if amount is zero\\n if (redeemAmount == 0) {\\n revert(\\\"redeemAmount is zero\\\");\\n }\\n\\n /* Fail if redeem not allowed */\\n comptroller.preRedeemHook(address(this), redeemer, redeemTokens);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (_getCashPrior() - totalReserves < redeemAmount) {\\n revert RedeemTransferOutNotPossible();\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\\n */\\n totalSupply = totalSupply - redeemTokens;\\n uint256 balanceAfter = accountTokens[redeemer] - redeemTokens;\\n accountTokens[redeemer] = balanceAfter;\\n\\n /*\\n * We invoke _doTransferOut for the receiver and the redeemAmount.\\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 _doTransferOut(receiver, redeemAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), redeemTokens);\\n emit Redeem(redeemer, redeemAmount, redeemTokens, balanceAfter);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, redeemAmount, redeemTokens);\\n }\\n\\n /**\\n * @notice Users or their delegates borrow assets from the protocol\\n * @param borrower User who borrows the assets\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param borrowAmount The amount of the underlying asset to borrow\\n */\\n function _borrowFresh(address borrower, address receiver, uint256 borrowAmount) internal {\\n /* Fail if borrow not allowed */\\n comptroller.preBorrowHook(address(this), borrower, borrowAmount);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert BorrowFreshnessCheck();\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (_getCashPrior() - totalReserves < borrowAmount) {\\n revert BorrowCashNotAvailable();\\n }\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowNew = accountBorrow + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;\\n uint256 totalBorrowsNew = totalBorrows + borrowAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\\n `*/\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /*\\n * We invoke _doTransferOut for the receiver and the borrowAmount.\\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, accountBorrowsNew, totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\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 underlying tokens being returned, or type(uint256).max for the full outstanding amount\\n * @return (uint) the actual repayment amount.\\n */\\n function _repayBorrowFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256) {\\n /* Fail if repayBorrow not allowed */\\n comptroller.preRepayHook(address(this), borrower);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert RepayBorrowFreshnessCheck();\\n }\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n\\n uint256 repayAmountFinal = repayAmount >= accountBorrowsPrev ? accountBorrowsPrev : 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 * 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 uint256 actualRepayAmount = _doTransferIn(payer, repayAmountFinal);\\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 uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\\n uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, actualRepayAmount, borrowIndex);\\n\\n return actualRepayAmount;\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal nonReentrant {\\n accrueInterest();\\n\\n uint256 error = vTokenCollateral.accrueInterest();\\n if (error != NO_ERROR) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n revert LiquidateAccrueCollateralInterestFailed(error);\\n }\\n\\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal {\\n /* Fail if liquidate not allowed */\\n comptroller.preLiquidateHook(\\n address(this),\\n address(vTokenCollateral),\\n borrower,\\n repayAmount,\\n skipLiquidityCheck\\n );\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert LiquidateFreshnessCheck();\\n }\\n\\n /* Verify vTokenCollateral market's slot(block or second) number equals current slot(block or second) number */\\n if (vTokenCollateral.accrualBlockNumber() != getBlockNumberOrTimestamp()) {\\n revert LiquidateCollateralFreshnessCheck();\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateLiquidatorIsBorrower();\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n revert LiquidateCloseAmountIsZero();\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n revert LiquidateCloseAmountIsUintMax();\\n }\\n\\n /* Fail if repayBorrow fails */\\n uint256 actualRepayAmount = _repayBorrowFresh(liquidator, borrower, repayAmount);\\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.liquidateCalculateSeizeTokens(\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n require(amountSeizeError == 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, call _seize internally to avoid re-entrancy, otherwise make an external call\\n if (address(vTokenCollateral) == address(this)) {\\n _seize(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\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\\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 * It's absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerContract The contract seizing the collateral (either borrowed vToken or Comptroller)\\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 */\\n function _seize(address seizerContract, address liquidator, address borrower, uint256 seizeTokens) internal {\\n /* Fail if seize not allowed */\\n comptroller.preSeizeHook(address(this), seizerContract, liquidator, borrower);\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateSeizeLiquidatorIsBorrower();\\n }\\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 uint256 liquidationIncentiveMantissa = ComptrollerViewInterface(address(comptroller))\\n .liquidationIncentiveMantissa();\\n uint256 numerator = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));\\n uint256 protocolSeizeTokens = div_(numerator, Exp({ mantissa: liquidationIncentiveMantissa }));\\n uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n uint256 protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the calculated values into storage */\\n totalSupply = totalSupply - protocolSeizeTokens;\\n accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\\n accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\\n\\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, protocolSeizeAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.LIQUIDATION\\n );\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\\n emit ProtocolSeize(borrower, protocolShareReserve, protocolSeizeAmount);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerContract, liquidator, borrower, seizeTokens);\\n }\\n\\n function _setComptroller(ComptrollerInterface newComptroller) internal {\\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\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n */\\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal {\\n // Verify market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert SetReserveFactorFreshCheck();\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > MAX_RESERVE_FACTOR_MANTISSA) {\\n revert SetReserveFactorBoundsCheck();\\n }\\n\\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\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 actualAddAmount The actual amount added, excluding the potential token fees\\n */\\n function _addReservesFresh(uint256 addAmount) internal returns (uint256) {\\n // totalReserves + actualAddAmount\\n uint256 totalReservesNew;\\n uint256 actualAddAmount;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert AddReservesFactorFreshCheck(actualAddAmount);\\n }\\n\\n actualAddAmount = _doTransferIn(msg.sender, addAmount);\\n totalReservesNew = totalReserves + actualAddAmount;\\n totalReserves = totalReservesNew;\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n return actualAddAmount;\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to the protocol reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n */\\n function _reduceReservesFresh(uint256 reduceAmount) internal {\\n if (reduceAmount == 0) {\\n return;\\n }\\n // totalReserves - reduceAmount\\n uint256 totalReservesNew;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert ReduceReservesFreshCheck();\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (_getCashPrior() < reduceAmount) {\\n revert ReduceReservesCashNotAvailable();\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n revert ReduceReservesCashValidation();\\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 // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, reduceAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit SpreadReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal {\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert SetInterestRateModelFreshCheck();\\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\\n /**\\n * Safe Token **\\n */\\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 returns (uint256) {\\n IERC20Upgradeable token = IERC20Upgradeable(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 * @param to Receiver of the underlying tokens\\n * @param amount Amount of underlying to transfer\\n */\\n function _doTransferOut(address to, uint256 amount) internal virtual {\\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\\n internalCash -= amount;\\n token.safeTransfer(to, amount);\\n }\\n\\n /**\\n * @notice Transfer `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 */\\n function _transferTokens(address spender, address src, address dst, uint256 tokens) internal {\\n /* Fail if transfer not allowed */\\n comptroller.preTransferHook(address(this), src, dst, tokens);\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n revert TransferNotAllowed();\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint256 startingAllowance;\\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 uint256 allowanceNew = startingAllowance - tokens;\\n uint256 srcTokensNew = accountTokens[src] - tokens;\\n uint256 dstTokensNew = accountTokens[dst] + tokens;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n\\n accountTokens[src] = srcTokensNew;\\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\\n /**\\n * @notice Initialize the 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_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n */\\n function _initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\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 _setComptroller(comptroller_);\\n\\n // Initialize slot(block or second) number and borrow index (slot(block or second) number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumberOrTimestamp();\\n borrowIndex = MANTISSA_ONE;\\n\\n // Set the interest rate model (depends on slot(block or second) number / borrow index)\\n _setInterestRateModelFresh(interestRateModel_);\\n\\n _setReserveFactorFresh(reserveFactorMantissa_);\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n _setShortfallContract(riskManagement.shortfall);\\n _setProtocolShareReserve(riskManagement.protocolShareReserve);\\n protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA;\\n\\n // Set underlying and sanity check it\\n underlying = underlying_;\\n IERC20Upgradeable(underlying).totalSupply();\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n _transferOwnership(admin_);\\n }\\n\\n function _setShortfallContract(address shortfall_) internal {\\n ensureNonzeroAddress(shortfall_);\\n address oldShortfall = shortfall;\\n shortfall = shortfall_;\\n emit NewShortfallContract(oldShortfall, shortfall_);\\n }\\n\\n function _setProtocolShareReserve(address payable protocolShareReserve_) internal {\\n ensureNonzeroAddress(protocolShareReserve_);\\n address oldProtocolShareReserve = address(protocolShareReserve);\\n protocolShareReserve = protocolShareReserve_;\\n emit NewProtocolShareReserve(oldProtocolShareReserve, address(protocolShareReserve_));\\n }\\n\\n function _ensureSenderIsDelegateOf(address user) internal view {\\n if (!ComptrollerViewInterface(address(comptroller)).approvedDelegates(user, msg.sender)) {\\n revert DelegateNotApproved();\\n }\\n }\\n\\n /**\\n * @notice Gets the internally tracked cash balance of this market\\n * @dev Returns the internalCash state variable, which is updated on transfers in/out\\n * @return The quantity of underlying tokens tracked internally by this contract\\n */\\n function _getCashPrior() internal view virtual returns (uint256) {\\n return internalCash;\\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 borrowBalance the calculated balance\\n */\\n function _borrowBalanceStored(address account) internal view returns (uint256) {\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot memory 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 0;\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;\\n\\n return principalTimesIndex / borrowSnapshot.interestIndex;\\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 exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function _exchangeRateStored() internal view virtual returns (uint256) {\\n uint256 _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return initialExchangeRateMantissa;\\n }\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply\\n */\\n uint256 totalCash = _getCashPrior();\\n uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;\\n uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply;\\n\\n return exchangeRate;\\n }\\n}\\n\",\"keccak256\":\"0x7267f5337062ad01a5011f7725a86cc2ad0351cca0aaceadc167341f168cdef2\",\"license\":\"BSD-3-Clause\"},\"contracts/VTokenInterfaces.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\\nimport { ComptrollerInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title VTokenStorage\\n * @author Venus\\n * @notice Storage layout used by the `VToken` contract\\n */\\n// solhint-disable-next-line max-states-count\\ncontract VTokenStorage {\\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 uint256 principal;\\n uint256 interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\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 Protocol share Reserve contract address\\n */\\n address payable public protocolShareReserve;\\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 InterestRateModel public interestRateModel;\\n\\n // Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n uint256 internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint256 public reserveFactorMantissa;\\n\\n /**\\n * @notice Slot(block or second) number that interest was last accrued at\\n */\\n uint256 public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint256 public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint256 public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint256 public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint256 public totalSupply;\\n\\n /**\\n * @notice Total bad debt of the market\\n */\\n uint256 public badDebt;\\n\\n // Official record of token balances for each account\\n mapping(address => uint256) internal accountTokens;\\n\\n // Approved token transfer amounts on behalf of others\\n mapping(address => mapping(address => uint256)) internal transferAllowances;\\n\\n // Mapping of account addresses to outstanding borrow balances\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint256 public protocolSeizeShareMantissa;\\n\\n /**\\n * @notice Storage of Shortfall contract address\\n */\\n address public shortfall;\\n\\n /**\\n * @notice delta slot (block or second) after which reserves will be reduced\\n */\\n uint256 public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last slot (block or second) number at which reserves were reduced\\n */\\n uint256 public reduceReservesBlockNumber;\\n\\n /**\\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\\n * @dev Updated via _doTransferIn(), _doTransferOut(), syncCash(), and badDebtRecovered(). Must be initialized via syncCash() 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[47] private __gap;\\n}\\n\\n/**\\n * @title VTokenInterface\\n * @author Venus\\n * @notice Interface implemented by the `VToken` contract\\n */\\nabstract contract VTokenInterface is VTokenStorage {\\n struct RiskManagementInit {\\n address shortfall;\\n address payable protocolShareReserve;\\n }\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address indexed minter, uint256 mintAmount, uint256 mintTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address indexed borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(\\n address indexed payer,\\n address indexed borrower,\\n uint256 repayAmount,\\n uint256 accountBorrows,\\n uint256 totalBorrows\\n );\\n\\n /**\\n * @notice Event emitted when bad debt is accumulated on a market\\n * @param borrower borrower to \\\"forgive\\\"\\n * @param badDebtDelta amount of new bad debt recorded\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtIncreased(address indexed borrower, uint256 badDebtDelta, uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when bad debt is recovered via an auction\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtRecovered(uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address indexed liquidator,\\n address indexed borrower,\\n uint256 repayAmount,\\n address indexed vTokenCollateral,\\n uint256 seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface indexed oldComptroller, ComptrollerInterface indexed newComptroller);\\n\\n /**\\n * @notice Event emitted when shortfall contract address is changed\\n */\\n event NewShortfallContract(address indexed oldShortfall, address indexed newShortfall);\\n\\n /**\\n * @notice Event emitted when protocol share reserve contract address is changed\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModel indexed oldInterestRateModel,\\n InterestRateModel indexed newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when protocol seize share is changed\\n */\\n event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address indexed benefactor, uint256 addAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the spread reserves are reduced\\n */\\n event SpreadReservesReduced(address indexed protocolShareReserve, uint256 reduceAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /**\\n * @notice Event emitted when healing the borrow\\n */\\n event HealBorrow(address indexed payer, address indexed borrower, uint256 repayAmount);\\n\\n /**\\n * @notice Event emitted when tokens are swept\\n */\\n event SweepToken(address indexed token);\\n\\n /**\\n * @notice Event emitted when reduce reserves slot (block or second) delta is changed\\n */\\n event NewReduceReservesBlockDelta(\\n uint256 oldReduceReservesBlockOrTimestampDelta,\\n uint256 newReduceReservesBlockOrTimestampDelta\\n );\\n\\n /**\\n * @notice Event emitted when liquidation reserves are reduced\\n */\\n event ProtocolSeize(address indexed from, address indexed to, uint256 amount);\\n\\n /**\\n * @notice Event emitted when internalCash is synced with actual token balance\\n */\\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\\n\\n /*** User Interface ***/\\n\\n function mint(uint256 mintAmount) external virtual returns (uint256);\\n\\n function mintBehalf(address minter, uint256 mintAllowed) external virtual returns (uint256);\\n\\n function redeem(uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemBehalf(address redeemer, uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);\\n\\n function redeemUnderlyingBehalf(address redeemer, uint256 redeemAmount) external virtual returns (uint256);\\n\\n function borrow(uint256 borrowAmount) external virtual returns (uint256);\\n\\n function borrowBehalf(address borrwwer, uint256 borrowAmount) external virtual returns (uint256);\\n\\n function repayBorrow(uint256 repayAmount) external virtual returns (uint256);\\n\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external virtual returns (uint256);\\n\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external virtual;\\n\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipCloseFactorCheck\\n ) external virtual;\\n\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external virtual;\\n\\n function transfer(address dst, uint256 amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint256 amount) external virtual returns (bool);\\n\\n function accrueInterest() external virtual returns (uint256);\\n\\n function sweepToken(IERC20Upgradeable token) external virtual;\\n\\n /*** Admin Functions ***/\\n\\n function setReserveFactor(uint256 newReserveFactorMantissa) external virtual;\\n\\n function reduceReserves(uint256 reduceAmount) external virtual;\\n\\n function exchangeRateCurrent() external virtual returns (uint256);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint256);\\n\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external virtual;\\n\\n function addReserves(uint256 addAmount) external virtual;\\n\\n function syncCash() external virtual;\\n\\n function totalBorrowsCurrent() external virtual returns (uint256);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint256);\\n\\n function approve(address spender, uint256 amount) external virtual returns (bool);\\n\\n function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool);\\n\\n function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint256);\\n\\n function balanceOf(address owner) external view virtual returns (uint256);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint256, uint256, uint256, uint256);\\n\\n function borrowRatePerBlock() external view virtual returns (uint256);\\n\\n function supplyRatePerBlock() external view virtual returns (uint256);\\n\\n function borrowBalanceStored(address account) external view virtual returns (uint256);\\n\\n function exchangeRateStored() external view virtual returns (uint256);\\n\\n function getCash() external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is a VToken contract (for inspection)\\n * @return Always true\\n */\\n function isVToken() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x155684e9cb12cdd8be63d2314c9452b68ee44ff98a00e0d65cd1fd7d0bdd4391\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\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\",\"keccak256\":\"0x54ab3a6f3bc87569ed12370f3470a1ec84cea9796d4d0ccf3d07dd4280c044aa\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/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 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\",\"keccak256\":\"0x93bdd5cfb100f0f9a1d446857e23c3633df6ab12c266333c978428edd96b1367\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x61010060405234801561001157600080fd5b50604051614176380380614176833981016040819052610030916100e9565b82828115801561003e575080155b1561005c576040516302723dfb60e21b815260040160405180910390fd5b81801561006857508015155b156100865760405163ae0fcab360e01b815260040160405180910390fd5b81151560a05281610097578061009d565b6301e133805b608052816100b4576100e160201b611d0c176100bf565b6100e560201b611d10175b6001600160401b031660c05250506001600160a01b031660e0525061013d9050565b4390565b4290565b6000806000606084860312156100fe57600080fd5b8351801515811461010e57600080fd5b6020850151604086015191945092506001600160a01b038116811461013257600080fd5b809150509250925092565b60805160a05160c05160e051613ff2610184600039600081816102e80152611d8201526000611ce00152600081816102b10152611f80015260006101dc0152613ff26000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c80637c51b642116100a2578063c7ad089511610071578063c7ad0895146102ac578063d26998e9146102e3578063d77ebf961461030a578063e0a67f111461032a578063e1d146fb1461034a57600080fd5b80637c51b6421461022c5780637c84e3b31461024c578063aa5dbd231461026c578063b31242391461028c57600080fd5b806347d86a81116100de57806347d86a811461019957806355dd9515146101ac5780636857249c146101d75780637a27db571461020c57600080fd5b80630d3ae318146101105780631f884fdf14610139578063345954dc146101595780633e3e399c14610179575b600080fd5b61012361011e366004612ff0565b610352565b604051610130919061335d565b60405180910390f35b61014c6101473660046133bb565b610626565b60405161013091906133fc565b61016c61016736600461345c565b6106ee565b6040516101309190613479565b61018c61018736600461345c565b610821565b60405161013091906134dd565b6101236101a7366004613567565b610b30565b6101bf6101ba3660046135a0565b610bb7565b6040516001600160a01b039091168152602001610130565b6101fe7f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610130565b61021f61021a366004613567565b610c37565b60405161013091906135eb565b61023f61023a3660046136c7565b610ee7565b6040516101309190613752565b61025f61025a36600461345c565b610fa0565b60405161013091906137a0565b61027f61027a36600461345c565b61110a565b60405161013091906137c0565b61029f61029a366004613567565b6118ca565b60405161013091906137cf565b6102d37f000000000000000000000000000000000000000000000000000000000000000081565b6040519015158152602001610130565b6101bf7f000000000000000000000000000000000000000000000000000000000000000081565b61031d610318366004613567565b611bb1565b60405161013091906137dd565b61033d610338366004613841565b611c24565b60405161013091906138da565b6101fe611cd9565b61035a612db7565b6040820151600061036a82611d14565b9050600061037782611c24565b60408681015190516328ebbe8b60e21b81526001600160a01b039182166004820152919250879160009183169063a3aefa2c90602401600060405180830381865afa1580156103ca573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526103f29190810190613962565b90506000876040015190506000604051806101a001604052808a6000015181526020018a602001516001600160a01b031681526020018a604001516001600160a01b031681526020018a6060015181526020018a608001518152602001846000015181526020018460200151815260200184604001518152602001836001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104cf9190613a16565b6001600160a01b03168152602001836001600160a01b031663e87554466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561051b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053f9190613a33565b8152602001836001600160a01b0316634ada90af6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610582573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105a69190613a33565b8152602001836001600160a01b031663db5c65de6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060d9190613a33565b8152602001959095525092955050505050505b92915050565b6060816000816001600160401b0381111561064357610643612f39565b60405190808252806020026020018201604052801561068857816020015b60408051808201909152600080825260208201528152602001906001900390816106615790505b50905060005b828110156106e5576106c08686838181106106ab576106ab613a4c565b905060200201602081019061025a919061345c565b8282815181106106d2576106d2613a4c565b602090810291909101015260010161068e565b50949350505050565b606060008290506000816001600160a01b031663d88ff1f46040518163ffffffff1660e01b8152600401600060405180830381865afa158015610735573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261075d9190810190613ae5565b80519091506000816001600160401b0381111561077c5761077c612f39565b6040519080825280602002602001820160405280156107b557816020015b6107a2612db7565b81526020019060019003908161079a5790505b50905060005b828110156108175760008482815181106107d7576107d7613a4c565b6020026020010151905060006107ed8983610352565b90508084848151811061080257610802613a4c565b602090810291909101015250506001016107bb565b5095945050505050565b60408051606080820183526000808352602083018190529282015290828161084882611d14565b90506000826001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561088a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ae9190613a16565b9050600082516001600160401b038111156108cb576108cb612f39565b60405190808252806020026020018201604052801561091057816020015b60408051808201909152600080825260208201528152602001906001900390816108e95790505b509050610940604051806060016040528060006001600160a01b0316815260200160008152602001606081525090565b6001600160a01b03881681526040810182905260005b8451811015610b1c57604080518082019091526000808252602082015285828151811061098557610985613a4c565b602002602001015181600001906001600160a01b031690816001600160a01b031681525050670de0b6b3a7640000856001600160a01b031663fc57d4df8885815181106109d4576109d4613a4c565b60200260200101516040518263ffffffff1660e01b8152600401610a0791906001600160a01b0391909116815260200190565b602060405180830381865afa158015610a24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a489190613a33565b878481518110610a5a57610a5a613a4c565b60200260200101516001600160a01b031663bbcac5576040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac39190613a33565b610acd9190613bab565b610ad79190613bc2565b60208201526040830151805182919084908110610af657610af6613a4c565b6020026020010181905250806020015188610b119190613be4565b975050600101610956565b506020810195909552509295945050505050565b610b38612db7565b604051637aee632d60e01b81526001600160a01b0383811660048301528491610baf91839190821690637aee632d90602401600060405180830381865afa158015610b87573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261011e9190810190613bf7565b949350505050565b60405163266e0a7f60e01b81526001600160a01b0383811660048301528281166024830152600091859182169063266e0a7f90604401602060405180830381865afa158015610c0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2e9190613a16565b95945050505050565b60606000610c4483611d14565b90506000836001600160a01b03166361252fd16040518163ffffffff1660e01b8152600401600060405180830381865afa158015610c86573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cae9190810190613c2b565b9050600081516001600160401b03811115610ccb57610ccb612f39565b604051908082528060200260200182016040528015610d1c57816020015b6040805160808101825260008082526020808301829052928201526060808201528252600019909201910181610ce95790505b50905060005b8251811015610817576040805160808101825260008082526020820181905291810191909152606080820152838281518110610d6057610d60613a4c565b60209081029190910101516001600160a01b031681528351849083908110610d8a57610d8a613a4c565b60200260200101516001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dcf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df39190613a16565b6001600160a01b031660208201528351849083908110610e1557610e15613a4c565b6020908102919091010151604051631627ee8960e01b81526001600160a01b038a8116600483015290911690631627ee8990602401602060405180830381865afa158015610e67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8b9190613a33565b816040018181525050610eb88886868581518110610eab57610eab613a4c565b6020026020010151611eb3565b816060018190525080838381518110610ed357610ed3613a4c565b602090810291909101015250600101610d22565b6060826000816001600160401b03811115610f0457610f04612f39565b604051908082528060200260200182016040528015610f3d57816020015b610f2a612e3a565b815260200190600190039081610f225790505b50905060005b8281101561081757610f7b878783818110610f6057610f60613a4c565b9050602002016020810190610f75919061345c565b866118ca565b828281518110610f8d57610f8d613a4c565b6020908102919091010152600101610f43565b60408051808201909152600080825260208201526000826001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ff4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110189190613a16565b90506000816001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561105a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061107e9190613a16565b6040805180820182526001600160a01b03808816808352925163fc57d4df60e01b815260048101939093529293509160208301919084169063fc57d4df90602401602060405180830381865afa1580156110dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111009190613a33565b9052949350505050565b611112612e79565b6000826001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611152573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111769190613a33565b90506000836001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111dc9190613a16565b604051638e8f294b60e01b81526001600160a01b03868116600483015291925082916000918291841690638e8f294b906024016040805180830381865afa15801561122b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061124f9190613cc9565b915091506000876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611293573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b79190613a16565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061131d9190613cf5565b60ff1690506000805b600860ff8216116113e3576000886001600160a01b031663e85a29608d8460ff16600881111561135857611358613d18565b6040518363ffffffff1660e01b8152600401611375929190613d2e565b602060405180830381865afa158015611392573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b69190613d69565b6113c15760006113c4565b60015b60ff9081169083161b9290921791506113dc81613d84565b9050611326565b506000808b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611425573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114499190613a33565b11156114b4578a6001600160a01b031663ae9d70b06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561148d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114b19190613a33565b90505b6040518061022001604052808c6001600160a01b031681526020018a81526020018281526020018c6001600160a01b031663f8f9da286040518163ffffffff1660e01b8152600401602060405180830381865afa158015611519573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153d9190613a33565b81526020018c6001600160a01b031663173b99046040518163ffffffff1660e01b8152600401602060405180830381865afa158015611580573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a49190613a33565b81526040516302c3bcbb60e01b81526001600160a01b038e811660048301526020909201918a16906302c3bcbb90602401602060405180830381865afa1580156115f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116169190613a33565b815260405163252c221960e11b81526001600160a01b038e811660048301526020909201918a1690634a58443290602401602060405180830381865afa158015611664573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116889190613a33565b81526020018c6001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ef9190613a33565b81526020018c6001600160a01b0316638f840ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611732573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117569190613a33565b81526020018c6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611799573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117bd9190613a33565b81526020018c6001600160a01b0316633b1d21a26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611800573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118249190613a33565b81526020018715158152602001868152602001856001600160a01b031681526020018c6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611884573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118a89190613cf5565b60ff168152602001848152602001838152509950505050505050505050919050565b6118d2612e3a565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908516906370a0823190602401602060405180830381865afa15801561191c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119409190613a33565b6040516305eff7ef60e21b81526001600160a01b0385811660048301529192506000918616906317bfdfbc906024016020604051808303816000875af115801561198e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b29190613a33565b604051633af9e66960e01b81526001600160a01b038681166004830152919250600091871690633af9e669906024016020604051808303816000875af1158015611a00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a249190613a33565b90506000806000886001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a8d9190613a16565b6040516370a0823160e01b81526001600160a01b038a81166004830152919250908216906370a0823190602401602060405180830381865afa158015611ad7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611afb9190613a33565b604051636eb1769f60e11b81526001600160a01b038a811660048301528b811660248301529194509082169063dd62ed3e90604401602060405180830381865afa158015611b4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b719190613a33565b6040805160c0810182526001600160a01b038c168152602081019890985287019590955250506060840191909152608083015260a0820152905092915050565b604051631e6db74760e31b81526001600160a01b038281166004830152606091849182169063f36dba3890602401600060405180830381865afa158015611bfc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610baf9190810190613da3565b80516060906000816001600160401b03811115611c4357611c43612f39565b604051908082528060200260200182016040528015611c7c57816020015b611c69612e79565b815260200190600190039081611c615790505b50905060005b82811015611cd157611cac858281518110611c9f57611c9f613a4c565b602002602001015161110a565b828281518110611cbe57611cbe613a4c565b6020908102919091010152600101611c82565b509392505050565b6000611d077f000000000000000000000000000000000000000000000000000000000000000063ffffffff16565b905090565b4390565b4290565b60606000826001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015611d56573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d7e9190810190613e31565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031603611dbf5792915050565b8051600090815b81811015611ea9576000848281518110611de257611de2613a4c565b60200260200101516001600160a01b03166322abdbf56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e4b9190613a33565b1115611ea157838181518110611e6357611e63613a4c565b6020026020010151848481518110611e7d57611e7d613a4c565b6001600160a01b0390921660209283029190910190910152611e9e83613ebf565b92505b600101611dc6565b5050815292915050565b6060600083516001600160401b03811115611ed057611ed0612f39565b604051908082528060200260200182016040528015611f1557816020015b6040805180820190915260008082526020820152815260200190600190039081611eee5790505b50905060005b84518110156106e557611f51604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b611f7e604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b7f00000000000000000000000000000000000000000000000000000000000000001561210157856001600160a01b0316638f693ec7888581518110611fc557611fc5613a4c565b60200260200101516040518263ffffffff1660e01b8152600401611ff891906001600160a01b0391909116815260200190565b606060405180830381865afa158015612015573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120399190613eef565b604085015260208401526001600160e01b0316825286516001600160a01b0387169063818149459089908690811061207357612073613a4c565b60200260200101516040518263ffffffff1660e01b81526004016120a691906001600160a01b0391909116815260200190565b606060405180830381865afa1580156120c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e79190613eef565b604084015260208301526001600160e01b0316815261226c565b856001600160a01b0316632c427b5788858151811061212257612122613a4c565b60200260200101516040518263ffffffff1660e01b815260040161215591906001600160a01b0391909116815260200190565b606060405180830381865afa158015612172573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121969190613f38565b63ffffffff90811660408601521660208401526001600160e01b0316825286516001600160a01b038716906392a18235908990869081106121d9576121d9613a4c565b60200260200101516040518263ffffffff1660e01b815260040161220c91906001600160a01b0391909116815260200190565b606060405180830381865afa158015612229573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061224d9190613f38565b63ffffffff90811660408501521660208301526001600160e01b031681525b6000604051806020016040528089868151811061228b5761228b613a4c565b60200260200101516001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122f49190613a33565b815250905061231e88858151811061230e5761230e613a4c565b6020026020010151888584612413565b61234288858151811061233357612333613a4c565b60200260200101518884612614565b600061236a89868151811061235957612359613a4c565b6020026020010151898c878661280b565b905060006123938a878151811061238357612383613a4c565b60200260200101518a8d87612a3b565b60408051808201909152600080825260208201529091508a87815181106123bc576123bc613a4c565b60209081029190910101516001600160a01b031681526123dc8284613be4565b6020820152875181908990899081106123f7576123f7613a4c565b6020026020010181905250505050505050806001019050611f1b565b604051637c05a7c560e01b81526001600160a01b03858116600483015260009190851690637c05a7c590602401602060405180830381865afa15801561245d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124819190613a33565b9050600061248d611cd9565b9050600084604001511180156124a65750836040015181115b156124b2575060408301515b60006124c2828660200151612c5f565b90506000811180156124d45750600083115b156125fd576000612546886001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561251c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125409190613a33565b86612c72565b905060006125548386612c90565b90506000808311612574576040518060200160405280600081525061257e565b61257e8284612c9c565b905060006125a760405180602001604052808b600001516001600160e01b031681525083612ce1565b90506125e28160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612d0d565b6001600160e01b03168952505050506020850182905261260b565b801561260b57602085018290525b50505050505050565b604051631d31307360e21b81526001600160a01b038481166004830152600091908416906374c4c1cc90602401602060405180830381865afa15801561265e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126829190613a33565b9050600061268e611cd9565b9050600083604001511180156126a75750826040015181115b156126b3575060408201515b60006126c3828560200151612c5f565b90506000811180156126d55750600083115b156127f5576000866001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561271a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061273e9190613a33565b9050600061274c8386612c90565b9050600080831161276c5760405180602001604052806000815250612776565b6127768284612c9c565b9050600061279f60405180602001604052808a600001516001600160e01b031681525083612ce1565b90506127da8160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612d0d565b6001600160e01b031688525050505060208401829052612803565b801561280357602084018290525b505050505050565b604080516020808201835284516001600160e01b031682528251908101928390526336fe846560e11b9092526001600160a01b0387811660248401528581166044840152600092839181908916636dfd08ca60648301602060405180830381865afa15801561287e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a29190613a33565b905280519091501580156129245750866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129139190613f7b565b6001600160e01b0316826000015110155b1561299757866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061298b9190613f7b565b6001600160e01b031681525b60006129a38383612d49565b6040516395dd919360e01b81526001600160a01b038981166004830152919250600091612a1e91908c16906395dd919390602401602060405180830381865afa1580156129f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a189190613a33565b87612c72565b90506000612a2c8284612d75565b9b9a5050505050505050505050565b604080516020808201835283516001600160e01b0316825282519081019283905263552c097160e01b9092526001600160a01b038681166024840152848116604484015260009283918190881663552c097160648301602060405180830381865afa158015612aae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ad29190613a33565b90528051909150158015612b545750856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b439190613f7b565b6001600160e01b0316826000015110155b15612bc757856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bbb9190613f7b565b6001600160e01b031681525b6000612bd38383612d49565b6040516370a0823160e01b81526001600160a01b0388811660048301529192506000918a16906370a0823190602401602060405180830381865afa158015612c1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c439190613a33565b90506000612c518284612d75565b9a9950505050505050505050565b6000612c6b8284613f96565b9392505050565b6000612c6b612c8984670de0b6b3a7640000612c90565b8351612d9f565b6000612c6b8284613bab565b6040805160208101909152600081526040518060200160405280612cd8612cd2866ec097ce7bc90715b34b9f1000000000612c90565b85612d9f565b90529392505050565b6040805160208101909152600081526040518060200160405280612cd885600001518560000151612dab565b6000816001600160e01b03841115612d415760405162461bcd60e51b8152600401612d389190613fa9565b60405180910390fd5b509192915050565b6040805160208101909152600081526040518060200160405280612cd885600001518560000151612c5f565b60006ec097ce7bc90715b34b9f1000000000612d95848460000151612c90565b612c6b9190613bc2565b6000612c6b8284613bc2565b6000612c6b8284613be4565b604051806101a001604052806060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160608152602001606081526020016060815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001606081525090565b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180610220016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b6001600160a01b0381168114612f2657600080fd5b50565b8035612f3481612f11565b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715612f7157612f71612f39565b60405290565b604051606081016001600160401b0381118282101715612f7157612f71612f39565b604051601f8201601f191681016001600160401b0381118282101715612fc157612fc1612f39565b604052919050565b60006001600160401b03821115612fe257612fe2612f39565b50601f01601f191660200190565b6000806040838503121561300357600080fd5b823561300e81612f11565b91506020838101356001600160401b038082111561302b57600080fd5b9085019060a0828803121561303f57600080fd5b613047612f4f565b82358281111561305657600080fd5b83019150601f8201881361306957600080fd5b813561307c61307782612fc9565b612f99565b818152898683860101111561309057600080fd5b8186850187830137600086838301015280835250506130b0848401612f29565b848201526130c060408401612f29565b60408201526060830135606082015260808301356080820152809450505050509250929050565b60005b838110156131025781810151838201526020016130ea565b50506000910152565b600081518084526131238160208601602086016130e7565b601f01601f19169290920160200192915050565b80516001600160a01b031682526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e0830152610100808201518184015250610120808201518184015250610140808201518184015250610160808201516131c28285018215159052565b505061018081810151908301526101a0808201516001600160a01b0316908301526101c080820151908301526101e0808201519083015261020090810151910152565b60008151808452602080850194506020840160005b838110156132415761322d878351613137565b61022096909601959082019060010161321a565b509495945050505050565b60006101a082518185526132628286018261310b565b915050602083015161327f60208601826001600160a01b03169052565b50604083015161329a60408601826001600160a01b03169052565b50606083015160608501526080830151608085015260a083015184820360a08601526132c6828261310b565b91505060c083015184820360c08601526132e0828261310b565b91505060e083015184820360e08601526132fa828261310b565b91505061010080840151613318828701826001600160a01b03169052565b505061012083810151908501526101408084015190850152610160808401519085015261018080840151858303828701526133538382613205565b9695505050505050565b602081526000612c6b602083018461324c565b60008083601f84011261338257600080fd5b5081356001600160401b0381111561339957600080fd5b6020830191508360208260051b85010111156133b457600080fd5b9250929050565b600080602083850312156133ce57600080fd5b82356001600160401b038111156133e457600080fd5b6133f085828601613370565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b8281101561344f5761343f84835180516001600160a01b03168252602090810151910152565b9284019290850190600101613419565b5091979650505050505050565b60006020828403121561346e57600080fd5b8135612c6b81612f11565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156134d057603f198886030184526134be85835161324c565b945092850192908501906001016134a2565b5092979650505050505050565b602080825282516001600160a01b03168282015282810151604080840191909152808401516060808501528051608085018190526000939291830191849160a08701905b8084101561355b5761354782865180516001600160a01b03168252602090810151910152565b938501936001939093019290820190613521565b50979650505050505050565b6000806040838503121561357a57600080fd5b823561358581612f11565b9150602083013561359581612f11565b809150509250929050565b6000806000606084860312156135b557600080fd5b83356135c081612f11565b925060208401356135d081612f11565b915060408401356135e081612f11565b809150509250925092565b600060208083018184528085518083526040925060408601915060408160051b8701018488016000805b848110156136b857898403603f19018652825180516001600160a01b03908116865289820151168986015287810151888601526060908101516080918601829052805191860182905289019060a086019084905b808210156136a35761368f83855180516001600160a01b03168252602090810151910152565b928b0192918a019160019190910190613669565b50509689019694505091870191600101613615565b50919998505050505050505050565b6000806000604084860312156136dc57600080fd5b83356001600160401b038111156136f257600080fd5b6136fe86828701613370565b90945092505060208401356135e081612f11565b80516001600160a01b031682526020808201519083015260408082015190830152606080820151908301526080808201519083015260a090810151910152565b6020808252825182820181905260009190848201906040850190845b8181101561379457613781838551613712565b9284019260c0929092019160010161376e565b50909695505050505050565b81516001600160a01b031681526020808301519082015260408101610620565b61022081016106208284613137565b60c081016106208284613712565b6020808252825182820181905260009190848201906040850190845b818110156137945783516001600160a01b0316835292840192918401916001016137f9565b60006001600160401b0382111561383757613837612f39565b5060051b60200190565b6000602080838503121561385457600080fd5b82356001600160401b0381111561386a57600080fd5b8301601f8101851361387b57600080fd5b80356138896130778261381e565b81815260059190911b820183019083810190878311156138a857600080fd5b928401925b828410156138cf5783356138c081612f11565b825292840192908401906138ad565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561379457613909838551613137565b9284019261022092909201916001016138f6565b600082601f83011261392e57600080fd5b815161393c61307782612fc9565b81815284602083860101111561395157600080fd5b610baf8260208301602087016130e7565b60006020828403121561397457600080fd5b81516001600160401b038082111561398b57600080fd5b908301906060828603121561399f57600080fd5b6139a7612f77565b8251828111156139b657600080fd5b6139c28782860161391d565b8252506020830151828111156139d757600080fd5b6139e38782860161391d565b6020830152506040830151828111156139fb57600080fd5b613a078782860161391d565b60408301525095945050505050565b600060208284031215613a2857600080fd5b8151612c6b81612f11565b600060208284031215613a4557600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600060a08284031215613a7457600080fd5b613a7c612f4f565b905081516001600160401b03811115613a9457600080fd5b613aa08482850161391d565b8252506020820151613ab181612f11565b60208201526040820151613ac481612f11565b80604083015250606082015160608201526080820151608082015292915050565b60006020808385031215613af857600080fd5b82516001600160401b0380821115613b0f57600080fd5b818501915085601f830112613b2357600080fd5b8151613b316130778261381e565b81815260059190911b83018401908481019088831115613b5057600080fd5b8585015b83811015613b8857805185811115613b6c5760008081fd5b613b7a8b89838a0101613a62565b845250918601918601613b54565b5098975050505050505050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761062057610620613b95565b600082613bdf57634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561062057610620613b95565b600060208284031215613c0957600080fd5b81516001600160401b03811115613c1f57600080fd5b610baf84828501613a62565b60006020808385031215613c3e57600080fd5b82516001600160401b03811115613c5457600080fd5b8301601f81018513613c6557600080fd5b8051613c736130778261381e565b81815260059190911b82018301908381019087831115613c9257600080fd5b928401925b828410156138cf578351613caa81612f11565b82529284019290840190613c97565b80518015158114612f3457600080fd5b60008060408385031215613cdc57600080fd5b613ce583613cb9565b9150602083015190509250929050565b600060208284031215613d0757600080fd5b815160ff81168114612c6b57600080fd5b634e487b7160e01b600052602160045260246000fd5b6001600160a01b03831681526040810160098310613d5c57634e487b7160e01b600052602160045260246000fd5b8260208301529392505050565b600060208284031215613d7b57600080fd5b612c6b82613cb9565b600060ff821660ff8103613d9a57613d9a613b95565b60010192915050565b60006020808385031215613db657600080fd5b82516001600160401b03811115613dcc57600080fd5b8301601f81018513613ddd57600080fd5b8051613deb6130778261381e565b81815260059190911b82018301908381019087831115613e0a57600080fd5b928401925b828410156138cf578351613e2281612f11565b82529284019290840190613e0f565b60006020808385031215613e4457600080fd5b82516001600160401b03811115613e5a57600080fd5b8301601f81018513613e6b57600080fd5b8051613e796130778261381e565b81815260059190911b82018301908381019087831115613e9857600080fd5b928401925b828410156138cf578351613eb081612f11565b82529284019290840190613e9d565b600060018201613ed157613ed1613b95565b5060010190565b80516001600160e01b0381168114612f3457600080fd5b600080600060608486031215613f0457600080fd5b613f0d84613ed8565b925060208401519150604084015190509250925092565b805163ffffffff81168114612f3457600080fd5b600080600060608486031215613f4d57600080fd5b613f5684613ed8565b9250613f6460208501613f24565b9150613f7260408501613f24565b90509250925092565b600060208284031215613f8d57600080fd5b612c6b82613ed8565b8181038181111561062057610620613b95565b602081526000612c6b602083018461310b56fea264697066735822122096dca9ef030f65331631c7305d4d9405c1d0b56d48eb3787508d19369d85297764736f6c63430008190033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061010b5760003560e01c80637c51b642116100a2578063c7ad089511610071578063c7ad0895146102ac578063d26998e9146102e3578063d77ebf961461030a578063e0a67f111461032a578063e1d146fb1461034a57600080fd5b80637c51b6421461022c5780637c84e3b31461024c578063aa5dbd231461026c578063b31242391461028c57600080fd5b806347d86a81116100de57806347d86a811461019957806355dd9515146101ac5780636857249c146101d75780637a27db571461020c57600080fd5b80630d3ae318146101105780631f884fdf14610139578063345954dc146101595780633e3e399c14610179575b600080fd5b61012361011e366004612ff0565b610352565b604051610130919061335d565b60405180910390f35b61014c6101473660046133bb565b610626565b60405161013091906133fc565b61016c61016736600461345c565b6106ee565b6040516101309190613479565b61018c61018736600461345c565b610821565b60405161013091906134dd565b6101236101a7366004613567565b610b30565b6101bf6101ba3660046135a0565b610bb7565b6040516001600160a01b039091168152602001610130565b6101fe7f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610130565b61021f61021a366004613567565b610c37565b60405161013091906135eb565b61023f61023a3660046136c7565b610ee7565b6040516101309190613752565b61025f61025a36600461345c565b610fa0565b60405161013091906137a0565b61027f61027a36600461345c565b61110a565b60405161013091906137c0565b61029f61029a366004613567565b6118ca565b60405161013091906137cf565b6102d37f000000000000000000000000000000000000000000000000000000000000000081565b6040519015158152602001610130565b6101bf7f000000000000000000000000000000000000000000000000000000000000000081565b61031d610318366004613567565b611bb1565b60405161013091906137dd565b61033d610338366004613841565b611c24565b60405161013091906138da565b6101fe611cd9565b61035a612db7565b6040820151600061036a82611d14565b9050600061037782611c24565b60408681015190516328ebbe8b60e21b81526001600160a01b039182166004820152919250879160009183169063a3aefa2c90602401600060405180830381865afa1580156103ca573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526103f29190810190613962565b90506000876040015190506000604051806101a001604052808a6000015181526020018a602001516001600160a01b031681526020018a604001516001600160a01b031681526020018a6060015181526020018a608001518152602001846000015181526020018460200151815260200184604001518152602001836001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104cf9190613a16565b6001600160a01b03168152602001836001600160a01b031663e87554466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561051b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053f9190613a33565b8152602001836001600160a01b0316634ada90af6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610582573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105a69190613a33565b8152602001836001600160a01b031663db5c65de6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060d9190613a33565b8152602001959095525092955050505050505b92915050565b6060816000816001600160401b0381111561064357610643612f39565b60405190808252806020026020018201604052801561068857816020015b60408051808201909152600080825260208201528152602001906001900390816106615790505b50905060005b828110156106e5576106c08686838181106106ab576106ab613a4c565b905060200201602081019061025a919061345c565b8282815181106106d2576106d2613a4c565b602090810291909101015260010161068e565b50949350505050565b606060008290506000816001600160a01b031663d88ff1f46040518163ffffffff1660e01b8152600401600060405180830381865afa158015610735573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261075d9190810190613ae5565b80519091506000816001600160401b0381111561077c5761077c612f39565b6040519080825280602002602001820160405280156107b557816020015b6107a2612db7565b81526020019060019003908161079a5790505b50905060005b828110156108175760008482815181106107d7576107d7613a4c565b6020026020010151905060006107ed8983610352565b90508084848151811061080257610802613a4c565b602090810291909101015250506001016107bb565b5095945050505050565b60408051606080820183526000808352602083018190529282015290828161084882611d14565b90506000826001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561088a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ae9190613a16565b9050600082516001600160401b038111156108cb576108cb612f39565b60405190808252806020026020018201604052801561091057816020015b60408051808201909152600080825260208201528152602001906001900390816108e95790505b509050610940604051806060016040528060006001600160a01b0316815260200160008152602001606081525090565b6001600160a01b03881681526040810182905260005b8451811015610b1c57604080518082019091526000808252602082015285828151811061098557610985613a4c565b602002602001015181600001906001600160a01b031690816001600160a01b031681525050670de0b6b3a7640000856001600160a01b031663fc57d4df8885815181106109d4576109d4613a4c565b60200260200101516040518263ffffffff1660e01b8152600401610a0791906001600160a01b0391909116815260200190565b602060405180830381865afa158015610a24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a489190613a33565b878481518110610a5a57610a5a613a4c565b60200260200101516001600160a01b031663bbcac5576040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac39190613a33565b610acd9190613bab565b610ad79190613bc2565b60208201526040830151805182919084908110610af657610af6613a4c565b6020026020010181905250806020015188610b119190613be4565b975050600101610956565b506020810195909552509295945050505050565b610b38612db7565b604051637aee632d60e01b81526001600160a01b0383811660048301528491610baf91839190821690637aee632d90602401600060405180830381865afa158015610b87573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261011e9190810190613bf7565b949350505050565b60405163266e0a7f60e01b81526001600160a01b0383811660048301528281166024830152600091859182169063266e0a7f90604401602060405180830381865afa158015610c0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2e9190613a16565b95945050505050565b60606000610c4483611d14565b90506000836001600160a01b03166361252fd16040518163ffffffff1660e01b8152600401600060405180830381865afa158015610c86573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cae9190810190613c2b565b9050600081516001600160401b03811115610ccb57610ccb612f39565b604051908082528060200260200182016040528015610d1c57816020015b6040805160808101825260008082526020808301829052928201526060808201528252600019909201910181610ce95790505b50905060005b8251811015610817576040805160808101825260008082526020820181905291810191909152606080820152838281518110610d6057610d60613a4c565b60209081029190910101516001600160a01b031681528351849083908110610d8a57610d8a613a4c565b60200260200101516001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dcf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df39190613a16565b6001600160a01b031660208201528351849083908110610e1557610e15613a4c565b6020908102919091010151604051631627ee8960e01b81526001600160a01b038a8116600483015290911690631627ee8990602401602060405180830381865afa158015610e67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8b9190613a33565b816040018181525050610eb88886868581518110610eab57610eab613a4c565b6020026020010151611eb3565b816060018190525080838381518110610ed357610ed3613a4c565b602090810291909101015250600101610d22565b6060826000816001600160401b03811115610f0457610f04612f39565b604051908082528060200260200182016040528015610f3d57816020015b610f2a612e3a565b815260200190600190039081610f225790505b50905060005b8281101561081757610f7b878783818110610f6057610f60613a4c565b9050602002016020810190610f75919061345c565b866118ca565b828281518110610f8d57610f8d613a4c565b6020908102919091010152600101610f43565b60408051808201909152600080825260208201526000826001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ff4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110189190613a16565b90506000816001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561105a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061107e9190613a16565b6040805180820182526001600160a01b03808816808352925163fc57d4df60e01b815260048101939093529293509160208301919084169063fc57d4df90602401602060405180830381865afa1580156110dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111009190613a33565b9052949350505050565b611112612e79565b6000826001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611152573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111769190613a33565b90506000836001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111dc9190613a16565b604051638e8f294b60e01b81526001600160a01b03868116600483015291925082916000918291841690638e8f294b906024016040805180830381865afa15801561122b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061124f9190613cc9565b915091506000876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611293573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b79190613a16565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061131d9190613cf5565b60ff1690506000805b600860ff8216116113e3576000886001600160a01b031663e85a29608d8460ff16600881111561135857611358613d18565b6040518363ffffffff1660e01b8152600401611375929190613d2e565b602060405180830381865afa158015611392573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b69190613d69565b6113c15760006113c4565b60015b60ff9081169083161b9290921791506113dc81613d84565b9050611326565b506000808b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611425573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114499190613a33565b11156114b4578a6001600160a01b031663ae9d70b06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561148d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114b19190613a33565b90505b6040518061022001604052808c6001600160a01b031681526020018a81526020018281526020018c6001600160a01b031663f8f9da286040518163ffffffff1660e01b8152600401602060405180830381865afa158015611519573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153d9190613a33565b81526020018c6001600160a01b031663173b99046040518163ffffffff1660e01b8152600401602060405180830381865afa158015611580573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a49190613a33565b81526040516302c3bcbb60e01b81526001600160a01b038e811660048301526020909201918a16906302c3bcbb90602401602060405180830381865afa1580156115f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116169190613a33565b815260405163252c221960e11b81526001600160a01b038e811660048301526020909201918a1690634a58443290602401602060405180830381865afa158015611664573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116889190613a33565b81526020018c6001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ef9190613a33565b81526020018c6001600160a01b0316638f840ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611732573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117569190613a33565b81526020018c6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611799573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117bd9190613a33565b81526020018c6001600160a01b0316633b1d21a26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611800573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118249190613a33565b81526020018715158152602001868152602001856001600160a01b031681526020018c6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611884573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118a89190613cf5565b60ff168152602001848152602001838152509950505050505050505050919050565b6118d2612e3a565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908516906370a0823190602401602060405180830381865afa15801561191c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119409190613a33565b6040516305eff7ef60e21b81526001600160a01b0385811660048301529192506000918616906317bfdfbc906024016020604051808303816000875af115801561198e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b29190613a33565b604051633af9e66960e01b81526001600160a01b038681166004830152919250600091871690633af9e669906024016020604051808303816000875af1158015611a00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a249190613a33565b90506000806000886001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a8d9190613a16565b6040516370a0823160e01b81526001600160a01b038a81166004830152919250908216906370a0823190602401602060405180830381865afa158015611ad7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611afb9190613a33565b604051636eb1769f60e11b81526001600160a01b038a811660048301528b811660248301529194509082169063dd62ed3e90604401602060405180830381865afa158015611b4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b719190613a33565b6040805160c0810182526001600160a01b038c168152602081019890985287019590955250506060840191909152608083015260a0820152905092915050565b604051631e6db74760e31b81526001600160a01b038281166004830152606091849182169063f36dba3890602401600060405180830381865afa158015611bfc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610baf9190810190613da3565b80516060906000816001600160401b03811115611c4357611c43612f39565b604051908082528060200260200182016040528015611c7c57816020015b611c69612e79565b815260200190600190039081611c615790505b50905060005b82811015611cd157611cac858281518110611c9f57611c9f613a4c565b602002602001015161110a565b828281518110611cbe57611cbe613a4c565b6020908102919091010152600101611c82565b509392505050565b6000611d077f000000000000000000000000000000000000000000000000000000000000000063ffffffff16565b905090565b4390565b4290565b60606000826001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015611d56573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d7e9190810190613e31565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031603611dbf5792915050565b8051600090815b81811015611ea9576000848281518110611de257611de2613a4c565b60200260200101516001600160a01b03166322abdbf56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e4b9190613a33565b1115611ea157838181518110611e6357611e63613a4c565b6020026020010151848481518110611e7d57611e7d613a4c565b6001600160a01b0390921660209283029190910190910152611e9e83613ebf565b92505b600101611dc6565b5050815292915050565b6060600083516001600160401b03811115611ed057611ed0612f39565b604051908082528060200260200182016040528015611f1557816020015b6040805180820190915260008082526020820152815260200190600190039081611eee5790505b50905060005b84518110156106e557611f51604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b611f7e604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b7f00000000000000000000000000000000000000000000000000000000000000001561210157856001600160a01b0316638f693ec7888581518110611fc557611fc5613a4c565b60200260200101516040518263ffffffff1660e01b8152600401611ff891906001600160a01b0391909116815260200190565b606060405180830381865afa158015612015573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120399190613eef565b604085015260208401526001600160e01b0316825286516001600160a01b0387169063818149459089908690811061207357612073613a4c565b60200260200101516040518263ffffffff1660e01b81526004016120a691906001600160a01b0391909116815260200190565b606060405180830381865afa1580156120c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e79190613eef565b604084015260208301526001600160e01b0316815261226c565b856001600160a01b0316632c427b5788858151811061212257612122613a4c565b60200260200101516040518263ffffffff1660e01b815260040161215591906001600160a01b0391909116815260200190565b606060405180830381865afa158015612172573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121969190613f38565b63ffffffff90811660408601521660208401526001600160e01b0316825286516001600160a01b038716906392a18235908990869081106121d9576121d9613a4c565b60200260200101516040518263ffffffff1660e01b815260040161220c91906001600160a01b0391909116815260200190565b606060405180830381865afa158015612229573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061224d9190613f38565b63ffffffff90811660408501521660208301526001600160e01b031681525b6000604051806020016040528089868151811061228b5761228b613a4c565b60200260200101516001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122f49190613a33565b815250905061231e88858151811061230e5761230e613a4c565b6020026020010151888584612413565b61234288858151811061233357612333613a4c565b60200260200101518884612614565b600061236a89868151811061235957612359613a4c565b6020026020010151898c878661280b565b905060006123938a878151811061238357612383613a4c565b60200260200101518a8d87612a3b565b60408051808201909152600080825260208201529091508a87815181106123bc576123bc613a4c565b60209081029190910101516001600160a01b031681526123dc8284613be4565b6020820152875181908990899081106123f7576123f7613a4c565b6020026020010181905250505050505050806001019050611f1b565b604051637c05a7c560e01b81526001600160a01b03858116600483015260009190851690637c05a7c590602401602060405180830381865afa15801561245d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124819190613a33565b9050600061248d611cd9565b9050600084604001511180156124a65750836040015181115b156124b2575060408301515b60006124c2828660200151612c5f565b90506000811180156124d45750600083115b156125fd576000612546886001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561251c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125409190613a33565b86612c72565b905060006125548386612c90565b90506000808311612574576040518060200160405280600081525061257e565b61257e8284612c9c565b905060006125a760405180602001604052808b600001516001600160e01b031681525083612ce1565b90506125e28160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612d0d565b6001600160e01b03168952505050506020850182905261260b565b801561260b57602085018290525b50505050505050565b604051631d31307360e21b81526001600160a01b038481166004830152600091908416906374c4c1cc90602401602060405180830381865afa15801561265e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126829190613a33565b9050600061268e611cd9565b9050600083604001511180156126a75750826040015181115b156126b3575060408201515b60006126c3828560200151612c5f565b90506000811180156126d55750600083115b156127f5576000866001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561271a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061273e9190613a33565b9050600061274c8386612c90565b9050600080831161276c5760405180602001604052806000815250612776565b6127768284612c9c565b9050600061279f60405180602001604052808a600001516001600160e01b031681525083612ce1565b90506127da8160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612d0d565b6001600160e01b031688525050505060208401829052612803565b801561280357602084018290525b505050505050565b604080516020808201835284516001600160e01b031682528251908101928390526336fe846560e11b9092526001600160a01b0387811660248401528581166044840152600092839181908916636dfd08ca60648301602060405180830381865afa15801561287e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a29190613a33565b905280519091501580156129245750866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129139190613f7b565b6001600160e01b0316826000015110155b1561299757866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061298b9190613f7b565b6001600160e01b031681525b60006129a38383612d49565b6040516395dd919360e01b81526001600160a01b038981166004830152919250600091612a1e91908c16906395dd919390602401602060405180830381865afa1580156129f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a189190613a33565b87612c72565b90506000612a2c8284612d75565b9b9a5050505050505050505050565b604080516020808201835283516001600160e01b0316825282519081019283905263552c097160e01b9092526001600160a01b038681166024840152848116604484015260009283918190881663552c097160648301602060405180830381865afa158015612aae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ad29190613a33565b90528051909150158015612b545750856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b439190613f7b565b6001600160e01b0316826000015110155b15612bc757856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bbb9190613f7b565b6001600160e01b031681525b6000612bd38383612d49565b6040516370a0823160e01b81526001600160a01b0388811660048301529192506000918a16906370a0823190602401602060405180830381865afa158015612c1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c439190613a33565b90506000612c518284612d75565b9a9950505050505050505050565b6000612c6b8284613f96565b9392505050565b6000612c6b612c8984670de0b6b3a7640000612c90565b8351612d9f565b6000612c6b8284613bab565b6040805160208101909152600081526040518060200160405280612cd8612cd2866ec097ce7bc90715b34b9f1000000000612c90565b85612d9f565b90529392505050565b6040805160208101909152600081526040518060200160405280612cd885600001518560000151612dab565b6000816001600160e01b03841115612d415760405162461bcd60e51b8152600401612d389190613fa9565b60405180910390fd5b509192915050565b6040805160208101909152600081526040518060200160405280612cd885600001518560000151612c5f565b60006ec097ce7bc90715b34b9f1000000000612d95848460000151612c90565b612c6b9190613bc2565b6000612c6b8284613bc2565b6000612c6b8284613be4565b604051806101a001604052806060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160608152602001606081526020016060815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001606081525090565b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180610220016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b6001600160a01b0381168114612f2657600080fd5b50565b8035612f3481612f11565b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715612f7157612f71612f39565b60405290565b604051606081016001600160401b0381118282101715612f7157612f71612f39565b604051601f8201601f191681016001600160401b0381118282101715612fc157612fc1612f39565b604052919050565b60006001600160401b03821115612fe257612fe2612f39565b50601f01601f191660200190565b6000806040838503121561300357600080fd5b823561300e81612f11565b91506020838101356001600160401b038082111561302b57600080fd5b9085019060a0828803121561303f57600080fd5b613047612f4f565b82358281111561305657600080fd5b83019150601f8201881361306957600080fd5b813561307c61307782612fc9565b612f99565b818152898683860101111561309057600080fd5b8186850187830137600086838301015280835250506130b0848401612f29565b848201526130c060408401612f29565b60408201526060830135606082015260808301356080820152809450505050509250929050565b60005b838110156131025781810151838201526020016130ea565b50506000910152565b600081518084526131238160208601602086016130e7565b601f01601f19169290920160200192915050565b80516001600160a01b031682526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e0830152610100808201518184015250610120808201518184015250610140808201518184015250610160808201516131c28285018215159052565b505061018081810151908301526101a0808201516001600160a01b0316908301526101c080820151908301526101e0808201519083015261020090810151910152565b60008151808452602080850194506020840160005b838110156132415761322d878351613137565b61022096909601959082019060010161321a565b509495945050505050565b60006101a082518185526132628286018261310b565b915050602083015161327f60208601826001600160a01b03169052565b50604083015161329a60408601826001600160a01b03169052565b50606083015160608501526080830151608085015260a083015184820360a08601526132c6828261310b565b91505060c083015184820360c08601526132e0828261310b565b91505060e083015184820360e08601526132fa828261310b565b91505061010080840151613318828701826001600160a01b03169052565b505061012083810151908501526101408084015190850152610160808401519085015261018080840151858303828701526133538382613205565b9695505050505050565b602081526000612c6b602083018461324c565b60008083601f84011261338257600080fd5b5081356001600160401b0381111561339957600080fd5b6020830191508360208260051b85010111156133b457600080fd5b9250929050565b600080602083850312156133ce57600080fd5b82356001600160401b038111156133e457600080fd5b6133f085828601613370565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b8281101561344f5761343f84835180516001600160a01b03168252602090810151910152565b9284019290850190600101613419565b5091979650505050505050565b60006020828403121561346e57600080fd5b8135612c6b81612f11565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156134d057603f198886030184526134be85835161324c565b945092850192908501906001016134a2565b5092979650505050505050565b602080825282516001600160a01b03168282015282810151604080840191909152808401516060808501528051608085018190526000939291830191849160a08701905b8084101561355b5761354782865180516001600160a01b03168252602090810151910152565b938501936001939093019290820190613521565b50979650505050505050565b6000806040838503121561357a57600080fd5b823561358581612f11565b9150602083013561359581612f11565b809150509250929050565b6000806000606084860312156135b557600080fd5b83356135c081612f11565b925060208401356135d081612f11565b915060408401356135e081612f11565b809150509250925092565b600060208083018184528085518083526040925060408601915060408160051b8701018488016000805b848110156136b857898403603f19018652825180516001600160a01b03908116865289820151168986015287810151888601526060908101516080918601829052805191860182905289019060a086019084905b808210156136a35761368f83855180516001600160a01b03168252602090810151910152565b928b0192918a019160019190910190613669565b50509689019694505091870191600101613615565b50919998505050505050505050565b6000806000604084860312156136dc57600080fd5b83356001600160401b038111156136f257600080fd5b6136fe86828701613370565b90945092505060208401356135e081612f11565b80516001600160a01b031682526020808201519083015260408082015190830152606080820151908301526080808201519083015260a090810151910152565b6020808252825182820181905260009190848201906040850190845b8181101561379457613781838551613712565b9284019260c0929092019160010161376e565b50909695505050505050565b81516001600160a01b031681526020808301519082015260408101610620565b61022081016106208284613137565b60c081016106208284613712565b6020808252825182820181905260009190848201906040850190845b818110156137945783516001600160a01b0316835292840192918401916001016137f9565b60006001600160401b0382111561383757613837612f39565b5060051b60200190565b6000602080838503121561385457600080fd5b82356001600160401b0381111561386a57600080fd5b8301601f8101851361387b57600080fd5b80356138896130778261381e565b81815260059190911b820183019083810190878311156138a857600080fd5b928401925b828410156138cf5783356138c081612f11565b825292840192908401906138ad565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561379457613909838551613137565b9284019261022092909201916001016138f6565b600082601f83011261392e57600080fd5b815161393c61307782612fc9565b81815284602083860101111561395157600080fd5b610baf8260208301602087016130e7565b60006020828403121561397457600080fd5b81516001600160401b038082111561398b57600080fd5b908301906060828603121561399f57600080fd5b6139a7612f77565b8251828111156139b657600080fd5b6139c28782860161391d565b8252506020830151828111156139d757600080fd5b6139e38782860161391d565b6020830152506040830151828111156139fb57600080fd5b613a078782860161391d565b60408301525095945050505050565b600060208284031215613a2857600080fd5b8151612c6b81612f11565b600060208284031215613a4557600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600060a08284031215613a7457600080fd5b613a7c612f4f565b905081516001600160401b03811115613a9457600080fd5b613aa08482850161391d565b8252506020820151613ab181612f11565b60208201526040820151613ac481612f11565b80604083015250606082015160608201526080820151608082015292915050565b60006020808385031215613af857600080fd5b82516001600160401b0380821115613b0f57600080fd5b818501915085601f830112613b2357600080fd5b8151613b316130778261381e565b81815260059190911b83018401908481019088831115613b5057600080fd5b8585015b83811015613b8857805185811115613b6c5760008081fd5b613b7a8b89838a0101613a62565b845250918601918601613b54565b5098975050505050505050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761062057610620613b95565b600082613bdf57634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561062057610620613b95565b600060208284031215613c0957600080fd5b81516001600160401b03811115613c1f57600080fd5b610baf84828501613a62565b60006020808385031215613c3e57600080fd5b82516001600160401b03811115613c5457600080fd5b8301601f81018513613c6557600080fd5b8051613c736130778261381e565b81815260059190911b82018301908381019087831115613c9257600080fd5b928401925b828410156138cf578351613caa81612f11565b82529284019290840190613c97565b80518015158114612f3457600080fd5b60008060408385031215613cdc57600080fd5b613ce583613cb9565b9150602083015190509250929050565b600060208284031215613d0757600080fd5b815160ff81168114612c6b57600080fd5b634e487b7160e01b600052602160045260246000fd5b6001600160a01b03831681526040810160098310613d5c57634e487b7160e01b600052602160045260246000fd5b8260208301529392505050565b600060208284031215613d7b57600080fd5b612c6b82613cb9565b600060ff821660ff8103613d9a57613d9a613b95565b60010192915050565b60006020808385031215613db657600080fd5b82516001600160401b03811115613dcc57600080fd5b8301601f81018513613ddd57600080fd5b8051613deb6130778261381e565b81815260059190911b82018301908381019087831115613e0a57600080fd5b928401925b828410156138cf578351613e2281612f11565b82529284019290840190613e0f565b60006020808385031215613e4457600080fd5b82516001600160401b03811115613e5a57600080fd5b8301601f81018513613e6b57600080fd5b8051613e796130778261381e565b81815260059190911b82018301908381019087831115613e9857600080fd5b928401925b828410156138cf578351613eb081612f11565b82529284019290840190613e9d565b600060018201613ed157613ed1613b95565b5060010190565b80516001600160e01b0381168114612f3457600080fd5b600080600060608486031215613f0457600080fd5b613f0d84613ed8565b925060208401519150604084015190509250925092565b805163ffffffff81168114612f3457600080fd5b600080600060608486031215613f4d57600080fd5b613f5684613ed8565b9250613f6460208501613f24565b9150613f7260408501613f24565b90509250925092565b600060208284031215613f8d57600080fd5b612c6b82613ed8565b8181038181111561062057610620613b95565b602081526000612c6b602083018461310b56fea264697066735822122096dca9ef030f65331631c7305d4d9405c1d0b56d48eb3787508d19369d85297764736f6c63430008190033", "devdoc": { "author": "Venus", "kind": "dev", @@ -1198,6 +1216,7 @@ "custom:oz-upgrades-unsafe-allow": "constructor", "params": { "blocksPerYear_": "The number of blocks per year", + "corePoolComptroller_": "The address of the core pool comptroller", "timeBased_": "A boolean indicating whether the contract is based on time or block." } }, @@ -1342,6 +1361,9 @@ "blocksOrSecondsPerYear()": { "notice": "Stores blocksPerYear if isTimeBased is true else secondsPerYear is stored" }, + "corePoolComptroller()": { + "notice": "Address of the core pool comptroller (all markets are returned for this pool, including paused ones)" + }, "getAllPools(address)": { "notice": "Queries all pools with addtional details for each of them" }, @@ -1391,7 +1413,7 @@ "storageLayout": { "storage": [ { - "astId": 1830, + "astId": 1737, "contract": "contracts/Lens/PoolLens.sol:PoolLens", "label": "__gap", "offset": 0, diff --git a/deployments/ethereum/solcInputs/09f8b2889a382752688c03578bc27f8d.json b/deployments/ethereum/solcInputs/09f8b2889a382752688c03578bc27f8d.json new file mode 100644 index 000000000..b2e4f0f5c --- /dev/null +++ b/deployments/ethereum/solcInputs/09f8b2889a382752688c03578bc27f8d.json @@ -0,0 +1,139 @@ +{ + "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/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/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/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/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" + }, + "@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/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/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\ninterface IProtocolShareReserve {\n /// @notice it represents the type of vToken income\n enum IncomeType {\n SPREAD,\n LIQUIDATION,\n ERC4626_WRAPPER_REWARDS,\n FLASHLOAN\n }\n\n function updateAssetsState(\n address comptroller,\n address asset,\n IncomeType incomeType\n ) external;\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/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/venus-protocol/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" + }, + "@venusprotocol/venus-protocol/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/Comptroller.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { IPrime } from \"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\";\n\nimport { ComptrollerInterface, Action } from \"./ComptrollerInterface.sol\";\nimport { ComptrollerStorage } from \"./ComptrollerStorage.sol\";\nimport { ExponentialNoError } from \"./ExponentialNoError.sol\";\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.sol\";\nimport { MaxLoopsLimitHelper } from \"./MaxLoopsLimitHelper.sol\";\nimport { ensureNonzeroAddress } from \"./lib/validators.sol\";\n\n/**\n * @title Comptroller\n * @author Venus\n * @notice The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating,\n * and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts\n * with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows\n * or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing\n * liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow,\n * as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the\n * markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market’s corresponding liquidation threshold,\n * the borrow is eligible for liquidation.\n *\n * The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed\n * the `minLiquidatableCollateral` for the `Comptroller`:\n *\n * - `healAccount()`: This function is called to seize all of a given user’s collateral, requiring the `msg.sender` repay a certain percentage\n * of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed\n * 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt\n * and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool.\n * - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation\n * incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic\n * verifying that the repay amount does not exceed the close factor.\n */\ncontract Comptroller is\n Ownable2StepUpgradeable,\n AccessControlledV8,\n ComptrollerStorage,\n ComptrollerInterface,\n ExponentialNoError,\n MaxLoopsLimitHelper\n{\n // PoolRegistry, immutable to save on gas\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable poolRegistry;\n\n /// @notice Emitted when an account enters a market\n event MarketEntered(VToken indexed vToken, address indexed account);\n\n /// @notice Emitted when an account exits a market\n event MarketExited(VToken indexed vToken, address indexed account);\n\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(VToken vToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa);\n\n /// @notice Emitted when liquidation threshold is changed by admin\n event NewLiquidationThreshold(\n VToken vToken,\n uint256 oldLiquidationThresholdMantissa,\n uint256 newLiquidationThresholdMantissa\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 an action is paused on a market\n event ActionPausedMarket(VToken vToken, Action action, bool pauseState);\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 the collateral threshold (in USD) for non-batch liquidations is changed\n event NewMinLiquidatableCollateral(uint256 oldMinLiquidatableCollateral, uint256 newMinLiquidatableCollateral);\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 a rewards distributor is added\n event NewRewardsDistributor(address indexed rewardsDistributor, address indexed rewardToken);\n\n /// @notice Emitted when a market is supported\n event MarketSupported(VToken vToken);\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 a market\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\n\n /// @notice Emitted when a market is unlisted\n event MarketUnlisted(address indexed vToken);\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 Thrown when collateral factor exceeds the upper bound\n error InvalidCollateralFactor();\n\n /// @notice Thrown when liquidation threshold exceeds the collateral factor\n error InvalidLiquidationThreshold();\n\n /// @notice Thrown when the action is only available to specific sender, but the real sender was different\n error UnexpectedSender(address expectedSender, address actualSender);\n\n /// @notice Thrown when the oracle returns an invalid price for some asset\n error PriceError(address vToken);\n\n /// @notice Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\n error SnapshotError(address vToken, address user);\n\n /// @notice Thrown when the market is not listed\n error MarketNotListed(address market);\n\n /// @notice Thrown when a market has an unexpected comptroller\n error ComptrollerMismatch();\n\n /// @notice Thrown when user is not member of market\n error MarketNotCollateral(address vToken, address user);\n\n /// @notice Thrown when borrow action is not paused\n error BorrowActionNotPaused();\n\n /// @notice Thrown when mint action is not paused\n error MintActionNotPaused();\n\n /// @notice Thrown when redeem action is not paused\n error RedeemActionNotPaused();\n\n /// @notice Thrown when repay action is not paused\n error RepayActionNotPaused();\n\n /// @notice Thrown when seize action is not paused\n error SeizeActionNotPaused();\n\n /// @notice Thrown when exit market action is not paused\n error ExitMarketActionNotPaused();\n\n /// @notice Thrown when transfer action is not paused\n error TransferActionNotPaused();\n\n /// @notice Thrown when enter market action is not paused\n error EnterMarketActionNotPaused();\n\n /// @notice Thrown when liquidate action is not paused\n error LiquidateActionNotPaused();\n\n /// @notice Thrown when borrow cap is not zero\n error BorrowCapIsNotZero();\n\n /// @notice Thrown when supply cap is not zero\n error SupplyCapIsNotZero();\n\n /// @notice Thrown when collateral factor is not zero\n error CollateralFactorIsNotZero();\n\n /**\n * @notice Thrown during the liquidation if user's total collateral amount is lower than\n * a predefined threshold. In this case only batch liquidations (either liquidateAccount\n * or healAccount) are available.\n */\n error MinimalCollateralViolated(uint256 expectedGreaterThan, uint256 actual);\n error CollateralExceedsThreshold(uint256 expectedLessThanOrEqualTo, uint256 actual);\n error InsufficientCollateral(uint256 collateralToSeize, uint256 availableCollateral);\n\n /// @notice Thrown when the account doesn't have enough liquidity to redeem or borrow\n error InsufficientLiquidity();\n\n /// @notice Thrown when trying to liquidate a healthy account\n error InsufficientShortfall();\n\n /// @notice Thrown when trying to repay more than allowed by close factor\n error TooMuchRepay();\n\n /// @notice Thrown if the user is trying to exit a market in which they have an outstanding debt\n error NonzeroBorrowBalance();\n\n /// @notice Thrown when trying to perform an action that is paused\n error ActionPaused(address market, Action action);\n\n /// @notice Thrown when trying to add a market that is already listed\n error MarketAlreadyListed(address market);\n\n /// @notice Thrown if the supply cap is exceeded\n error SupplyCapExceeded(address market, uint256 cap);\n\n /// @notice Thrown if the borrow cap is exceeded\n error BorrowCapExceeded(address market, uint256 cap);\n\n /// @notice Thrown if delegate approval status is already set to the requested value\n error DelegationStatusUnchanged();\n\n /// @param poolRegistry_ Pool registry address\n /// @custom:oz-upgrades-unsafe-allow constructor\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n constructor(address poolRegistry_) {\n ensureNonzeroAddress(poolRegistry_);\n\n poolRegistry = poolRegistry_;\n _disableInitializers();\n }\n\n /**\n * @param loopLimit Limit for the loops can iterate to avoid the DOS\n * @param accessControlManager Access control manager contract address\n */\n function initialize(uint256 loopLimit, address accessControlManager) external initializer {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager);\n\n _setMaxLoopsLimit(loopLimit);\n }\n\n /**\n * @notice Add assets to be included in account liquidity calculation; enabling them to be used as collateral\n * @param vTokens The list of addresses of the vToken markets to be enabled\n * @return errors An array of NO_ERROR for compatibility with Venus core tooling\n * @custom:event MarketEntered is emitted for each market on success\n * @custom:error ActionPaused error is thrown if entering any of the markets is paused\n * @custom:error MarketNotListed error is thrown if any of the markets is not listed\n * @custom:access Not restricted\n */\n function enterMarkets(address[] memory vTokens) external override returns (uint256[] memory) {\n uint256 len = vTokens.length;\n\n uint256[] memory results = new uint256[](len);\n for (uint256 i; i < len; ++i) {\n VToken vToken = VToken(vTokens[i]);\n\n _addToMarket(vToken, msg.sender);\n results[i] = NO_ERROR;\n }\n\n return results;\n }\n\n /**\n * @notice Unlist a market by setting isListed to false\n * @dev Checks if all actions are paused, borrow/supply caps is set to 0 and collateral factor is to 0.\n * @param market The address of the market (token) to unlist\n * @return uint256 Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event MarketUnlisted is emitted on success\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error BorrowActionNotPaused error is thrown if borrow action is not paused\n * @custom:error MintActionNotPaused error is thrown if mint action is not paused\n * @custom:error RedeemActionNotPaused error is thrown if redeem action is not paused\n * @custom:error RepayActionNotPaused error is thrown if repay action is not paused\n * @custom:error EnterMarketActionNotPaused error is thrown if enter market action is not paused\n * @custom:error LiquidateActionNotPaused error is thrown if liquidate action is not paused\n * @custom:error BorrowCapIsNotZero error is thrown if borrow cap is not zero\n * @custom:error SupplyCapIsNotZero error is thrown if supply cap is not zero\n * @custom:error CollateralFactorIsNotZero error is thrown if collateral factor is not zero\n */\n function unlistMarket(address market) external returns (uint256) {\n _checkAccessAllowed(\"unlistMarket(address)\");\n\n Market storage _market = markets[market];\n\n if (!_market.isListed) {\n revert MarketNotListed(market);\n }\n\n if (!actionPaused(market, Action.BORROW)) {\n revert BorrowActionNotPaused();\n }\n\n if (!actionPaused(market, Action.MINT)) {\n revert MintActionNotPaused();\n }\n\n if (!actionPaused(market, Action.REDEEM)) {\n revert RedeemActionNotPaused();\n }\n\n if (!actionPaused(market, Action.REPAY)) {\n revert RepayActionNotPaused();\n }\n\n if (!actionPaused(market, Action.SEIZE)) {\n revert SeizeActionNotPaused();\n }\n\n if (!actionPaused(market, Action.ENTER_MARKET)) {\n revert EnterMarketActionNotPaused();\n }\n\n if (!actionPaused(market, Action.LIQUIDATE)) {\n revert LiquidateActionNotPaused();\n }\n\n if (!actionPaused(market, Action.TRANSFER)) {\n revert TransferActionNotPaused();\n }\n\n if (!actionPaused(market, Action.EXIT_MARKET)) {\n revert ExitMarketActionNotPaused();\n }\n\n if (borrowCaps[market] != 0) {\n revert BorrowCapIsNotZero();\n }\n\n if (supplyCaps[market] != 0) {\n revert SupplyCapIsNotZero();\n }\n\n if (_market.collateralFactorMantissa != 0) {\n revert CollateralFactorIsNotZero();\n }\n\n _market.isListed = false;\n emit MarketUnlisted(market);\n\n return NO_ERROR;\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 * @custom:event DelegateUpdated emits on success\n * @custom:error ZeroAddressNotAllowed is thrown when delegate address is zero\n * @custom:error DelegationStatusUnchanged is thrown if approval status is already set to the requested value\n * @custom:access Not restricted\n */\n function updateDelegate(address delegate, bool approved) external {\n ensureNonzeroAddress(delegate);\n if (approvedDelegates[msg.sender][delegate] == approved) {\n revert DelegationStatusUnchanged();\n }\n\n approvedDelegates[msg.sender][delegate] = approved;\n emit DelegateUpdated(msg.sender, delegate, approved);\n }\n\n /**\n * @notice Removes asset from sender's account liquidity calculation; disabling them as collateral\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event MarketExited is emitted on success\n * @custom:error ActionPaused error is thrown if exiting the market is paused\n * @custom:error NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function exitMarket(address vTokenAddress) external override returns (uint256) {\n _checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\n VToken vToken = VToken(vTokenAddress);\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\n (uint256 tokensHeld, uint256 amountOwed, ) = _safeGetAccountSnapshot(vToken, msg.sender);\n\n /* Fail if the sender has a borrow balance */\n if (amountOwed != 0) {\n revert NonzeroBorrowBalance();\n }\n\n /* Fail if the sender is not permitted to redeem all of their tokens */\n _checkRedeemAllowed(vTokenAddress, msg.sender, tokensHeld);\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 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 // load into memory for faster iteration\n VToken[] memory userAssetList = accountAssets[msg.sender];\n uint256 len = userAssetList.length;\n\n uint256 assetIndex = len;\n for (uint256 i; i < len; ++i) {\n if (userAssetList[i] == vToken) {\n assetIndex = i;\n break;\n }\n }\n\n // We *must* have found the asset in the list or our redundant data structure is broken\n assert(assetIndex < len);\n\n // copy last item in list to location of item to be removed, reduce length by 1\n VToken[] storage storedList = accountAssets[msg.sender];\n storedList[assetIndex] = storedList[storedList.length - 1];\n storedList.pop();\n\n emit MarketExited(vToken, msg.sender);\n\n return NO_ERROR;\n }\n\n /*** Policy Hooks ***/\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 * @custom:error ActionPaused error is thrown if supplying to this market is paused\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\n * @custom:access Not restricted\n */\n function preMintHook(address vToken, address minter, uint256 mintAmount) external override {\n _checkActionPauseState(vToken, Action.MINT);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n uint256 supplyCap = supplyCaps[vToken];\n // Skipping the cap check for uncapped coins to save some gas\n if (supplyCap != type(uint256).max) {\n uint256 vTokenSupply = VToken(vToken).totalSupply();\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\n if (nextTotalSupply > supplyCap) {\n revert SupplyCapExceeded(vToken, supplyCap);\n }\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, minter);\n }\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external override {\n _checkActionPauseState(vToken, Action.REDEEM);\n\n _checkRedeemAllowed(vToken, redeemer, redeemTokens);\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, redeemer);\n }\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 if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(redeemer, vToken);\n }\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 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 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 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 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 * @custom:error ActionPaused error is thrown if borrowing is paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if there is not enough collateral to borrow\n * @custom:error BorrowCapExceeded is thrown if the borrow cap will be exceeded should this borrow succeed\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted if vToken is enabled as collateral, otherwise only vToken\n */\n /// disable-eslint\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external override {\n _checkActionPauseState(vToken, Action.BORROW);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n if (!markets[vToken].accountMembership[borrower]) {\n // only vTokens may call borrowAllowed if borrower not in market\n _checkSenderIs(vToken);\n\n // attempt to add borrower to the market or revert\n _addToMarket(VToken(msg.sender), borrower);\n }\n\n // Update the prices of tokens\n updatePrices(borrower);\n\n if (oracle.getUnderlyingPrice(vToken) == 0) {\n revert PriceError(address(vToken));\n }\n\n uint256 borrowCap = borrowCaps[vToken];\n // Skipping the cap check for uncapped coins to save some gas\n if (borrowCap != type(uint256).max) {\n uint256 totalBorrows = VToken(vToken).totalBorrows();\n uint256 badDebt = VToken(vToken).badDebt();\n uint256 nextTotalBorrows = totalBorrows + borrowAmount + badDebt;\n if (nextTotalBorrows > borrowCap) {\n revert BorrowCapExceeded(vToken, borrowCap);\n }\n }\n\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n borrower,\n VToken(vToken),\n 0,\n borrowAmount,\n _getCollateralFactor\n );\n\n if (snapshot.shortfall > 0) {\n revert InsufficientLiquidity();\n }\n\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\n }\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 borrower The account which would borrowed the asset\n * @custom:error ActionPaused error is thrown if repayments are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:access Not restricted\n */\n function preRepayHook(address vToken, address borrower) external override {\n _checkActionPauseState(vToken, Action.REPAY);\n\n oracle.updatePrice(vToken);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\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 borrower The address of the borrower\n * @param repayAmount The amount of underlying being repaid\n * @param skipLiquidityCheck Allows the borrow to be liquidated regardless of the account liquidity\n * @custom:error ActionPaused error is thrown if liquidations are paused in this market\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\n * @custom:error TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor\n * @custom:error MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations\n * @custom:error InsufficientShortfall is thrown when trying to liquidate a healthy account\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n */\n function preLiquidateHook(\n address vTokenBorrowed,\n address vTokenCollateral,\n address borrower,\n uint256 repayAmount,\n bool skipLiquidityCheck\n ) external override {\n // Pause Action.LIQUIDATE on BORROWED TOKEN to prevent liquidating it.\n // If we want to pause liquidating to vTokenCollateral, we should pause\n // Action.SEIZE on it\n _checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\n\n // Update the prices of tokens\n updatePrices(borrower);\n\n if (!markets[vTokenBorrowed].isListed) {\n revert MarketNotListed(address(vTokenBorrowed));\n }\n if (!markets[vTokenCollateral].isListed) {\n revert MarketNotListed(address(vTokenCollateral));\n }\n\n uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\n\n /* Allow accounts to be liquidated if it is a forced liquidation */\n if (skipLiquidityCheck || isForcedLiquidationEnabled[vTokenBorrowed]) {\n if (repayAmount > borrowBalance) {\n revert TooMuchRepay();\n }\n return;\n }\n\n /* The borrower must have shortfall and collateral > threshold in order to be liquidatable */\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral <= minLiquidatableCollateral) {\n /* The liquidator should use either liquidateAccount or healAccount */\n revert MinimalCollateralViolated(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n /* The liquidator may not repay more than what is allowed by the closeFactor */\n uint256 maxClose = mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance);\n if (repayAmount > maxClose) {\n revert TooMuchRepay();\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 seizerContract Contract that tries to seize the asset (either borrowed vToken or Comptroller)\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @custom:error ActionPaused error is thrown if seizing this type of collateral is paused\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\n * @custom:error ComptrollerMismatch error is when seizer contract or seized asset belong to different pools\n * @custom:access Not restricted\n */\n function preSeizeHook(\n address vTokenCollateral,\n address seizerContract,\n address liquidator,\n address borrower\n ) external override {\n // Pause Action.SEIZE on COLLATERAL to prevent seizing it.\n // If we want to pause liquidating vTokenBorrowed, we should pause\n // Action.LIQUIDATE on it\n _checkActionPauseState(vTokenCollateral, Action.SEIZE);\n\n Market storage market = markets[vTokenCollateral];\n\n if (!market.isListed) {\n revert MarketNotListed(vTokenCollateral);\n }\n\n if (seizerContract == address(this)) {\n // If Comptroller is the seizer, just check if collateral's comptroller\n // is equal to the current address\n if (address(VToken(vTokenCollateral).comptroller()) != address(this)) {\n revert ComptrollerMismatch();\n }\n } else {\n // If the seizer is not the Comptroller, check that the seizer is a\n // listed market, and that the markets' comptrollers match\n if (!markets[seizerContract].isListed) {\n revert MarketNotListed(seizerContract);\n }\n if (VToken(vTokenCollateral).comptroller() != VToken(seizerContract).comptroller()) {\n revert ComptrollerMismatch();\n }\n }\n\n if (!market.accountMembership[borrower]) {\n revert MarketNotCollateral(vTokenCollateral, borrower);\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vTokenCollateral);\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, borrower);\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, liquidator);\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external override {\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 _checkRedeemAllowed(vToken, src, transferTokens);\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, src);\n rewardsDistributor.distributeSupplierRewardToken(vToken, dst);\n }\n }\n\n /*** Pool-level operations ***/\n\n /**\n * @notice Seizes all the remaining collateral, makes msg.sender repay the existing\n * borrows, and treats the rest of the debt as bad debt (for each market).\n * The sender has to repay a certain percentage of the debt, computed as\n * collateral / (borrows * liquidationIncentive).\n * @param user account to heal\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for healing\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function healAccount(address user) external {\n VToken[] memory userAssets = getAssetsIn(user);\n uint256 userAssetsCount = userAssets.length;\n\n address liquidator = msg.sender;\n {\n ResilientOracleInterface oracle_ = oracle;\n // We need all user's markets to be fresh for the computations to be correct\n for (uint256 i; i < userAssetsCount; ++i) {\n userAssets[i].accrueInterest();\n oracle_.updatePrice(address(userAssets[i]));\n }\n }\n\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(user, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n // percentage = collateral / (borrows * liquidation incentive)\n Exp memory collateral = Exp({ mantissa: snapshot.totalCollateral });\n Exp memory scaledBorrows = mul_(\n Exp({ mantissa: snapshot.borrows }),\n Exp({ mantissa: liquidationIncentiveMantissa })\n );\n\n Exp memory percentage = div_(collateral, scaledBorrows);\n if (lessThanExp(Exp({ mantissa: MANTISSA_ONE }), percentage)) {\n revert CollateralExceedsThreshold(scaledBorrows.mantissa, collateral.mantissa);\n }\n\n for (uint256 i; i < userAssetsCount; ++i) {\n VToken market = userAssets[i];\n\n (uint256 tokens, uint256 borrowBalance, ) = _safeGetAccountSnapshot(market, user);\n uint256 repaymentAmount = mul_ScalarTruncate(percentage, borrowBalance);\n\n // Seize the entire collateral\n if (tokens != 0) {\n market.seize(liquidator, user, tokens);\n }\n // Repay a certain percentage of the borrow, forgive the rest\n if (borrowBalance != 0) {\n market.healBorrow(liquidator, user, repaymentAmount);\n }\n }\n }\n\n /**\n * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than\n * a predefined threshold, and the account collateral can be seized to cover all borrows. If\n * the collateral is higher than the threshold, use regular liquidations. If the collateral is\n * below the threshold, and the account is insolvent, use healAccount.\n * @param borrower the borrower address\n * @param orders an array of liquidation orders\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation\n * @custom:error InsufficientCollateral error is thrown when there is not enough collateral to cover the debt\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function liquidateAccount(address borrower, LiquidationOrder[] calldata orders) external {\n // We will accrue interest and update the oracle prices later during the liquidation\n\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\n // You should use the regular vToken.liquidateBorrow(...) call\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n uint256 collateralToSeize = mul_ScalarTruncate(\n Exp({ mantissa: liquidationIncentiveMantissa }),\n snapshot.borrows\n );\n if (collateralToSeize >= snapshot.totalCollateral) {\n // There is not enough collateral to seize. Use healBorrow to repay some part of the borrow\n // and record bad debt.\n revert InsufficientCollateral(collateralToSeize, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n uint256 ordersCount = orders.length;\n\n _ensureMaxLoops(ordersCount / 2);\n\n for (uint256 i; i < ordersCount; ++i) {\n if (!markets[address(orders[i].vTokenBorrowed)].isListed) {\n revert MarketNotListed(address(orders[i].vTokenBorrowed));\n }\n if (!markets[address(orders[i].vTokenCollateral)].isListed) {\n revert MarketNotListed(address(orders[i].vTokenCollateral));\n }\n\n LiquidationOrder calldata order = orders[i];\n order.vTokenBorrowed.forceLiquidateBorrow(\n msg.sender,\n borrower,\n order.repayAmount,\n order.vTokenCollateral,\n true\n );\n }\n\n VToken[] memory borrowMarkets = getAssetsIn(borrower);\n uint256 marketsCount = borrowMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower);\n require(borrowBalance == 0, \"Nonzero borrow balance after liquidation\");\n }\n }\n\n /**\n * @notice Sets the closeFactor to use when liquidating borrows\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\n * @custom:event Emits NewCloseFactor on success\n * @custom:access Controlled by AccessControlManager\n */\n function setCloseFactor(uint256 newCloseFactorMantissa) external {\n _checkAccessAllowed(\"setCloseFactor(uint256)\");\n require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, \"Close factor greater than maximum close factor\");\n require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, \"Close factor smaller than minimum close factor\");\n\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\n closeFactorMantissa = newCloseFactorMantissa;\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\n }\n\n /**\n * @notice Sets the collateralFactor for a market\n * @dev This function is restricted by the AccessControlManager\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 * @custom:event Emits NewCollateralFactor when collateral factor is updated\n * and NewLiquidationThreshold when liquidation threshold is updated\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InvalidCollateralFactor error is thrown when collateral factor is too high\n * @custom:error InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor\n * @custom:error PriceError is thrown when the oracle returns an invalid price for the asset\n * @custom:access Controlled by AccessControlManager\n */\n function setCollateralFactor(\n VToken vToken,\n uint256 newCollateralFactorMantissa,\n uint256 newLiquidationThresholdMantissa\n ) external {\n _checkAccessAllowed(\"setCollateralFactor(address,uint256,uint256)\");\n\n // Verify market is listed\n Market storage market = markets[address(vToken)];\n if (!market.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n // Check collateral factor <= 0.9\n if (newCollateralFactorMantissa > MAX_COLLATERAL_FACTOR_MANTISSA) {\n revert InvalidCollateralFactor();\n }\n\n // Ensure that liquidation threshold <= 1\n if (newLiquidationThresholdMantissa > MANTISSA_ONE) {\n revert InvalidLiquidationThreshold();\n }\n\n // Ensure that liquidation threshold >= CF\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\n revert InvalidLiquidationThreshold();\n }\n\n // If collateral factor != 0, fail if price == 0\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\n revert PriceError(address(vToken));\n }\n\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\n market.collateralFactorMantissa = newCollateralFactorMantissa;\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\n }\n\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\n emit NewLiquidationThreshold(vToken, oldLiquidationThresholdMantissa, newLiquidationThresholdMantissa);\n }\n }\n\n /**\n * @notice Sets liquidationIncentive\n * @dev This function is restricted by the AccessControlManager\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\n * @custom:event Emits NewLiquidationIncentive on success\n * @custom:access Controlled by AccessControlManager\n */\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external {\n require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, \"liquidation incentive should be greater than 1e18\");\n\n _checkAccessAllowed(\"setLiquidationIncentive(uint256)\");\n\n // Save current value for use in log\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\n\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\n /**\n * @notice Add the market to the markets mapping and set it as listed\n * @dev Only callable by the PoolRegistry\n * @param vToken The address of the market (token) to list\n * @custom:error MarketAlreadyListed is thrown if the market is already listed in this pool\n * @custom:access Only PoolRegistry\n */\n function supportMarket(VToken vToken) external {\n _checkSenderIs(poolRegistry);\n\n if (markets[address(vToken)].isListed) {\n revert MarketAlreadyListed(address(vToken));\n }\n\n require(vToken.isVToken(), \"Comptroller: Invalid vToken\"); // Sanity check to make sure its really a VToken\n\n Market storage newMarket = markets[address(vToken)];\n newMarket.isListed = true;\n newMarket.collateralFactorMantissa = 0;\n newMarket.liquidationThresholdMantissa = 0;\n\n _addMarket(address(vToken));\n\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n rewardsDistributors[i].initializeMarket(address(vToken));\n }\n\n emit MarketSupported(vToken);\n }\n\n /**\n * @notice Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\n * @dev This function is restricted by the AccessControlManager\n * @dev A borrow cap of type(uint256).max corresponds to unlimited borrowing.\n * @dev Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed\n until the total borrows amount goes below the new borrow cap\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 type(uint256).max corresponds to unlimited borrowing.\n * @custom:access Controlled by AccessControlManager\n */\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\n _checkAccessAllowed(\"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 _ensureMaxLoops(numMarkets);\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 * @notice Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\n * @dev This function is restricted by the AccessControlManager\n * @dev A supply cap of type(uint256).max corresponds to unlimited supply.\n * @dev Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed\n until the total supplies amount goes below the new supply cap\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 type(uint256).max corresponds to unlimited supply.\n * @custom:access Controlled by AccessControlManager\n */\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\n _checkAccessAllowed(\"setMarketSupplyCaps(address[],uint256[])\");\n uint256 vTokensCount = vTokens.length;\n\n require(vTokensCount != 0, \"invalid number of markets\");\n require(vTokensCount == newSupplyCaps.length, \"invalid number of markets\");\n\n _ensureMaxLoops(vTokensCount);\n\n for (uint256 i; i < vTokensCount; ++i) {\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\n }\n }\n\n /**\n * @notice Pause/unpause specified actions\n * @dev This function is restricted by the AccessControlManager\n * @param marketsList Markets to pause/unpause the actions on\n * @param actionsList List of action ids to pause/unpause\n * @param paused The new paused state (true=paused, false=unpaused)\n * @custom:access Controlled by AccessControlManager\n */\n function setActionsPaused(VToken[] calldata marketsList, Action[] calldata actionsList, bool paused) external {\n _checkAccessAllowed(\"setActionsPaused(address[],uint256[],bool)\");\n\n uint256 marketsCount = marketsList.length;\n uint256 actionsCount = actionsList.length;\n\n _ensureMaxLoops(marketsCount * actionsCount);\n\n for (uint256 marketIdx; marketIdx < marketsCount; ++marketIdx) {\n for (uint256 actionIdx; actionIdx < actionsCount; ++actionIdx) {\n _setActionPaused(address(marketsList[marketIdx]), actionsList[actionIdx], paused);\n }\n }\n }\n\n /**\n * @notice Set the given collateral threshold for non-batch liquidations. Regular liquidations\n * will fail if the collateral amount is less than this threshold. Liquidators should use batch\n * operations like liquidateAccount or healAccount.\n * @dev This function is restricted by the AccessControlManager\n * @param newMinLiquidatableCollateral The new min liquidatable collateral (in USD).\n * @custom:access Controlled by AccessControlManager\n */\n function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external {\n _checkAccessAllowed(\"setMinLiquidatableCollateral(uint256)\");\n\n uint256 oldMinLiquidatableCollateral = minLiquidatableCollateral;\n minLiquidatableCollateral = newMinLiquidatableCollateral;\n emit NewMinLiquidatableCollateral(oldMinLiquidatableCollateral, newMinLiquidatableCollateral);\n }\n\n /**\n * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor\n * contracts with the same rewardToken, and there could be overlaping among them considering the last reward slot (block or second)\n * @dev Only callable by the admin\n * @param _rewardsDistributor Address of the RewardDistributor contract to add\n * @custom:access Only Governance\n * @custom:event Emits NewRewardsDistributor with distributor address\n */\n function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner {\n require(!rewardsDistributorExists[address(_rewardsDistributor)], \"already exists\");\n\n uint256 rewardsDistributorsLen = rewardsDistributors.length;\n _ensureMaxLoops(rewardsDistributorsLen + 1);\n\n rewardsDistributors.push(_rewardsDistributor);\n rewardsDistributorExists[address(_rewardsDistributor)] = true;\n\n uint256 marketsCount = allMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n _rewardsDistributor.initializeMarket(address(allMarkets[i]));\n }\n\n emit NewRewardsDistributor(address(_rewardsDistributor), address(_rewardsDistributor.rewardToken()));\n }\n\n /**\n * @notice Sets a new price oracle for the Comptroller\n * @dev Only callable by the admin\n * @param newOracle Address of the new price oracle to set\n * @custom:event Emits NewPriceOracle on success\n * @custom:error ZeroAddressNotAllowed is thrown when the new oracle address is zero\n */\n function setPriceOracle(ResilientOracleInterface newOracle) external onlyOwner {\n ensureNonzeroAddress(address(newOracle));\n\n ResilientOracleInterface oldOracle = oracle;\n oracle = newOracle;\n emit NewPriceOracle(oldOracle, newOracle);\n }\n\n /**\n * @notice Set the for loop iteration limit to avoid DOS\n * @param limit Limit for the max loops can execute at a time\n */\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\n _setMaxLoopsLimit(limit);\n }\n\n /**\n * @notice Sets the prime token contract for the comptroller\n * @param _prime Address of the Prime contract\n */\n function setPrimeToken(IPrime _prime) external onlyOwner {\n ensureNonzeroAddress(address(_prime));\n\n emit NewPrimeToken(prime, _prime);\n prime = _prime;\n }\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 * @param vTokenBorrowed Borrowed vToken\n * @param enable Whether to enable forced liquidations\n */\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\n _checkAccessAllowed(\"setForcedLiquidation(address,bool)\");\n ensureNonzeroAddress(vTokenBorrowed);\n\n if (!markets[vTokenBorrowed].isListed) {\n revert MarketNotListed(vTokenBorrowed);\n }\n\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\n }\n\n /**\n * @notice Determine the current account liquidity with respect to liquidation threshold requirements\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\n * @param account The account get liquidity for\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Account liquidity in excess of liquidation threshold requirements,\n * @return shortfall Account shortfall below liquidation threshold requirements\n */\n function getAccountLiquidity(\n address account\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getLiquidationThreshold);\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\n }\n\n /**\n * @notice Determine the current account liquidity with respect to collateral requirements\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\n * @param account The account get liquidity for\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Account liquidity in excess of collateral requirements,\n * @return shortfall Account shortfall below collateral requirements\n */\n function getBorrowingPower(\n address account\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getCollateralFactor);\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\n }\n\n /**\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Hypothetical account liquidity in excess of collateral requirements,\n * @return shortfall 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 error, uint256 liquidity, uint256 shortfall) {\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n account,\n VToken(vTokenModify),\n redeemTokens,\n borrowAmount,\n _getCollateralFactor\n );\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\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 markets The list of market addresses\n */\n function getAllMarkets() external view override returns (VToken[] memory) {\n return allMarkets;\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 /*** Assets You Are In ***/\n\n /**\n * @notice Returns whether the given account is entered in a given market\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 market specified, 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 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 error Always NO_ERROR for compatibility with Venus core tooling\n * @return tokensToSeize Number of vTokenCollateral tokens to be seized in a liquidation\n * @custom:error PriceError if the oracle returns an invalid price\n */\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view override returns (uint256 error, uint256 tokensToSeize) {\n /* Read oracle prices for borrowed and collateral markets */\n uint256 priceBorrowedMantissa = _safeGetUnderlyingPrice(VToken(vTokenBorrowed));\n uint256 priceCollateralMantissa = _safeGetUnderlyingPrice(VToken(vTokenCollateral));\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 uint256 exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\n uint256 seizeTokens;\n Exp memory numerator;\n Exp memory denominator;\n Exp memory ratio;\n\n numerator = mul_(Exp({ mantissa: liquidationIncentiveMantissa }), Exp({ mantissa: priceBorrowedMantissa }));\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\n ratio = div_(numerator, denominator);\n\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\n\n return (NO_ERROR, seizeTokens);\n }\n\n /**\n * @notice Returns reward speed given a vToken\n * @param vToken The vToken to get the reward speeds for\n * @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors\n */\n function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {\n uint256 rewardsDistributorsLength = rewardsDistributors.length;\n rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);\n for (uint256 i; i < rewardsDistributorsLength; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n address rewardToken = address(rewardsDistributor.rewardToken());\n rewardSpeeds[i] = RewardSpeeds({\n rewardToken: rewardToken,\n supplySpeed: rewardsDistributor.rewardTokenSupplySpeeds(vToken),\n borrowSpeed: rewardsDistributor.rewardTokenBorrowSpeeds(vToken)\n });\n }\n return rewardSpeeds;\n }\n\n /**\n * @notice Return all reward distributors for this pool\n * @return Array of RewardDistributor addresses\n */\n function getRewardDistributors() external view returns (RewardsDistributor[] memory) {\n return rewardsDistributors;\n }\n\n /**\n * @notice A marker method that returns true for a valid Comptroller contract\n * @return Always true\n */\n function isComptroller() external pure override returns (bool) {\n return true;\n }\n\n /**\n * @notice Update the prices of all the tokens associated with the provided account\n * @param account Address of the account to get associated tokens with\n */\n function updatePrices(address account) public {\n VToken[] memory vTokens = getAssetsIn(account);\n uint256 vTokensCount = vTokens.length;\n\n ResilientOracleInterface oracle_ = oracle;\n\n for (uint256 i; i < vTokensCount; ++i) {\n oracle_.updatePrice(address(vTokens[i]));\n }\n }\n\n /**\n * @notice Checks if a certain action is paused on a market\n * @param market vToken address\n * @param action Action to check\n * @return paused True if the action is paused otherwise false\n */\n function actionPaused(address market, Action action) public view returns (bool) {\n return _actionPaused[market][action];\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 list with the assets the account has entered\n */\n function getAssetsIn(address account) public 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 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 */\n function _addToMarket(VToken vToken, address borrower) internal {\n _checkActionPauseState(address(vToken), Action.ENTER_MARKET);\n Market storage marketToJoin = markets[address(vToken)];\n\n if (!marketToJoin.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n if (marketToJoin.accountMembership[borrower]) {\n // already joined\n return;\n }\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\n /**\n * @notice Internal function to validate that a market hasn't already been added\n * and if it hasn't adds it\n * @param vToken The market to support\n */\n function _addMarket(address vToken) internal {\n uint256 marketsCount = allMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n if (allMarkets[i] == VToken(vToken)) {\n revert MarketAlreadyListed(vToken);\n }\n }\n allMarkets.push(VToken(vToken));\n marketsCount = allMarkets.length;\n _ensureMaxLoops(marketsCount);\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 _setActionPaused(address market, Action action, bool paused) internal {\n require(markets[market].isListed, \"cannot pause a market that is not listed\");\n _actionPaused[market][action] = paused;\n emit ActionPausedMarket(VToken(market), action, paused);\n }\n\n /**\n * @dev Internal function to check that vTokens can be safely redeemed for the underlying asset.\n * @param vToken Address of the vTokens to redeem\n * @param redeemer Account redeeming the tokens\n * @param redeemTokens The number of tokens to redeem\n */\n function _checkRedeemAllowed(address vToken, address redeemer, uint256 redeemTokens) internal {\n Market storage market = markets[vToken];\n\n if (!market.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\n if (!market.accountMembership[redeemer]) {\n return;\n }\n\n // Update the prices of tokens\n updatePrices(redeemer);\n\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n redeemer,\n VToken(vToken),\n redeemTokens,\n 0,\n _getCollateralFactor\n );\n if (snapshot.shortfall > 0) {\n revert InsufficientLiquidity();\n }\n }\n\n /**\n * @notice Get the total collateral, weighted collateral, borrow balance, liquidity, shortfall\n * @param account The account to get the snapshot for\n * @param weight The function to compute the weight of the collateral – either collateral factor or\n * liquidation threshold. Accepts the address of the vToken and returns the weight as Exp.\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\n * without calculating accumulated interest.\n * @return snapshot Account liquidity snapshot\n */\n function _getCurrentLiquiditySnapshot(\n address account,\n function(VToken) internal view returns (Exp memory) weight\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\n return _getHypotheticalLiquiditySnapshot(account, VToken(address(0)), 0, 0, weight);\n }\n\n /**\n * @notice Determine what the supply/borrow balances 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 weight The function to compute the weight of the collateral – either collateral factor or\n liquidation threshold. Accepts the address of the VToken and returns the weight\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\n * without calculating accumulated interest.\n * @return snapshot Account liquidity snapshot\n */\n function _getHypotheticalLiquiditySnapshot(\n address account,\n VToken vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount,\n function(VToken) internal view returns (Exp memory) weight\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\n // For each asset the account is in\n VToken[] memory assets = getAssetsIn(account);\n uint256 assetsCount = assets.length;\n\n for (uint256 i; i < assetsCount; ++i) {\n VToken asset = assets[i];\n\n // Read the balances and exchange rate from the vToken\n (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) = _safeGetAccountSnapshot(\n asset,\n account\n );\n\n // Get the normalized price of the asset\n Exp memory oraclePrice = Exp({ mantissa: _safeGetUnderlyingPrice(asset) });\n\n // Pre-compute conversion factors from vTokens -> usd\n Exp memory vTokenPrice = mul_(Exp({ mantissa: exchangeRateMantissa }), oraclePrice);\n Exp memory weightedVTokenPrice = mul_(weight(asset), vTokenPrice);\n\n // weightedCollateral += weightedVTokenPrice * vTokenBalance\n snapshot.weightedCollateral = mul_ScalarTruncateAddUInt(\n weightedVTokenPrice,\n vTokenBalance,\n snapshot.weightedCollateral\n );\n\n // totalCollateral += vTokenPrice * vTokenBalance\n snapshot.totalCollateral = mul_ScalarTruncateAddUInt(vTokenPrice, vTokenBalance, snapshot.totalCollateral);\n\n // borrows += oraclePrice * borrowBalance\n snapshot.borrows = mul_ScalarTruncateAddUInt(oraclePrice, borrowBalance, snapshot.borrows);\n\n // Calculate effects of interacting with vTokenModify\n if (asset == vTokenModify) {\n // redeem effect\n // effects += tokensToDenom * redeemTokens\n snapshot.effects = mul_ScalarTruncateAddUInt(weightedVTokenPrice, redeemTokens, snapshot.effects);\n\n // borrow effect\n // effects += oraclePrice * borrowAmount\n snapshot.effects = mul_ScalarTruncateAddUInt(oraclePrice, borrowAmount, snapshot.effects);\n }\n }\n\n uint256 borrowPlusEffects = snapshot.borrows + snapshot.effects;\n // These are safe, as the underflow condition is checked first\n unchecked {\n if (snapshot.weightedCollateral > borrowPlusEffects) {\n snapshot.liquidity = snapshot.weightedCollateral - borrowPlusEffects;\n snapshot.shortfall = 0;\n } else {\n snapshot.liquidity = 0;\n snapshot.shortfall = borrowPlusEffects - snapshot.weightedCollateral;\n }\n }\n\n return snapshot;\n }\n\n /**\n * @dev Retrieves price from oracle for an asset and checks it is nonzero\n * @param asset Address for asset to query price\n * @return Underlying price\n */\n function _safeGetUnderlyingPrice(VToken asset) internal view returns (uint256) {\n uint256 oraclePriceMantissa = oracle.getUnderlyingPrice(address(asset));\n if (oraclePriceMantissa == 0) {\n revert PriceError(address(asset));\n }\n return oraclePriceMantissa;\n }\n\n /**\n * @dev Return collateral factor for a market\n * @param asset Address for asset\n * @return Collateral factor as exponential\n */\n function _getCollateralFactor(VToken asset) internal view returns (Exp memory) {\n return Exp({ mantissa: markets[address(asset)].collateralFactorMantissa });\n }\n\n /**\n * @dev Retrieves liquidation threshold for a market as an exponential\n * @param asset Address for asset to liquidation threshold\n * @return Liquidation threshold as exponential\n */\n function _getLiquidationThreshold(VToken asset) internal view returns (Exp memory) {\n return Exp({ mantissa: markets[address(asset)].liquidationThresholdMantissa });\n }\n\n /**\n * @dev Returns supply and borrow balances of user in vToken, reverts on failure\n * @param vToken Market to query\n * @param user Account address\n * @return vTokenBalance Balance of vTokens, the same as vToken.balanceOf(user)\n * @return borrowBalance Borrowed amount, including the interest\n * @return exchangeRateMantissa Stored exchange rate\n */\n function _safeGetAccountSnapshot(\n VToken vToken,\n address user\n ) internal view returns (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) {\n uint256 err;\n (err, vTokenBalance, borrowBalance, exchangeRateMantissa) = vToken.getAccountSnapshot(user);\n if (err != 0) {\n revert SnapshotError(address(vToken), user);\n }\n return (vTokenBalance, borrowBalance, exchangeRateMantissa);\n }\n\n /// @notice Reverts if the call is not from expectedSender\n /// @param expectedSender Expected transaction sender\n function _checkSenderIs(address expectedSender) internal view {\n if (msg.sender != expectedSender) {\n revert UnexpectedSender(expectedSender, msg.sender);\n }\n }\n\n /// @notice Reverts if a certain action is paused on a market\n /// @param market Market to check\n /// @param action Action to check\n function _checkActionPauseState(address market, Action action) private view {\n if (actionPaused(market, action)) {\n revert ActionPaused(market, action);\n }\n }\n}\n" + }, + "contracts/ComptrollerInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.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\n/**\n * @title ComptrollerInterface\n * @author Venus\n * @notice Interface implemented by the `Comptroller` contract.\n */\ninterface ComptrollerInterface {\n /*** Assets You Are In ***/\n\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\n\n function exitMarket(address vToken) external returns (uint256);\n\n /*** Policy Hooks ***/\n\n function preMintHook(address vToken, address minter, uint256 mintAmount) external;\n\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external;\n\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external;\n\n function preRepayHook(address vToken, address borrower) external;\n\n function preLiquidateHook(\n address vTokenBorrowed,\n address vTokenCollateral,\n address borrower,\n uint256 repayAmount,\n bool skipLiquidityCheck\n ) external;\n\n function preSeizeHook(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower\n ) external;\n\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\n\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\n\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\n\n function repayBorrowVerify(\n address vToken,\n address payer,\n address borrower,\n uint repayAmount,\n uint borrowerIndex\n ) external;\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 seizeVerify(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint seizeTokens\n ) external;\n\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\n\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external;\n\n function isComptroller() external view returns (bool);\n\n /*** Liquidity/Liquidation Calculations ***/\n\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 repayAmount\n ) external view returns (uint256, uint256);\n\n function getAllMarkets() external view returns (VToken[] memory);\n\n function actionPaused(address market, Action action) external view returns (bool);\n}\n\n/**\n * @title ComptrollerViewInterface\n * @author Venus\n * @notice Interface implemented by the `Comptroller` contract, including only some util view functions.\n */\ninterface ComptrollerViewInterface {\n function markets(address) external view returns (bool, uint256);\n\n function oracle() external view returns (ResilientOracleInterface);\n\n function getAssetsIn(address) external view returns (VToken[] memory);\n\n function closeFactorMantissa() external view returns (uint256);\n\n function liquidationIncentiveMantissa() external view returns (uint256);\n\n function minLiquidatableCollateral() external view returns (uint256);\n\n function getRewardDistributors() external view returns (RewardsDistributor[] memory);\n\n function getAllMarkets() external view returns (VToken[] memory);\n\n function borrowCaps(address) external view returns (uint256);\n\n function supplyCaps(address) external view returns (uint256);\n\n function approvedDelegates(address user, address delegate) external view returns (bool);\n}\n" + }, + "contracts/ComptrollerStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.sol\";\nimport { IPrime } from \"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\";\nimport { Action } from \"./ComptrollerInterface.sol\";\n\n/**\n * @title ComptrollerStorage\n * @author Venus\n * @notice Storage layout for the `Comptroller` contract.\n */\ncontract ComptrollerStorage {\n struct LiquidationOrder {\n VToken vTokenCollateral;\n VToken vTokenBorrowed;\n uint256 repayAmount;\n }\n\n struct AccountLiquiditySnapshot {\n uint256 totalCollateral;\n uint256 weightedCollateral;\n uint256 borrows;\n uint256 effects;\n uint256 liquidity;\n uint256 shortfall;\n }\n\n struct RewardSpeeds {\n address rewardToken;\n uint256 supplySpeed;\n uint256 borrowSpeed;\n }\n\n struct Market {\n // Whether or not this market is listed\n bool isListed;\n // 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 uint256 collateralFactorMantissa;\n // 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 uint256 liquidationThresholdMantissa;\n // Per-market mapping of \"accounts in this asset\"\n mapping(address => bool) accountMembership;\n }\n\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 Per-account mapping of \"assets you are in\"\n */\n mapping(address => VToken[]) public accountAssets;\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 /// @notice A list of all markets\n VToken[] public allMarkets;\n\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\n mapping(address => uint256) public borrowCaps;\n\n /// @notice Minimal collateral required for regular (non-batch) liquidations\n uint256 public minLiquidatableCollateral;\n\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\n mapping(address => uint256) public supplyCaps;\n\n /// @notice True if a certain action is paused on a certain market\n mapping(address => mapping(Action => bool)) internal _actionPaused;\n\n // List of Reward Distributors added\n RewardsDistributor[] internal rewardsDistributors;\n\n // Used to check if rewards distributor is added\n mapping(address => bool) internal rewardsDistributorExists;\n\n /// @notice Flag indicating whether forced liquidation enabled for a market\n mapping(address => bool) public isForcedLiquidationEnabled;\n\n uint256 internal constant NO_ERROR = 0;\n\n // closeFactorMantissa must be strictly greater than this value\n uint256 internal constant MIN_CLOSE_FACTOR_MANTISSA = 0.05e18; // 0.05\n\n // closeFactorMantissa must not exceed this value\n uint256 internal constant MAX_CLOSE_FACTOR_MANTISSA = 0.9e18; // 0.9\n\n // No collateralFactorMantissa may exceed this value\n uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.95e18; // 0.95\n\n /// Prime token address\n IPrime public prime;\n\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 /**\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[47] private __gap;\n}\n" + }, + "contracts/ErrorReporter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n/**\n * @title TokenErrorReporter\n * @author Venus\n * @notice Errors that can be thrown by the `VToken` contract.\n */\ncontract TokenErrorReporter {\n uint256 public constant NO_ERROR = 0; // support legacy return codes\n\n error TransferNotAllowed();\n\n error MintFreshnessCheck();\n\n error RedeemFreshnessCheck();\n error RedeemTransferOutNotPossible();\n\n error BorrowFreshnessCheck();\n error BorrowCashNotAvailable();\n error DelegateNotApproved();\n\n error RepayBorrowFreshnessCheck();\n\n error HealBorrowUnauthorized();\n error ForceLiquidateBorrowUnauthorized();\n\n error LiquidateFreshnessCheck();\n error LiquidateCollateralFreshnessCheck();\n error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\n error LiquidateLiquidatorIsBorrower();\n error LiquidateCloseAmountIsZero();\n error LiquidateCloseAmountIsUintMax();\n\n error LiquidateSeizeLiquidatorIsBorrower();\n\n error ProtocolSeizeShareTooBig();\n\n error SetReserveFactorFreshCheck();\n error SetReserveFactorBoundsCheck();\n\n error AddReservesFactorFreshCheck(uint256 actualAddAmount);\n\n error ReduceReservesFreshCheck();\n error ReduceReservesCashNotAvailable();\n error ReduceReservesCashValidation();\n\n error SetInterestRateModelFreshCheck();\n}\n" + }, + "contracts/ExponentialNoError.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from \"./lib/constants.sol\";\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 struct Exp {\n uint256 mantissa;\n }\n\n struct Double {\n uint256 mantissa;\n }\n\n uint256 internal constant EXP_SCALE = EXP_SCALE_;\n uint256 internal constant DOUBLE_SCALE = 1e36;\n uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;\n uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;\n\n /**\n * @dev Truncates the given exp to a whole number value.\n * For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15\n */\n function truncate(Exp memory exp) internal pure returns (uint256) {\n // Note: We are not using careful math here as we're performing a division that cannot fail\n return exp.mantissa / EXP_SCALE;\n }\n\n /**\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\n */\n // solhint-disable-next-line func-name-mixedcase\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\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 // solhint-disable-next-line func-name-mixedcase\n function mul_ScalarTruncateAddUInt(Exp memory a, uint256 scalar, uint256 addend) internal pure returns (uint256) {\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 function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\n require(n <= type(uint224).max, errorMessage);\n return uint224(n);\n }\n\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\n require(n <= type(uint32).max, 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_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a + b;\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_(uint256 a, uint256 b) internal pure returns (uint256) {\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) / EXP_SCALE });\n }\n\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\n return Exp({ mantissa: mul_(a.mantissa, b) });\n }\n\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\n return mul_(a, b.mantissa) / EXP_SCALE;\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) / DOUBLE_SCALE });\n }\n\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: mul_(a.mantissa, b) });\n }\n\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\n return mul_(a, b.mantissa) / DOUBLE_SCALE;\n }\n\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a * b;\n }\n\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });\n }\n\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\n return Exp({ mantissa: div_(a.mantissa, b) });\n }\n\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\n return div_(mul_(a, EXP_SCALE), 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, DOUBLE_SCALE), b.mantissa) });\n }\n\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(a.mantissa, b) });\n }\n\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\n return div_(mul_(a, DOUBLE_SCALE), b.mantissa);\n }\n\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a / b;\n }\n\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });\n }\n}\n" + }, + "contracts/InterestRateModel.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n/**\n * @title Compound's InterestRateModel Interface\n * @author Compound\n */\nabstract contract InterestRateModel {\n /**\n * @notice Calculates the current borrow interest rate per slot (block or second)\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 amount of reserves the market has\n * @param badDebt The amount of badDebt in the market\n * @return The borrow rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\n */\n function getBorrowRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) external view virtual returns (uint256);\n\n /**\n * @notice Calculates the current supply interest rate per slot (block or second)\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 amount of reserves the market has\n * @param reserveFactorMantissa The current reserve factor the market has\n * @param badDebt The amount of badDebt in the market\n * @return The supply rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\n */\n function getSupplyRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 reserveFactorMantissa,\n uint256 badDebt\n ) external view virtual returns (uint256);\n\n /**\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\n * @return Always true\n */\n function isInterestRateModel() external pure virtual returns (bool) {\n return true;\n }\n}\n" + }, + "contracts/Lens/PoolLens.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IERC20Metadata } from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { ExponentialNoError } from \"../ExponentialNoError.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { Action, ComptrollerInterface, ComptrollerViewInterface } from \"../ComptrollerInterface.sol\";\nimport { PoolRegistryInterface } from \"../Pool/PoolRegistryInterface.sol\";\nimport { PoolRegistry } from \"../Pool/PoolRegistry.sol\";\nimport { RewardsDistributor } from \"../Rewards/RewardsDistributor.sol\";\nimport { TimeManagerV8 } from \"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\";\n\n/**\n * @title PoolLens\n * @author Venus\n * @notice The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information\n * for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be\n * looked up for specific pools and markets:\n- the vToken balance of a given user;\n- the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address;\n- the vToken address in a pool for a given asset;\n- a list of all pools that support an asset;\n- the underlying asset price of a vToken;\n- the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\n */\ncontract PoolLens is ExponentialNoError, TimeManagerV8 {\n /**\n * @dev Struct for PoolDetails.\n */\n struct PoolData {\n string name;\n address creator;\n address comptroller;\n uint256 blockPosted;\n uint256 timestampPosted;\n string category;\n string logoURL;\n string description;\n address priceOracle;\n uint256 closeFactor;\n uint256 liquidationIncentive;\n uint256 minLiquidatableCollateral;\n VTokenMetadata[] vTokens;\n }\n\n /**\n * @dev Struct for VToken.\n */\n struct VTokenMetadata {\n address vToken;\n uint256 exchangeRateCurrent;\n uint256 supplyRatePerBlockOrTimestamp;\n uint256 borrowRatePerBlockOrTimestamp;\n uint256 reserveFactorMantissa;\n uint256 supplyCaps;\n uint256 borrowCaps;\n uint256 totalBorrows;\n uint256 totalReserves;\n uint256 totalSupply;\n uint256 totalCash;\n bool isListed;\n uint256 collateralFactorMantissa;\n address underlyingAssetAddress;\n uint256 vTokenDecimals;\n uint256 underlyingDecimals;\n uint256 pausedActions;\n }\n\n /**\n * @dev Struct for VTokenBalance.\n */\n struct VTokenBalances {\n address vToken;\n uint256 balanceOf;\n uint256 borrowBalanceCurrent;\n uint256 balanceOfUnderlying;\n uint256 tokenBalance;\n uint256 tokenAllowance;\n }\n\n /**\n * @dev Struct for underlyingPrice of VToken.\n */\n struct VTokenUnderlyingPrice {\n address vToken;\n uint256 underlyingPrice;\n }\n\n /**\n * @dev Struct with pending reward info for a market.\n */\n struct PendingReward {\n address vTokenAddress;\n uint256 amount;\n }\n\n /**\n * @dev Struct with reward distribution totals for a single reward token and distributor.\n */\n struct RewardSummary {\n address distributorAddress;\n address rewardTokenAddress;\n uint256 totalRewards;\n PendingReward[] pendingRewards;\n }\n\n /**\n * @dev Struct used in RewardDistributor to save last updated market state.\n */\n struct RewardTokenState {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block number or timestamp the index was last updated at\n uint256 blockOrTimestamp;\n // The block number or timestamp at which to stop rewards\n uint256 lastRewardingBlockOrTimestamp;\n }\n\n /**\n * @dev Struct with bad debt of a market denominated\n */\n struct BadDebt {\n address vTokenAddress;\n uint256 badDebtUsd;\n }\n\n /**\n * @dev Struct with bad debt total denominated in usd for a pool and an array of BadDebt structs for each market\n */\n struct BadDebtSummary {\n address comptroller;\n uint256 totalBadDebtUsd;\n BadDebt[] badDebts;\n }\n\n /// @notice Address of the core pool comptroller (all markets are returned for this pool, including paused ones)\n address public immutable corePoolComptroller;\n\n /**\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\n * @param blocksPerYear_ The number of blocks per year\n * @param corePoolComptroller_ The address of the core pool comptroller\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor(\n bool timeBased_,\n uint256 blocksPerYear_,\n address corePoolComptroller_\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\n corePoolComptroller = corePoolComptroller_;\n }\n\n /**\n * @notice Queries the user's supply/borrow balances in vTokens\n * @param vTokens The list of vToken addresses\n * @param account The user Account\n * @return A list of structs containing balances data\n */\n function vTokenBalancesAll(VToken[] calldata vTokens, address account) external returns (VTokenBalances[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenBalances[] memory res = new VTokenBalances[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenBalances(vTokens[i], account);\n }\n return res;\n }\n\n /**\n * @notice Queries all pools with addtional details for each of them\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @return Arrays of all Venus pools' data\n */\n function getAllPools(address poolRegistryAddress) external view returns (PoolData[] memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n PoolRegistry.VenusPool[] memory venusPools = poolRegistryInterface.getAllPools();\n uint256 poolLength = venusPools.length;\n\n PoolData[] memory poolDataItems = new PoolData[](poolLength);\n\n for (uint256 i; i < poolLength; ++i) {\n PoolRegistry.VenusPool memory venusPool = venusPools[i];\n PoolData memory poolData = getPoolDataFromVenusPool(poolRegistryAddress, venusPool);\n poolDataItems[i] = poolData;\n }\n\n return poolDataItems;\n }\n\n /**\n * @notice Queries the details of a pool identified by Comptroller address\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param comptroller The Comptroller implementation address\n * @return PoolData structure containing the details of the pool\n */\n function getPoolByComptroller(\n address poolRegistryAddress,\n address comptroller\n ) external view returns (PoolData memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return getPoolDataFromVenusPool(poolRegistryAddress, poolRegistryInterface.getPoolByComptroller(comptroller));\n }\n\n /**\n * @notice Returns vToken holding the specified underlying asset in the specified pool\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param comptroller The pool comptroller\n * @param asset The underlyingAsset of VToken\n * @return Address of the vToken\n */\n function getVTokenForAsset(\n address poolRegistryAddress,\n address comptroller,\n address asset\n ) external view returns (address) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return poolRegistryInterface.getVTokenForAsset(comptroller, asset);\n }\n\n /**\n * @notice Returns all pools that support the specified underlying asset\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param asset The underlying asset of vToken\n * @return A list of Comptroller contracts\n */\n function getPoolsSupportedByAsset(\n address poolRegistryAddress,\n address asset\n ) external view returns (address[] memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return poolRegistryInterface.getPoolsSupportedByAsset(asset);\n }\n\n /**\n * @notice Returns the price data for the underlying assets of the specified vTokens\n * @param vTokens The list of vToken addresses\n * @return An array containing the price data for each asset\n */\n function vTokenUnderlyingPriceAll(\n VToken[] calldata vTokens\n ) external view returns (VTokenUnderlyingPrice[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenUnderlyingPrice[] memory res = new VTokenUnderlyingPrice[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenUnderlyingPrice(vTokens[i]);\n }\n return res;\n }\n\n /**\n * @notice Returns the pending rewards for a user for a given pool.\n * @param account The user account.\n * @param comptrollerAddress address\n * @return Pending rewards array\n */\n function getPendingRewards(\n address account,\n address comptrollerAddress\n ) external view returns (RewardSummary[] memory) {\n VToken[] memory markets = _getMarkets(ComptrollerInterface(comptrollerAddress));\n RewardsDistributor[] memory rewardsDistributors = ComptrollerViewInterface(comptrollerAddress)\n .getRewardDistributors();\n RewardSummary[] memory rewardSummary = new RewardSummary[](rewardsDistributors.length);\n for (uint256 i; i < rewardsDistributors.length; ++i) {\n RewardSummary memory reward;\n reward.distributorAddress = address(rewardsDistributors[i]);\n reward.rewardTokenAddress = address(rewardsDistributors[i].rewardToken());\n reward.totalRewards = rewardsDistributors[i].rewardTokenAccrued(account);\n reward.pendingRewards = _calculateNotDistributedAwards(account, markets, rewardsDistributors[i]);\n rewardSummary[i] = reward;\n }\n return rewardSummary;\n }\n\n /**\n * @notice Returns a summary of a pool's bad debt broken down by market\n *\n * @param comptrollerAddress Address of the comptroller\n *\n * @return badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and\n * a break down of bad debt by market\n */\n function getPoolBadDebt(address comptrollerAddress) external view returns (BadDebtSummary memory) {\n uint256 totalBadDebtUsd;\n\n // Get every listed market in the pool\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\n VToken[] memory markets = _getMarkets(ComptrollerInterface(comptrollerAddress));\n ResilientOracleInterface priceOracle = comptroller.oracle();\n\n BadDebt[] memory badDebts = new BadDebt[](markets.length);\n\n BadDebtSummary memory badDebtSummary;\n badDebtSummary.comptroller = comptrollerAddress;\n badDebtSummary.badDebts = badDebts;\n\n // // Calculate the bad debt is USD per market\n for (uint256 i; i < markets.length; ++i) {\n BadDebt memory badDebt;\n badDebt.vTokenAddress = address(markets[i]);\n badDebt.badDebtUsd =\n (VToken(address(markets[i])).badDebt() * priceOracle.getUnderlyingPrice(address(markets[i]))) /\n EXP_SCALE;\n badDebtSummary.badDebts[i] = badDebt;\n totalBadDebtUsd = totalBadDebtUsd + badDebt.badDebtUsd;\n }\n\n badDebtSummary.totalBadDebtUsd = totalBadDebtUsd;\n\n return badDebtSummary;\n }\n\n /**\n * @notice Queries the user's supply/borrow balances in the specified vToken\n * @param vToken vToken address\n * @param account The user Account\n * @return A struct containing the balances data\n */\n function vTokenBalances(VToken vToken, address account) public returns (VTokenBalances memory) {\n uint256 balanceOf = vToken.balanceOf(account);\n uint256 borrowBalanceCurrent = vToken.borrowBalanceCurrent(account);\n uint256 balanceOfUnderlying = vToken.balanceOfUnderlying(account);\n uint256 tokenBalance;\n uint256 tokenAllowance;\n\n IERC20 underlying = IERC20(vToken.underlying());\n tokenBalance = underlying.balanceOf(account);\n tokenAllowance = underlying.allowance(account, address(vToken));\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 Queries additional information for the pool\n * @param poolRegistryAddress Address of the PoolRegistry\n * @param venusPool The VenusPool Object from PoolRegistry\n * @return Enriched PoolData\n */\n function getPoolDataFromVenusPool(\n address poolRegistryAddress,\n PoolRegistry.VenusPool memory venusPool\n ) public view returns (PoolData memory) {\n // Get tokens in the Pool\n ComptrollerInterface comptrollerInstance = ComptrollerInterface(venusPool.comptroller);\n\n VToken[] memory vTokens = _getMarkets(comptrollerInstance);\n\n VTokenMetadata[] memory vTokenMetadataItems = vTokenMetadataAll(vTokens);\n\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n\n PoolRegistry.VenusPoolMetaData memory venusPoolMetaData = poolRegistryInterface.getVenusPoolMetadata(\n venusPool.comptroller\n );\n\n ComptrollerViewInterface comptrollerViewInstance = ComptrollerViewInterface(venusPool.comptroller);\n\n PoolData memory poolData = PoolData({\n name: venusPool.name,\n creator: venusPool.creator,\n comptroller: venusPool.comptroller,\n blockPosted: venusPool.blockPosted,\n timestampPosted: venusPool.timestampPosted,\n category: venusPoolMetaData.category,\n logoURL: venusPoolMetaData.logoURL,\n description: venusPoolMetaData.description,\n vTokens: vTokenMetadataItems,\n priceOracle: address(comptrollerViewInstance.oracle()),\n closeFactor: comptrollerViewInstance.closeFactorMantissa(),\n liquidationIncentive: comptrollerViewInstance.liquidationIncentiveMantissa(),\n minLiquidatableCollateral: comptrollerViewInstance.minLiquidatableCollateral()\n });\n\n return poolData;\n }\n\n /**\n * @notice Returns the metadata of VToken\n * @param vToken The address of vToken\n * @return VTokenMetadata struct\n */\n function vTokenMetadata(VToken vToken) public view returns (VTokenMetadata memory) {\n uint256 exchangeRateCurrent = vToken.exchangeRateStored();\n address comptrollerAddress = address(vToken.comptroller());\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\n (bool isListed, uint256 collateralFactorMantissa) = comptroller.markets(address(vToken));\n\n address underlyingAssetAddress = vToken.underlying();\n uint256 underlyingDecimals = IERC20Metadata(underlyingAssetAddress).decimals();\n\n uint256 pausedActions;\n for (uint8 i; i <= uint8(type(Action).max); ++i) {\n uint256 paused = ComptrollerInterface(comptrollerAddress).actionPaused(address(vToken), Action(i)) ? 1 : 0;\n pausedActions |= paused << i;\n }\n\n uint256 supplyRatePerBlock;\n\n if (vToken.totalSupply() > 0) {\n supplyRatePerBlock = vToken.supplyRatePerBlock();\n }\n\n return\n VTokenMetadata({\n vToken: address(vToken),\n exchangeRateCurrent: exchangeRateCurrent,\n supplyRatePerBlockOrTimestamp: supplyRatePerBlock,\n borrowRatePerBlockOrTimestamp: vToken.borrowRatePerBlock(),\n reserveFactorMantissa: vToken.reserveFactorMantissa(),\n supplyCaps: comptroller.supplyCaps(address(vToken)),\n borrowCaps: comptroller.borrowCaps(address(vToken)),\n totalBorrows: vToken.totalBorrows(),\n totalReserves: vToken.totalReserves(),\n totalSupply: vToken.totalSupply(),\n totalCash: vToken.getCash(),\n isListed: isListed,\n collateralFactorMantissa: collateralFactorMantissa,\n underlyingAssetAddress: underlyingAssetAddress,\n vTokenDecimals: vToken.decimals(),\n underlyingDecimals: underlyingDecimals,\n pausedActions: pausedActions\n });\n }\n\n /**\n * @notice Returns the metadata of all VTokens\n * @param vTokens The list of vToken addresses\n * @return An array of VTokenMetadata structs\n */\n function vTokenMetadataAll(VToken[] memory vTokens) public view returns (VTokenMetadata[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenMetadata[] memory res = new VTokenMetadata[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenMetadata(vTokens[i]);\n }\n return res;\n }\n\n /**\n * @notice Returns the price data for the underlying asset of the specified vToken\n * @param vToken vToken address\n * @return The price data for each asset\n */\n function vTokenUnderlyingPrice(VToken vToken) public view returns (VTokenUnderlyingPrice memory) {\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(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 Returns markets from a comptroller. For the core pool, all markets are returned.\n * For other pools, markets with zero internalCash are filtered.\n * @param comptroller The comptroller to query\n * @return An array of VToken addresses\n */\n function _getMarkets(ComptrollerInterface comptroller) internal view returns (VToken[] memory) {\n VToken[] memory allMarkets = comptroller.getAllMarkets();\n\n if (address(comptroller) == corePoolComptroller) {\n return allMarkets;\n }\n\n // Single-loop filter: pack active markets to the front of allMarkets\n uint256 count;\n uint256 len = allMarkets.length;\n for (uint256 i; i < len; ++i) {\n if (allMarkets[i].internalCash() > 0) {\n allMarkets[count] = allMarkets[i];\n ++count;\n }\n }\n\n // Trim the array to the active count\n assembly {\n mstore(allMarkets, count)\n }\n\n return allMarkets;\n }\n\n function _calculateNotDistributedAwards(\n address account,\n VToken[] memory markets,\n RewardsDistributor rewardsDistributor\n ) internal view returns (PendingReward[] memory) {\n PendingReward[] memory pendingRewards = new PendingReward[](markets.length);\n\n for (uint256 i; i < markets.length; ++i) {\n // Market borrow and supply state we will modify update in-memory, in order to not modify storage\n RewardTokenState memory borrowState;\n RewardTokenState memory supplyState;\n\n if (isTimeBased) {\n (\n borrowState.index,\n borrowState.blockOrTimestamp,\n borrowState.lastRewardingBlockOrTimestamp\n ) = rewardsDistributor.rewardTokenBorrowStateTimeBased(address(markets[i]));\n (\n supplyState.index,\n supplyState.blockOrTimestamp,\n supplyState.lastRewardingBlockOrTimestamp\n ) = rewardsDistributor.rewardTokenSupplyStateTimeBased(address(markets[i]));\n } else {\n (\n borrowState.index,\n borrowState.blockOrTimestamp,\n borrowState.lastRewardingBlockOrTimestamp\n ) = rewardsDistributor.rewardTokenBorrowState(address(markets[i]));\n (\n supplyState.index,\n supplyState.blockOrTimestamp,\n supplyState.lastRewardingBlockOrTimestamp\n ) = rewardsDistributor.rewardTokenSupplyState(address(markets[i]));\n }\n\n Exp memory marketBorrowIndex = Exp({ mantissa: markets[i].borrowIndex() });\n\n // Update market supply and borrow index in-memory\n updateMarketBorrowIndex(address(markets[i]), rewardsDistributor, borrowState, marketBorrowIndex);\n updateMarketSupplyIndex(address(markets[i]), rewardsDistributor, supplyState);\n\n // Calculate pending rewards\n uint256 borrowReward = calculateBorrowerReward(\n address(markets[i]),\n rewardsDistributor,\n account,\n borrowState,\n marketBorrowIndex\n );\n uint256 supplyReward = calculateSupplierReward(\n address(markets[i]),\n rewardsDistributor,\n account,\n supplyState\n );\n\n PendingReward memory pendingReward;\n pendingReward.vTokenAddress = address(markets[i]);\n pendingReward.amount = borrowReward + supplyReward;\n pendingRewards[i] = pendingReward;\n }\n return pendingRewards;\n }\n\n function updateMarketBorrowIndex(\n address vToken,\n RewardsDistributor rewardsDistributor,\n RewardTokenState memory borrowState,\n Exp memory marketBorrowIndex\n ) internal view {\n uint256 borrowSpeed = rewardsDistributor.rewardTokenBorrowSpeeds(vToken);\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n if (\n borrowState.lastRewardingBlockOrTimestamp > 0 &&\n blockNumberOrTimestamp > borrowState.lastRewardingBlockOrTimestamp\n ) {\n blockNumberOrTimestamp = borrowState.lastRewardingBlockOrTimestamp;\n }\n\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, borrowState.blockOrTimestamp);\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\n // Remove the total earned interest rate since the opening of the market from total borrows\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, borrowSpeed);\n Double memory ratio = borrowAmount > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\n } else if (deltaBlocksOrTimestamp > 0) {\n borrowState.blockOrTimestamp = blockNumberOrTimestamp;\n }\n }\n\n function updateMarketSupplyIndex(\n address vToken,\n RewardsDistributor rewardsDistributor,\n RewardTokenState memory supplyState\n ) internal view {\n uint256 supplySpeed = rewardsDistributor.rewardTokenSupplySpeeds(vToken);\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n if (\n supplyState.lastRewardingBlockOrTimestamp > 0 &&\n blockNumberOrTimestamp > supplyState.lastRewardingBlockOrTimestamp\n ) {\n blockNumberOrTimestamp = supplyState.lastRewardingBlockOrTimestamp;\n }\n\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, supplyState.blockOrTimestamp);\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\n uint256 supplyTokens = VToken(vToken).totalSupply();\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, supplySpeed);\n Double memory ratio = supplyTokens > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\n } else if (deltaBlocksOrTimestamp > 0) {\n supplyState.blockOrTimestamp = blockNumberOrTimestamp;\n }\n }\n\n function calculateBorrowerReward(\n address vToken,\n RewardsDistributor rewardsDistributor,\n address borrower,\n RewardTokenState memory borrowState,\n Exp memory marketBorrowIndex\n ) internal view returns (uint256) {\n Double memory borrowIndex = Double({ mantissa: borrowState.index });\n Double memory borrowerIndex = Double({\n mantissa: rewardsDistributor.rewardTokenBorrowerIndex(vToken, borrower)\n });\n if (borrowerIndex.mantissa == 0 && borrowIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\n // Covers the case where users borrowed tokens before the market's borrow state index was set\n borrowerIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\n }\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\n return borrowerDelta;\n }\n\n function calculateSupplierReward(\n address vToken,\n RewardsDistributor rewardsDistributor,\n address supplier,\n RewardTokenState memory supplyState\n ) internal view returns (uint256) {\n Double memory supplyIndex = Double({ mantissa: supplyState.index });\n Double memory supplierIndex = Double({\n mantissa: rewardsDistributor.rewardTokenSupplierIndex(vToken, supplier)\n });\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\n // Covers the case where users supplied tokens before the market's supply state index was set\n supplierIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\n }\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\n return supplierDelta;\n }\n}\n" + }, + "contracts/lib/constants.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\n/// @dev The approximate number of seconds per year\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\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" + }, + "contracts/lib/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 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" + }, + "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" + }, + "contracts/Pool/PoolRegistry.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\n\nimport { PoolRegistryInterface } from \"./PoolRegistryInterface.sol\";\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { ensureNonzeroAddress } from \"../lib/validators.sol\";\n\n/**\n * @title PoolRegistry\n * @author Venus\n * @notice The Isolated Pools architecture centers around the `PoolRegistry` contract. The `PoolRegistry` maintains a directory of isolated lending\n * pools and can perform actions like creating and registering new pools, adding new markets to existing pools, setting and updating the pool's required\n * metadata, and providing the getter methods to get information on the pools.\n *\n * Isolated lending has three main components: PoolRegistry, pools, and markets. The PoolRegistry is responsible for managing pools.\n * It can create new pools, update pool metadata and manage markets within pools. PoolRegistry contains getter methods to get the details of\n * any existing pool like `getVTokenForAsset` and `getPoolsSupportedByAsset`. It also contains methods for updating pool metadata (`updatePoolMetadata`)\n * and setting pool name (`setPoolName`).\n *\n * The directory of pools is managed through two mappings: `_poolByComptroller` which is a hashmap with the comptroller address as the key and `VenusPool` as\n * the value and `_poolsByID` which is an array of comptroller addresses. Individual pools can be accessed by calling `getPoolByComptroller` with the pool's\n * comptroller address. `_poolsByID` is used to iterate through all of the pools.\n *\n * PoolRegistry also contains a map of asset addresses called `_supportedPools` that maps to an array of assets suppored by each pool. This array of pools by\n * asset is retrieved by calling `getPoolsSupportedByAsset`.\n *\n * PoolRegistry registers new isolated pools in the directory with the `createRegistryPool` method. Isolated pools are composed of independent markets with\n * specific assets and custom risk management configurations according to their markets.\n */\ncontract PoolRegistry is Ownable2StepUpgradeable, AccessControlledV8, PoolRegistryInterface {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n struct AddMarketInput {\n VToken vToken;\n uint256 collateralFactor;\n uint256 liquidationThreshold;\n uint256 initialSupply;\n address vTokenReceiver;\n uint256 supplyCap;\n uint256 borrowCap;\n }\n\n uint256 internal constant MAX_POOL_NAME_LENGTH = 100;\n\n /**\n * @notice Maps pool's comptroller address to metadata.\n */\n mapping(address => VenusPoolMetaData) public metadata;\n\n /**\n * @dev Maps pool ID to pool's comptroller address\n */\n mapping(uint256 => address) private _poolsByID;\n\n /**\n * @dev Total number of pools created.\n */\n uint256 private _numberOfPools;\n\n /**\n * @dev Maps comptroller address to Venus pool Index.\n */\n mapping(address => VenusPool) private _poolByComptroller;\n\n /**\n * @dev Maps pool's comptroller address to asset to vToken.\n */\n mapping(address => mapping(address => address)) private _vTokens;\n\n /**\n * @dev Maps asset to list of supported pools.\n */\n mapping(address => address[]) private _supportedPools;\n\n /**\n * @notice Emitted when a new Venus pool is added to the directory.\n */\n event PoolRegistered(address indexed comptroller, VenusPool pool);\n\n /**\n * @notice Emitted when a pool name is set.\n */\n event PoolNameSet(address indexed comptroller, string oldName, string newName);\n\n /**\n * @notice Emitted when a pool metadata is updated.\n */\n event PoolMetadataUpdated(\n address indexed comptroller,\n VenusPoolMetaData oldMetadata,\n VenusPoolMetaData newMetadata\n );\n\n /**\n * @notice Emitted when a Market is added to the pool.\n */\n event MarketAdded(address indexed comptroller, address indexed vTokenAddress);\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the deployer to owner\n * @param accessControlManager_ AccessControlManager contract address\n */\n function initialize(address accessControlManager_) external initializer {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n }\n\n /**\n * @notice Adds a new Venus pool to the directory\n * @dev Price oracle must be configured before adding a pool\n * @param name The name of the pool\n * @param comptroller Pool's Comptroller contract\n * @param closeFactor The pool's close factor (scaled by 1e18)\n * @param liquidationIncentive The pool's liquidation incentive (scaled by 1e18)\n * @param minLiquidatableCollateral Minimal collateral for regular (non-batch) liquidations flow\n * @return index The index of the registered Venus pool\n * @custom:error ZeroAddressNotAllowed is thrown when Comptroller address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\n */\n function addPool(\n string calldata name,\n Comptroller comptroller,\n uint256 closeFactor,\n uint256 liquidationIncentive,\n uint256 minLiquidatableCollateral\n ) external virtual returns (uint256 index) {\n _checkAccessAllowed(\"addPool(string,address,uint256,uint256,uint256)\");\n // Input validation\n ensureNonzeroAddress(address(comptroller));\n ensureNonzeroAddress(address(comptroller.oracle()));\n\n uint256 poolId = _registerPool(name, address(comptroller));\n\n // Set Venus pool parameters\n comptroller.setCloseFactor(closeFactor);\n comptroller.setLiquidationIncentive(liquidationIncentive);\n comptroller.setMinLiquidatableCollateral(minLiquidatableCollateral);\n\n return poolId;\n }\n\n /**\n * @notice Add a market to an existing pool and then mint to provide initial supply\n * @param input The structure describing the parameters for adding a market to a pool\n * @custom:error ZeroAddressNotAllowed is thrown when vToken address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when vTokenReceiver address is zero\n */\n function addMarket(AddMarketInput memory input) external {\n _checkAccessAllowed(\"addMarket(AddMarketInput)\");\n ensureNonzeroAddress(address(input.vToken));\n ensureNonzeroAddress(input.vTokenReceiver);\n require(input.initialSupply > 0, \"PoolRegistry: initialSupply is zero\");\n\n VToken vToken = input.vToken;\n address vTokenAddress = address(vToken);\n address comptrollerAddress = address(vToken.comptroller());\n Comptroller comptroller = Comptroller(comptrollerAddress);\n address underlyingAddress = vToken.underlying();\n IERC20Upgradeable underlying = IERC20Upgradeable(underlyingAddress);\n\n require(_poolByComptroller[comptrollerAddress].creator != address(0), \"PoolRegistry: Pool not registered\");\n // solhint-disable-next-line reason-string\n require(\n _vTokens[comptrollerAddress][underlyingAddress] == address(0),\n \"PoolRegistry: Market already added for asset comptroller combination\"\n );\n\n comptroller.supportMarket(vToken);\n comptroller.setCollateralFactor(vToken, input.collateralFactor, input.liquidationThreshold);\n\n uint256[] memory newSupplyCaps = new uint256[](1);\n uint256[] memory newBorrowCaps = new uint256[](1);\n VToken[] memory vTokens = new VToken[](1);\n\n newSupplyCaps[0] = input.supplyCap;\n newBorrowCaps[0] = input.borrowCap;\n vTokens[0] = vToken;\n\n comptroller.setMarketSupplyCaps(vTokens, newSupplyCaps);\n comptroller.setMarketBorrowCaps(vTokens, newBorrowCaps);\n\n _vTokens[comptrollerAddress][underlyingAddress] = vTokenAddress;\n _supportedPools[underlyingAddress].push(comptrollerAddress);\n\n uint256 amountToSupply = _transferIn(underlying, msg.sender, input.initialSupply);\n underlying.forceApprove(vTokenAddress, 0);\n underlying.forceApprove(vTokenAddress, amountToSupply);\n vToken.mintBehalf(input.vTokenReceiver, amountToSupply);\n\n emit MarketAdded(comptrollerAddress, vTokenAddress);\n }\n\n /**\n * @notice Modify existing Venus pool name\n * @param comptroller Pool's Comptroller\n * @param name New pool name\n */\n function setPoolName(address comptroller, string calldata name) external {\n _checkAccessAllowed(\"setPoolName(address,string)\");\n _ensureValidName(name);\n VenusPool storage pool = _poolByComptroller[comptroller];\n string memory oldName = pool.name;\n pool.name = name;\n emit PoolNameSet(comptroller, oldName, name);\n }\n\n /**\n * @notice Update metadata of an existing pool\n * @param comptroller Pool's Comptroller\n * @param metadata_ New pool metadata\n */\n function updatePoolMetadata(address comptroller, VenusPoolMetaData calldata metadata_) external {\n _checkAccessAllowed(\"updatePoolMetadata(address,VenusPoolMetaData)\");\n VenusPoolMetaData memory oldMetadata = metadata[comptroller];\n metadata[comptroller] = metadata_;\n emit PoolMetadataUpdated(comptroller, oldMetadata, metadata_);\n }\n\n /**\n * @notice Returns arrays of all Venus pools' data\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\n * @return A list of all pools within PoolRegistry, with details for each pool\n */\n function getAllPools() external view override returns (VenusPool[] memory) {\n uint256 numberOfPools_ = _numberOfPools; // storage load to save gas\n VenusPool[] memory _pools = new VenusPool[](numberOfPools_);\n for (uint256 i = 1; i <= numberOfPools_; ++i) {\n address comptroller = _poolsByID[i];\n _pools[i - 1] = (_poolByComptroller[comptroller]);\n }\n return _pools;\n }\n\n /**\n * @param comptroller The comptroller proxy address associated to the pool\n * @return Returns Venus pool\n */\n function getPoolByComptroller(address comptroller) external view override returns (VenusPool memory) {\n return _poolByComptroller[comptroller];\n }\n\n /**\n * @param comptroller comptroller of Venus pool\n * @return Returns Metadata of Venus pool\n */\n function getVenusPoolMetadata(address comptroller) external view override returns (VenusPoolMetaData memory) {\n return metadata[comptroller];\n }\n\n function getVTokenForAsset(address comptroller, address asset) external view override returns (address) {\n return _vTokens[comptroller][asset];\n }\n\n function getPoolsSupportedByAsset(address asset) external view override returns (address[] memory) {\n return _supportedPools[asset];\n }\n\n /**\n * @dev Adds a new Venus pool to the directory (without checking msg.sender).\n * @param name The name of the pool\n * @param comptroller The pool's Comptroller proxy contract address\n * @return The index of the registered Venus pool\n */\n function _registerPool(string calldata name, address comptroller) internal returns (uint256) {\n VenusPool storage storedPool = _poolByComptroller[comptroller];\n\n require(storedPool.creator == address(0), \"PoolRegistry: Pool already exists in the directory.\");\n _ensureValidName(name);\n\n ++_numberOfPools;\n uint256 numberOfPools_ = _numberOfPools; // cache on stack to save storage read gas\n\n VenusPool memory pool = VenusPool(name, msg.sender, comptroller, block.number, block.timestamp);\n\n _poolsByID[numberOfPools_] = comptroller;\n _poolByComptroller[comptroller] = pool;\n\n emit PoolRegistered(comptroller, pool);\n return numberOfPools_;\n }\n\n function _transferIn(IERC20Upgradeable token, address from, uint256 amount) internal returns (uint256) {\n uint256 balanceBefore = token.balanceOf(address(this));\n token.safeTransferFrom(from, address(this), amount);\n uint256 balanceAfter = token.balanceOf(address(this));\n return balanceAfter - balanceBefore;\n }\n\n function _ensureValidName(string calldata name) internal pure {\n require(bytes(name).length <= MAX_POOL_NAME_LENGTH, \"Pool's name is too large\");\n }\n}\n" + }, + "contracts/Pool/PoolRegistryInterface.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 /**\n * @notice Struct for a Venus interest rate pool metadata.\n */\n struct VenusPoolMetaData {\n string category;\n string logoURL;\n string description;\n }\n\n /// @notice Get all pools in PoolRegistry\n function getAllPools() external view returns (VenusPool[] memory);\n\n /// @notice Get a pool by comptroller address\n function getPoolByComptroller(address comptroller) external view returns (VenusPool memory);\n\n /// @notice Get the address of the VToken contract in the Pool where the underlying token is the provided 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 /// @notice Get the metadata of a Pool by comptroller address\n function getVenusPoolMetadata(address comptroller) external view returns (VenusPoolMetaData memory);\n}\n" + }, + "contracts/Rewards/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\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 { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { TimeManagerV8 } from \"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\";\n\nimport { ExponentialNoError } from \"../ExponentialNoError.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { MaxLoopsLimitHelper } from \"../MaxLoopsLimitHelper.sol\";\nimport { RewardsDistributorStorage } from \"./RewardsDistributorStorage.sol\";\n\n/**\n * @title `RewardsDistributor`\n * @author Venus\n * @notice Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol.\n * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward\n * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool.\n * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward\n * token to be released each slot (block or second) for borrowers and suppliers, which is distributed based on a user’s percentage of the borrows or supplies\n * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting\n * their contributor reward token speed, which similarly allocates a fixed amount of reward token per slot (block or second).\n *\n * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed\n * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized\n * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\n */\ncontract RewardsDistributor is\n ExponentialNoError,\n Ownable2StepUpgradeable,\n AccessControlledV8,\n MaxLoopsLimitHelper,\n RewardsDistributorStorage,\n TimeManagerV8\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice The initial REWARD TOKEN index for a market\n uint224 public constant INITIAL_INDEX = 1e36;\n\n /// @notice Emitted when REWARD TOKEN is distributed to a supplier\n event DistributedSupplierRewardToken(\n VToken indexed vToken,\n address indexed supplier,\n uint256 rewardTokenDelta,\n uint256 rewardTokenTotal,\n uint256 rewardTokenSupplyIndex\n );\n\n /// @notice Emitted when REWARD TOKEN is distributed to a borrower\n event DistributedBorrowerRewardToken(\n VToken indexed vToken,\n address indexed borrower,\n uint256 rewardTokenDelta,\n uint256 rewardTokenTotal,\n uint256 rewardTokenBorrowIndex\n );\n\n /// @notice Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\n event RewardTokenSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /// @notice Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\n event RewardTokenBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /// @notice Emitted when REWARD TOKEN is granted by admin\n event RewardTokenGranted(address indexed recipient, uint256 amount);\n\n /// @notice Emitted when a new REWARD TOKEN speed is set for a contributor\n event ContributorRewardTokenSpeedUpdated(address indexed contributor, uint256 newSpeed);\n\n /// @notice Emitted when a market is initialized\n event MarketInitialized(address indexed vToken);\n\n /// @notice Emitted when a reward token supply index is updated\n event RewardTokenSupplyIndexUpdated(address indexed vToken);\n\n /// @notice Emitted when a reward token borrow index is updated\n event RewardTokenBorrowIndexUpdated(address indexed vToken, Exp marketBorrowIndex);\n\n /// @notice Emitted when a reward for contributor is updated\n event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued);\n\n /// @notice Emitted when a reward token last rewarding block for supply is updated\n event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\n\n /// @notice Emitted when a reward token last rewarding block for borrow is updated\n event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\n\n /// @notice Emitted when a reward token last rewarding timestamp for supply is updated\n event SupplyLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\n\n /// @notice Emitted when a reward token last rewarding timestamp for borrow is updated\n event BorrowLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\n\n modifier onlyComptroller() {\n require(address(comptroller) == msg.sender, \"Only comptroller can call this function\");\n _;\n }\n\n /**\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\n * @param blocksPerYear_ The number of blocks per year\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /**\n * @notice RewardsDistributor initializer\n * @dev Initializes the deployer to owner\n * @param comptroller_ Comptroller to attach the reward distributor to\n * @param rewardToken_ Reward token to distribute\n * @param loopsLimit_ Maximum number of iterations for the loops in this contract\n * @param accessControlManager_ AccessControlManager contract address\n */\n function initialize(\n Comptroller comptroller_,\n IERC20Upgradeable rewardToken_,\n uint256 loopsLimit_,\n address accessControlManager_\n ) external initializer {\n comptroller = comptroller_;\n rewardToken = rewardToken_;\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n\n _setMaxLoopsLimit(loopsLimit_);\n }\n\n /**\n * @notice Initializes the market state for a specific vToken\n * @param vToken The address of the vToken to be initialized\n * @custom:event MarketInitialized emits on success\n * @custom:access Only Comptroller\n */\n function initializeMarket(address vToken) external onlyComptroller {\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n isTimeBased\n ? _initializeMarketTimestampBased(vToken, blockNumberOrTimestamp)\n : _initializeMarketBlockBased(vToken, safe32(blockNumberOrTimestamp, \"block number exceeds 32 bits\"));\n\n emit MarketInitialized(vToken);\n }\n\n /*** Reward Token Distribution ***/\n\n /**\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them\n * Borrowers will begin to accrue after the first interaction with the protocol.\n * @dev This function should only be called when the user has a borrow position in the market\n * (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook)\n * We avoid an external call to check if they are in the market to save gas because this function is called in many places\n * @param vToken The market in which the borrower is interacting\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\n * @param marketBorrowIndex The current global borrow index of vToken\n */\n function distributeBorrowerRewardToken(\n address vToken,\n address borrower,\n Exp memory marketBorrowIndex\n ) external onlyComptroller {\n _distributeBorrowerRewardToken(vToken, borrower, marketBorrowIndex);\n }\n\n function updateRewardTokenSupplyIndex(address vToken) external onlyComptroller {\n _updateRewardTokenSupplyIndex(vToken);\n }\n\n /**\n * @notice Transfer REWARD TOKEN to the recipient\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\n * @param recipient The address of the recipient to transfer REWARD TOKEN to\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\n */\n function grantRewardToken(address recipient, uint256 amount) external onlyOwner {\n uint256 amountLeft = _grantRewardToken(recipient, amount);\n require(amountLeft == 0, \"insufficient rewardToken for grant\");\n emit RewardTokenGranted(recipient, amount);\n }\n\n function updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) external onlyComptroller {\n _updateRewardTokenBorrowIndex(vToken, marketBorrowIndex);\n }\n\n /**\n * @notice Set REWARD TOKEN borrow and supply speeds for the specified markets\n * @param vTokens The markets whose REWARD TOKEN speed to update\n * @param supplySpeeds New supply-side REWARD TOKEN speed for the corresponding market\n * @param borrowSpeeds New borrow-side REWARD TOKEN speed for the corresponding market\n */\n function setRewardTokenSpeeds(\n VToken[] memory vTokens,\n uint256[] memory supplySpeeds,\n uint256[] memory borrowSpeeds\n ) external {\n _checkAccessAllowed(\"setRewardTokenSpeeds(address[],uint256[],uint256[])\");\n uint256 numTokens = vTokens.length;\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \"invalid setRewardTokenSpeeds\");\n\n for (uint256 i; i < numTokens; ++i) {\n _setRewardTokenSpeed(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\n }\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding block for the specified markets, used when contract is block based\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\n * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market\n * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market\n */\n function setLastRewardingBlocks(\n VToken[] calldata vTokens,\n uint32[] calldata supplyLastRewardingBlocks,\n uint32[] calldata borrowLastRewardingBlocks\n ) external {\n _checkAccessAllowed(\"setLastRewardingBlocks(address[],uint32[],uint32[])\");\n require(!isTimeBased, \"Block-based operation only\");\n\n uint256 numTokens = vTokens.length;\n require(\n numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length,\n \"RewardsDistributor::setLastRewardingBlocks invalid input\"\n );\n\n for (uint256 i; i < numTokens; ) {\n _setLastRewardingBlock(vTokens[i], supplyLastRewardingBlocks[i], borrowLastRewardingBlocks[i]);\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding block timestamp for the specified markets, used when contract is time based\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\n * @param supplyLastRewardingBlockTimestamps New supply-side REWARD TOKEN last rewarding block timestamp for the corresponding market\n * @param borrowLastRewardingBlockTimestamps New borrow-side REWARD TOKEN last rewarding block timestamp for the corresponding market\n */\n function setLastRewardingBlockTimestamps(\n VToken[] calldata vTokens,\n uint256[] calldata supplyLastRewardingBlockTimestamps,\n uint256[] calldata borrowLastRewardingBlockTimestamps\n ) external {\n _checkAccessAllowed(\"setLastRewardingBlockTimestamps(address[],uint256[],uint256[])\");\n require(isTimeBased, \"Time-based operation only\");\n\n uint256 numTokens = vTokens.length;\n require(\n numTokens == supplyLastRewardingBlockTimestamps.length &&\n numTokens == borrowLastRewardingBlockTimestamps.length,\n \"RewardsDistributor::setLastRewardingBlockTimestamps invalid input\"\n );\n\n for (uint256 i; i < numTokens; ) {\n _setLastRewardingBlockTimestamp(\n vTokens[i],\n supplyLastRewardingBlockTimestamps[i],\n borrowLastRewardingBlockTimestamps[i]\n );\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Set REWARD TOKEN speed for a single contributor\n * @param contributor The contributor whose REWARD TOKEN speed to update\n * @param rewardTokenSpeed New REWARD TOKEN speed for contributor\n */\n function setContributorRewardTokenSpeed(address contributor, uint256 rewardTokenSpeed) external onlyOwner {\n // note that REWARD TOKEN speed could be set to 0 to halt liquidity rewards for a contributor\n updateContributorRewards(contributor);\n if (rewardTokenSpeed == 0) {\n // release storage\n delete lastContributorBlock[contributor];\n } else {\n lastContributorBlock[contributor] = getBlockNumberOrTimestamp();\n }\n rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed;\n\n emit ContributorRewardTokenSpeedUpdated(contributor, rewardTokenSpeed);\n }\n\n function distributeSupplierRewardToken(address vToken, address supplier) external onlyComptroller {\n _distributeSupplierRewardToken(vToken, supplier);\n }\n\n /**\n * @notice Claim all the rewardToken accrued by holder in all markets\n * @param holder The address to claim REWARD TOKEN for\n */\n function claimRewardToken(address holder) external {\n return claimRewardToken(holder, comptroller.getAllMarkets());\n }\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) external onlyOwner {\n _setMaxLoopsLimit(limit);\n }\n\n /**\n * @notice Calculate additional accrued REWARD TOKEN for a contributor since last accrual\n * @param contributor The address to calculate contributor rewards for\n */\n function updateContributorRewards(address contributor) public {\n uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor];\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, lastContributorBlock[contributor]);\n if (deltaBlocksOrTimestamp > 0 && rewardTokenSpeed > 0) {\n uint256 newAccrued = mul_(deltaBlocksOrTimestamp, rewardTokenSpeed);\n uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued);\n\n rewardTokenAccrued[contributor] = contributorAccrued;\n lastContributorBlock[contributor] = blockNumberOrTimestamp;\n\n emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]);\n }\n }\n\n /**\n * @notice Claim all the rewardToken accrued by holder in the specified markets\n * @param holder The address to claim REWARD TOKEN for\n * @param vTokens The list of markets to claim REWARD TOKEN in\n */\n function claimRewardToken(address holder, VToken[] memory vTokens) public {\n uint256 vTokensCount = vTokens.length;\n\n _ensureMaxLoops(vTokensCount);\n\n for (uint256 i; i < vTokensCount; ++i) {\n VToken vToken = vTokens[i];\n require(comptroller.isMarketListed(vToken), \"market must be listed\");\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\n _distributeBorrowerRewardToken(address(vToken), holder, borrowIndex);\n _updateRewardTokenSupplyIndex(address(vToken));\n _distributeSupplierRewardToken(address(vToken), holder);\n }\n rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]);\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding block for a single market.\n * @param vToken market's whose reward token last rewarding block to be updated\n * @param supplyLastRewardingBlock New supply-side REWARD TOKEN last rewarding block for market\n * @param borrowLastRewardingBlock New borrow-side REWARD TOKEN last rewarding block for market\n */\n function _setLastRewardingBlock(\n VToken vToken,\n uint32 supplyLastRewardingBlock,\n uint32 borrowLastRewardingBlock\n ) internal {\n require(comptroller.isMarketListed(vToken), \"rewardToken market is not listed\");\n\n uint256 blockNumber = getBlockNumberOrTimestamp();\n\n require(supplyLastRewardingBlock > blockNumber, \"setting last rewarding block in the past is not allowed\");\n require(borrowLastRewardingBlock > blockNumber, \"setting last rewarding block in the past is not allowed\");\n\n uint32 currentSupplyLastRewardingBlock = rewardTokenSupplyState[address(vToken)].lastRewardingBlock;\n uint32 currentBorrowLastRewardingBlock = rewardTokenBorrowState[address(vToken)].lastRewardingBlock;\n\n require(\n currentSupplyLastRewardingBlock == 0 || currentSupplyLastRewardingBlock > blockNumber,\n \"this RewardsDistributor is already locked\"\n );\n require(\n currentBorrowLastRewardingBlock == 0 || currentBorrowLastRewardingBlock > blockNumber,\n \"this RewardsDistributor is already locked\"\n );\n\n if (currentSupplyLastRewardingBlock != supplyLastRewardingBlock) {\n rewardTokenSupplyState[address(vToken)].lastRewardingBlock = supplyLastRewardingBlock;\n emit SupplyLastRewardingBlockUpdated(address(vToken), supplyLastRewardingBlock);\n }\n\n if (currentBorrowLastRewardingBlock != borrowLastRewardingBlock) {\n rewardTokenBorrowState[address(vToken)].lastRewardingBlock = borrowLastRewardingBlock;\n emit BorrowLastRewardingBlockUpdated(address(vToken), borrowLastRewardingBlock);\n }\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding timestamp for a single market.\n * @param vToken market's whose reward token last rewarding timestamp to be updated\n * @param supplyLastRewardingBlockTimestamp New supply-side REWARD TOKEN last rewarding timestamp for market\n * @param borrowLastRewardingBlockTimestamp New borrow-side REWARD TOKEN last rewarding timestamp for market\n */\n function _setLastRewardingBlockTimestamp(\n VToken vToken,\n uint256 supplyLastRewardingBlockTimestamp,\n uint256 borrowLastRewardingBlockTimestamp\n ) internal {\n require(comptroller.isMarketListed(vToken), \"rewardToken market is not listed\");\n\n uint256 blockTimestamp = getBlockNumberOrTimestamp();\n\n require(\n supplyLastRewardingBlockTimestamp > blockTimestamp,\n \"setting last rewarding timestamp in the past is not allowed\"\n );\n require(\n borrowLastRewardingBlockTimestamp > blockTimestamp,\n \"setting last rewarding timestamp in the past is not allowed\"\n );\n\n uint256 currentSupplyLastRewardingBlockTimestamp = rewardTokenSupplyStateTimeBased[address(vToken)]\n .lastRewardingTimestamp;\n uint256 currentBorrowLastRewardingBlockTimestamp = rewardTokenBorrowStateTimeBased[address(vToken)]\n .lastRewardingTimestamp;\n\n require(\n currentSupplyLastRewardingBlockTimestamp == 0 || currentSupplyLastRewardingBlockTimestamp > blockTimestamp,\n \"this RewardsDistributor is already locked\"\n );\n require(\n currentBorrowLastRewardingBlockTimestamp == 0 || currentBorrowLastRewardingBlockTimestamp > blockTimestamp,\n \"this RewardsDistributor is already locked\"\n );\n\n if (currentSupplyLastRewardingBlockTimestamp != supplyLastRewardingBlockTimestamp) {\n rewardTokenSupplyStateTimeBased[address(vToken)].lastRewardingTimestamp = supplyLastRewardingBlockTimestamp;\n emit SupplyLastRewardingBlockTimestampUpdated(address(vToken), supplyLastRewardingBlockTimestamp);\n }\n\n if (currentBorrowLastRewardingBlockTimestamp != borrowLastRewardingBlockTimestamp) {\n rewardTokenBorrowStateTimeBased[address(vToken)].lastRewardingTimestamp = borrowLastRewardingBlockTimestamp;\n emit BorrowLastRewardingBlockTimestampUpdated(address(vToken), borrowLastRewardingBlockTimestamp);\n }\n }\n\n /**\n * @notice Set REWARD TOKEN speed for a single market.\n * @param vToken market's whose reward token rate to be updated\n * @param supplySpeed New supply-side REWARD TOKEN speed for market\n * @param borrowSpeed New borrow-side REWARD TOKEN speed for market\n */\n function _setRewardTokenSpeed(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\n require(comptroller.isMarketListed(vToken), \"rewardToken market is not listed\");\n\n if (rewardTokenSupplySpeeds[address(vToken)] != supplySpeed) {\n // Supply speed updated so let's update supply state to ensure that\n // 1. REWARD TOKEN accrued properly for the old speed, and\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\n _updateRewardTokenSupplyIndex(address(vToken));\n\n // Update speed and emit event\n rewardTokenSupplySpeeds[address(vToken)] = supplySpeed;\n emit RewardTokenSupplySpeedUpdated(vToken, supplySpeed);\n }\n\n if (rewardTokenBorrowSpeeds[address(vToken)] != borrowSpeed) {\n // Borrow speed updated so let's update borrow state to ensure that\n // 1. REWARD TOKEN accrued properly for the old speed, and\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\n\n // Update speed and emit event\n rewardTokenBorrowSpeeds[address(vToken)] = borrowSpeed;\n emit RewardTokenBorrowSpeedUpdated(vToken, borrowSpeed);\n }\n }\n\n /**\n * @notice Calculate REWARD TOKEN 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 REWARD TOKEN to\n */\n function _distributeSupplierRewardToken(address vToken, address supplier) internal {\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\n\n uint256 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\n uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier];\n\n // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN\n rewardTokenSupplierIndex[vToken][supplier] = supplyIndex;\n\n if (supplierIndex == 0 && supplyIndex >= INITIAL_INDEX) {\n // Covers the case where users supplied tokens before the market's supply state index was set.\n // Rewards the user with REWARD TOKEN accrued from the start of when supplier rewards were first\n // set for the market.\n supplierIndex = INITIAL_INDEX;\n }\n\n // Calculate change in the cumulative sum of the REWARD TOKEN per vToken accrued\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\n\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\n\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerVToken\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\n\n uint256 supplierAccrued = add_(rewardTokenAccrued[supplier], supplierDelta);\n rewardTokenAccrued[supplier] = supplierAccrued;\n\n emit DistributedSupplierRewardToken(VToken(vToken), supplier, supplierDelta, supplierAccrued, supplyIndex);\n }\n\n /**\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them.\n * @param vToken The market in which the borrower is interacting\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\n * @param marketBorrowIndex The current global borrow index of vToken\n */\n function _distributeBorrowerRewardToken(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\n\n uint256 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\n uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower];\n\n // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN\n rewardTokenBorrowerIndex[vToken][borrower] = borrowIndex;\n\n if (borrowerIndex == 0 && borrowIndex >= INITIAL_INDEX) {\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\n // Rewards the user with REWARD TOKEN accrued from the start of when borrower rewards were first\n // set for the market.\n borrowerIndex = INITIAL_INDEX;\n }\n\n // Calculate change in the cumulative sum of the REWARD TOKEN per borrowed unit accrued\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\n\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\n\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerBorrowedUnit\n if (borrowerAmount != 0) {\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\n\n uint256 borrowerAccrued = add_(rewardTokenAccrued[borrower], borrowerDelta);\n rewardTokenAccrued[borrower] = borrowerAccrued;\n\n emit DistributedBorrowerRewardToken(VToken(vToken), borrower, borrowerDelta, borrowerAccrued, borrowIndex);\n }\n }\n\n /**\n * @notice Transfer REWARD TOKEN to the user.\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all.\n * @param user The address of the user to transfer REWARD TOKEN to\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\n * @return The amount of REWARD TOKEN which was NOT transferred to the user\n */\n function _grantRewardToken(address user, uint256 amount) internal returns (uint256) {\n uint256 rewardTokenRemaining = rewardToken.balanceOf(address(this));\n if (amount > 0 && amount <= rewardTokenRemaining) {\n rewardToken.safeTransfer(user, amount);\n return 0;\n }\n return amount;\n }\n\n /**\n * @notice Accrue REWARD TOKEN to the market by updating the supply index\n * @param vToken The market whose supply index to update\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\n */\n function _updateRewardTokenSupplyIndex(address vToken) internal {\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\n\n uint256 supplySpeed = rewardTokenSupplySpeeds[vToken];\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n if (!isTimeBased) {\n safe32(blockNumberOrTimestamp, \"block number exceeds 32 bits\");\n }\n\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\n ? supplyStateTimeBased.lastRewardingTimestamp\n : uint256(supplyState.lastRewardingBlock);\n\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\n }\n\n uint256 deltaBlocksOrTimestamp = sub_(\n blockNumberOrTimestamp,\n (isTimeBased ? supplyStateTimeBased.timestamp : uint256(supplyState.block))\n );\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\n uint256 supplyTokens = VToken(vToken).totalSupply();\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, supplySpeed);\n Double memory ratio = supplyTokens > 0\n ? fraction(accruedSinceUpdate, supplyTokens)\n : Double({ mantissa: 0 });\n uint224 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\n uint224 index = safe224(\n add_(Double({ mantissa: supplyIndex }), ratio).mantissa,\n \"new index exceeds 224 bits\"\n );\n\n if (isTimeBased) {\n supplyStateTimeBased.index = index;\n supplyStateTimeBased.timestamp = blockNumberOrTimestamp;\n } else {\n supplyState.index = index;\n supplyState.block = uint32(blockNumberOrTimestamp);\n }\n } else if (deltaBlocksOrTimestamp > 0) {\n isTimeBased ? supplyStateTimeBased.timestamp = blockNumberOrTimestamp : supplyState.block = uint32(\n blockNumberOrTimestamp\n );\n }\n\n emit RewardTokenSupplyIndexUpdated(vToken);\n }\n\n /**\n * @notice Accrue REWARD TOKEN to the market by updating the borrow index\n * @param vToken The market whose borrow index to update\n * @param marketBorrowIndex The current global borrow index of vToken\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\n */\n function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\n\n uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken];\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n if (!isTimeBased) {\n safe32(blockNumberOrTimestamp, \"block number exceeds 32 bits\");\n }\n\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\n ? borrowStateTimeBased.lastRewardingTimestamp\n : uint256(borrowState.lastRewardingBlock);\n\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\n }\n\n uint256 deltaBlocksOrTimestamp = sub_(\n blockNumberOrTimestamp,\n (isTimeBased ? borrowStateTimeBased.timestamp : uint256(borrowState.block))\n );\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, borrowSpeed);\n Double memory ratio = borrowAmount > 0\n ? fraction(accruedSinceUpdate, borrowAmount)\n : Double({ mantissa: 0 });\n uint224 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\n uint224 index = safe224(\n add_(Double({ mantissa: borrowIndex }), ratio).mantissa,\n \"new index exceeds 224 bits\"\n );\n\n if (isTimeBased) {\n borrowStateTimeBased.index = index;\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\n } else {\n borrowState.index = index;\n borrowState.block = uint32(blockNumberOrTimestamp);\n }\n } else if (deltaBlocksOrTimestamp > 0) {\n if (isTimeBased) {\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\n } else {\n borrowState.block = uint32(blockNumberOrTimestamp);\n }\n }\n\n emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex);\n }\n\n /**\n * @notice Initializes the market state for a specific vToken called when contract is block-based\n * @param vToken The address of the vToken to be initialized\n * @param blockNumber current block number\n */\n function _initializeMarketBlockBased(address vToken, uint32 blockNumber) internal {\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n RewardToken storage borrowState = rewardTokenBorrowState[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 = INITIAL_INDEX;\n }\n\n if (borrowState.index == 0) {\n // Initialize borrow state index with default value\n borrowState.index = INITIAL_INDEX;\n }\n\n /*\n * Update market state block numbers\n */\n supplyState.block = borrowState.block = blockNumber;\n }\n\n /**\n * @notice Initializes the market state for a specific vToken called when contract is time-based\n * @param vToken The address of the vToken to be initialized\n * @param blockTimestamp current block timestamp\n */\n function _initializeMarketTimestampBased(address vToken, uint256 blockTimestamp) internal {\n TimeBasedRewardToken storage supplyState = rewardTokenSupplyStateTimeBased[vToken];\n TimeBasedRewardToken storage borrowState = rewardTokenBorrowStateTimeBased[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 = INITIAL_INDEX;\n }\n\n if (borrowState.index == 0) {\n // Initialize borrow state index with default value\n borrowState.index = INITIAL_INDEX;\n }\n\n /*\n * Update market state block timestamp\n */\n supplyState.timestamp = borrowState.timestamp = blockTimestamp;\n }\n}\n" + }, + "contracts/Rewards/RewardsDistributorStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\nimport { Comptroller } from \"../Comptroller.sol\";\n\n/**\n * @title RewardsDistributorStorage\n * @author Venus\n * @dev Storage for RewardsDistributor\n */\ncontract RewardsDistributorStorage {\n struct RewardToken {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block number the index was last updated at\n uint32 block;\n // The block number at which to stop rewards\n uint32 lastRewardingBlock;\n }\n\n struct TimeBasedRewardToken {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block timestamp the index was last updated at\n uint256 timestamp;\n // The block timestamp at which to stop rewards\n uint256 lastRewardingTimestamp;\n }\n\n /// @notice The REWARD TOKEN market supply state for each market\n mapping(address => RewardToken) public rewardTokenSupplyState;\n\n /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\n mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex;\n\n /// @notice The REWARD TOKEN accrued but not yet transferred to each user\n mapping(address => uint256) public rewardTokenAccrued;\n\n /// @notice The rate at which rewardToken is distributed to the corresponding borrow market per slot (block or second)\n mapping(address => uint256) public rewardTokenBorrowSpeeds;\n\n /// @notice The rate at which rewardToken is distributed to the corresponding supply market per slot (block or second)\n mapping(address => uint256) public rewardTokenSupplySpeeds;\n\n /// @notice The REWARD TOKEN market borrow state for each market\n mapping(address => RewardToken) public rewardTokenBorrowState;\n\n /// @notice The portion of REWARD TOKEN that each contributor receives per slot (block or second)\n mapping(address => uint256) public rewardTokenContributorSpeeds;\n\n /// @notice Last slot (block or second) at which a contributor's REWARD TOKEN rewards have been allocated\n mapping(address => uint256) public lastContributorBlock;\n\n /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\n mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex;\n\n Comptroller internal comptroller;\n\n IERC20Upgradeable public rewardToken;\n\n /// @notice The REWARD TOKEN market supply state for each market\n mapping(address => TimeBasedRewardToken) public rewardTokenSupplyStateTimeBased;\n\n /// @notice The REWARD TOKEN market borrow state for each market\n mapping(address => TimeBasedRewardToken) public rewardTokenBorrowStateTimeBased;\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[37] private __gap;\n}\n" + }, + "contracts/VToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\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 { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { IProtocolShareReserve } from \"@venusprotocol/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\";\n\nimport { VTokenInterface } from \"./VTokenInterfaces.sol\";\nimport { ComptrollerInterface, ComptrollerViewInterface } from \"./ComptrollerInterface.sol\";\nimport { TokenErrorReporter } from \"./ErrorReporter.sol\";\nimport { InterestRateModel } from \"./InterestRateModel.sol\";\nimport { ExponentialNoError } from \"./ExponentialNoError.sol\";\nimport { TimeManagerV8 } from \"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\";\nimport { ensureNonzeroAddress } from \"./lib/validators.sol\";\n\n/**\n * @title VToken\n * @author Venus\n * @notice Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview,\n * each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of\n * the pool. The main actions a user regularly interacts with in a market are:\n\n- mint/redeem of vTokens;\n- transfer of vTokens;\n- borrow/repay a loan on an underlying asset;\n- liquidate a borrow or liquidate/heal an account.\n\n * A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`.\n * The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted\n * `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken`\n * as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that\n * a user may borrow up to a portion of their collateral determined by the market’s collateral factor. However, if their borrowed amount exceeds an amount\n * calculated using the market’s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also\n * pay off interest accrued on the borrow.\n * \n * The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller`\n * and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a\n * total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`.\n * Both functions settle all of an account’s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of\n * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\n */\ncontract VToken is\n Ownable2StepUpgradeable,\n AccessControlledV8,\n VTokenInterface,\n ExponentialNoError,\n TokenErrorReporter,\n TimeManagerV8\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5%\n\n // Maximum fraction of interest that can be set aside for reserves\n uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18;\n\n // Maximum borrow rate that can ever be applied per slot(block or second)\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n uint256 internal immutable MAX_BORROW_RATE_MANTISSA;\n\n /**\n * Reentrancy Guard **\n */\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 * @param timeBased_ A boolean indicating whether the contract is based on time or block.\n * @param blocksPerYear_ The number of blocks per year\n * @param maxBorrowRateMantissa_ The maximum value of borrowing rate mantissa\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor(\n bool timeBased_,\n uint256 blocksPerYear_,\n uint256 maxBorrowRateMantissa_\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n require(maxBorrowRateMantissa_ <= 1e18, \"Max borrow rate must be <= 1e18\");\n\n MAX_BORROW_RATE_MANTISSA = maxBorrowRateMantissa_;\n _disableInitializers();\n }\n\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_ ERC-20 name of this token\n * @param symbol_ ERC-20 symbol of this token\n * @param decimals_ ERC-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param accessControlManager_ AccessControlManager contract address\n * @param riskManagement Addresses of risk & income related contracts\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\n * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\n */\n function initialize(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address admin_,\n address accessControlManager_,\n RiskManagementInit memory riskManagement,\n uint256 reserveFactorMantissa_\n ) external initializer {\n ensureNonzeroAddress(admin_);\n\n // Initialize the market\n _initialize(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_,\n accessControlManager_,\n riskManagement,\n reserveFactorMantissa_\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 * @return success True if the transfer succeeded, reverts otherwise\n * @custom:event Emits Transfer event on success\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\n * @custom:access Not restricted\n */\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\n _transferTokens(msg.sender, msg.sender, dst, amount);\n return true;\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 success True if the transfer succeeded, reverts otherwise\n * @custom:event Emits Transfer event on success\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\n * @custom:access Not restricted\n */\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\n _transferTokens(msg.sender, src, dst, amount);\n return true;\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 (uint256.max means infinite)\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function approve(address spender, uint256 amount) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n transferAllowances[src][spender] = amount;\n emit Approval(src, spender, amount);\n return true;\n }\n\n /**\n * @notice Increase approval for `spender`\n * @param spender The address of the account which may transfer tokens\n * @param addedValue The number of additional tokens spender can transfer\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function increaseAllowance(address spender, uint256 addedValue) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n uint256 newAllowance = transferAllowances[src][spender];\n newAllowance += addedValue;\n transferAllowances[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n return true;\n }\n\n /**\n * @notice Decreases approval for `spender`\n * @param spender The address of the account which may transfer tokens\n * @param subtractedValue The number of tokens to remove from total approval\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n uint256 currentAllowance = transferAllowances[src][spender];\n require(currentAllowance >= subtractedValue, \"decreased allowance below zero\");\n unchecked {\n currentAllowance -= subtractedValue;\n }\n\n transferAllowances[src][spender] = currentAllowance;\n\n emit Approval(src, spender, currentAllowance);\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 amount The amount of underlying owned by `owner`\n */\n function balanceOfUnderlying(address owner) external override returns (uint256) {\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\n return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\n }\n\n /**\n * @notice Returns the current total borrows plus accrued interest\n * @return totalBorrows The total borrows with interest\n */\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\n accrueInterest();\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 borrowBalance The calculated balance\n */\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\n accrueInterest();\n return _borrowBalanceStored(account);\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function mint(uint256 mintAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _mintFresh(msg.sender, msg.sender, mintAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param minter User whom the supply will be attributed to\n * @param mintAmount The amount of the underlying asset to supply\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when minter address is zero\n */\n function mintBehalf(address minter, uint256 mintAmount) external override nonReentrant returns (uint256) {\n ensureNonzeroAddress(minter);\n\n accrueInterest();\n\n _mintFresh(msg.sender, minter, mintAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\n * @custom:access Not restricted\n */\n function redeem(uint256 redeemTokens) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _redeemFresh(msg.sender, msg.sender, redeemTokens, 0);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function redeemBehalf(address redeemer, uint256 redeemTokens) external override nonReentrant returns (uint256) {\n _ensureSenderIsDelegateOf(redeemer);\n\n accrueInterest();\n\n _redeemFresh(redeemer, msg.sender, redeemTokens, 0);\n return NO_ERROR;\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 receive from redeeming vTokens\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n */\n function redeemUnderlying(uint256 redeemAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _redeemFresh(msg.sender, msg.sender, 0, redeemAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function redeemUnderlyingBehalf(\n address redeemer,\n uint256 redeemAmount\n ) external override nonReentrant returns (uint256) {\n _ensureSenderIsDelegateOf(redeemer);\n\n accrueInterest();\n\n _redeemFresh(redeemer, msg.sender, 0, redeemAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Borrow event; may emit AccrueInterest\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\n * @custom:access Not restricted\n */\n function borrow(uint256 borrowAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _borrowFresh(msg.sender, msg.sender, borrowAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:error DelegateNotApproved is thrown if caller is not approved delegate\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\n * @custom:event Emits Borrow event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function borrowBehalf(address borrower, uint256 borrowAmount) external override returns (uint256) {\n _ensureSenderIsDelegateOf(borrower);\n accrueInterest();\n\n _borrowFresh(borrower, msg.sender, borrowAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function repayBorrow(uint256 repayAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _repayBorrowFresh(msg.sender, msg.sender, repayAmount);\n return NO_ERROR;\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, or type(uint256).max for the full outstanding amount\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _repayBorrowFresh(msg.sender, borrower, repayAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\n * @custom:access Not restricted\n */\n function liquidateBorrow(\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) external override returns (uint256) {\n _liquidateBorrow(msg.sender, borrower, repayAmount, vTokenCollateral, false);\n return NO_ERROR;\n }\n\n /**\n * @notice sets protocol share accumulated from liquidations\n * @dev must be equal or less than liquidation incentive - 1\n * @param newProtocolSeizeShareMantissa_ new protocol share mantissa\n * @custom:event Emits NewProtocolSeizeShare event on success\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:error ProtocolSeizeShareTooBig is thrown when the new seize share is too high\n * @custom:access Controlled by AccessControlManager\n */\n function setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa_) external {\n _checkAccessAllowed(\"setProtocolSeizeShare(uint256)\");\n uint256 liquidationIncentive = ComptrollerViewInterface(address(comptroller)).liquidationIncentiveMantissa();\n if (newProtocolSeizeShareMantissa_ + MANTISSA_ONE > liquidationIncentive) {\n revert ProtocolSeizeShareTooBig();\n }\n\n uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\n protocolSeizeShareMantissa = newProtocolSeizeShareMantissa_;\n emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa_);\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 * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\n * @custom:event Emits NewReserveFactor event; may emit AccrueInterest\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:error SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\n * @custom:access Controlled by AccessControlManager\n */\n function setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant {\n _checkAccessAllowed(\"setReserveFactor(uint256)\");\n\n accrueInterest();\n _setReserveFactorFresh(newReserveFactorMantissa);\n }\n\n /**\n * @notice Accrues interest and reduces reserves by transferring to the protocol reserve contract\n * @dev Gracefully return if reserves already reduced in accrueInterest\n * @param reduceAmount Amount of reduction to reserves\n * @custom:event Emits ReservesReduced event; may emit AccrueInterest\n * @custom:error ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash\n * @custom:error ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\n * @custom:access Not restricted\n */\n function reduceReserves(uint256 reduceAmount) external override nonReentrant {\n accrueInterest();\n if (reduceReservesBlockNumber == getBlockNumberOrTimestamp()) return;\n _reduceReservesFresh(reduceAmount);\n }\n\n /**\n * @notice The sender adds to reserves.\n * @param addAmount The amount of underlying token to add as reserves\n * @custom:event Emits ReservesAdded event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function addReserves(uint256 addAmount) external override nonReentrant {\n accrueInterest();\n _addReservesFresh(addAmount);\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 * @custom:event Emits NewMarketInterestRateModel event; may emit AccrueInterest\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:access Controlled by AccessControlManager\n */\n function setInterestRateModel(InterestRateModel newInterestRateModel) external override {\n _checkAccessAllowed(\"setInterestRateModel(address)\");\n\n accrueInterest();\n _setInterestRateModelFresh(newInterestRateModel);\n }\n\n /**\n * @notice Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially\n * \"forgiving\" the borrower. Healing is a situation that should rarely happen. However, some pools\n * may list risky assets or be configured improperly – we want to still handle such cases gracefully.\n * We assume that Comptroller does the seizing, so this function is only available to Comptroller.\n * @dev This function does not call any Comptroller hooks (like \"healAllowed\"), because we assume\n * the Comptroller does all the necessary checks before calling this function.\n * @param payer account who repays the debt\n * @param borrower account to heal\n * @param repayAmount amount to repay\n * @custom:event Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\n * @custom:error HealBorrowUnauthorized is thrown when the request does not come from Comptroller\n * @custom:access Only Comptroller\n */\n function healBorrow(address payer, address borrower, uint256 repayAmount) external override nonReentrant {\n if (repayAmount != 0) {\n comptroller.preRepayHook(address(this), borrower);\n }\n\n if (msg.sender != address(comptroller)) {\n revert HealBorrowUnauthorized();\n }\n\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n uint256 totalBorrowsNew = totalBorrows;\n\n uint256 actualRepayAmount;\n if (repayAmount != 0) {\n // _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\n // We violate checks-effects-interactions here to account for tokens that take transfer fees\n actualRepayAmount = _doTransferIn(payer, repayAmount);\n totalBorrowsNew = totalBorrowsNew - actualRepayAmount;\n emit RepayBorrow(\n payer,\n borrower,\n actualRepayAmount,\n accountBorrowsPrev - actualRepayAmount,\n totalBorrowsNew\n );\n }\n\n // The transaction will fail if trying to repay too much\n uint256 badDebtDelta = accountBorrowsPrev - actualRepayAmount;\n if (badDebtDelta != 0) {\n uint256 badDebtOld = badDebt;\n uint256 badDebtNew = badDebtOld + badDebtDelta;\n totalBorrowsNew = totalBorrowsNew - badDebtDelta;\n badDebt = badDebtNew;\n\n // We treat healing as \"repayment\", where vToken is the payer\n emit RepayBorrow(address(this), borrower, badDebtDelta, 0, totalBorrowsNew);\n emit BadDebtIncreased(borrower, badDebtDelta, badDebtOld, badDebtNew);\n }\n\n accountBorrows[borrower].principal = 0;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n emit HealBorrow(payer, borrower, repayAmount);\n }\n\n /**\n * @notice The extended version of liquidations, callable only by Comptroller. May skip\n * the close factor check. The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\n * @custom:error ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\n * @custom:access Only Comptroller\n */\n function forceLiquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) external override {\n if (msg.sender != address(comptroller)) {\n revert ForceLiquidateBorrowUnauthorized();\n }\n _liquidateBorrow(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\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 * @custom:event Emits Transfer, ReservesAdded events\n * @custom:error LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:access Not restricted\n */\n function seize(address liquidator, address borrower, uint256 seizeTokens) external override nonReentrant {\n _seize(msg.sender, liquidator, borrower, seizeTokens);\n }\n\n /**\n * @notice Updates bad debt\n * @dev Called only when bad debt is recovered from auction. Updates internal cash balance.\n * @param recoveredAmount_ The amount of bad debt recovered\n * @custom:event Emits BadDebtRecovered event\n * @custom:access Only Shortfall contract\n */\n function badDebtRecovered(uint256 recoveredAmount_) external {\n require(msg.sender == shortfall, \"only shortfall contract can update bad debt\");\n require(recoveredAmount_ <= badDebt, \"more than bad debt recovered from auction\");\n\n uint256 badDebtOld = badDebt;\n uint256 badDebtNew = badDebtOld - recoveredAmount_;\n badDebt = badDebtNew;\n internalCash += recoveredAmount_;\n\n emit BadDebtRecovered(badDebtOld, badDebtNew);\n }\n\n /**\n * @notice Sets protocol share reserve contract address\n * @param protocolShareReserve_ The address of the protocol share reserve contract\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\n * @custom:access Only Governance\n */\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\n _setProtocolShareReserve(protocolShareReserve_);\n }\n\n /**\n * @notice Sets shortfall contract address\n * @param shortfall_ The address of the shortfall contract\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\n * @custom:access Only Governance\n */\n function setShortfallContract(address shortfall_) external onlyOwner {\n _setShortfallContract(shortfall_);\n }\n\n /**\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\n * @param token The address of the ERC-20 token to sweep\n * @custom:access Only Governance\n */\n function sweepToken(IERC20Upgradeable token) external override {\n require(msg.sender == owner(), \"VToken::sweepToken: only admin can sweep tokens\");\n require(address(token) != underlying, \"VToken::sweepToken: can not sweep underlying token\");\n uint256 balance = token.balanceOf(address(this));\n token.safeTransfer(owner(), balance);\n\n emit SweepToken(address(token));\n }\n\n /**\n * @notice Sync internalCash with the actual underlying token balance\n * @dev Used for one-time migration after upgrade to initialize internalCash\n * @custom:event Emits CashSynced\n * @custom:access Controlled by AccessControlManager\n */\n function syncCash() external override nonReentrant {\n _checkAccessAllowed(\"syncCash()\");\n uint256 oldInternalCash = internalCash;\n uint256 actualCash = IERC20Upgradeable(underlying).balanceOf(address(this));\n internalCash = actualCash;\n emit CashSynced(oldInternalCash, actualCash);\n }\n\n /**\n * @notice A public function to set new threshold of slot(block or second) difference after which funds will be sent to the protocol share reserve\n * @param _newReduceReservesBlockOrTimestampDelta slot(block or second) difference value\n * @custom:access Only Governance\n */\n function setReduceReservesBlockDelta(uint256 _newReduceReservesBlockOrTimestampDelta) external {\n _checkAccessAllowed(\"setReduceReservesBlockDelta(uint256)\");\n require(_newReduceReservesBlockOrTimestampDelta > 0, \"Invalid Input\");\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, _newReduceReservesBlockOrTimestampDelta);\n reduceReservesBlockDelta = _newReduceReservesBlockOrTimestampDelta;\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 amount 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 amount 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 error Always NO_ERROR for compatibility with Venus core tooling\n * @return vTokenBalance User's balance of vTokens\n * @return borrowBalance Amount owed in terms of underlying\n * @return exchangeRate Stored exchange rate\n */\n function getAccountSnapshot(\n address account\n )\n external\n view\n override\n returns (uint256 error, uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRate)\n {\n return (NO_ERROR, accountTokens[account], _borrowBalanceStored(account), _exchangeRateStored());\n }\n\n /**\n * @notice Get the internally tracked cash balance of this vToken in the underlying asset\n * @return cash The quantity of underlying asset tracked internally by this contract\n */\n function getCash() external view override returns (uint256) {\n return _getCashPrior();\n }\n\n /**\n * @notice Returns the current per slot(block or second) borrow interest rate for this vToken\n * @return rate The borrow interest rate per slot(block or second), scaled by 1e18\n */\n function borrowRatePerBlock() external view override returns (uint256) {\n return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt);\n }\n\n /**\n * @notice Returns the current per-slot(block or second) supply interest rate for this v\n * @return rate The supply interest rate per slot(block or second), scaled by 1e18\n */\n function supplyRatePerBlock() external view override returns (uint256) {\n return\n interestRateModel.getSupplyRate(\n _getCashPrior(),\n totalBorrows,\n totalReserves,\n reserveFactorMantissa,\n badDebt\n );\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 borrowBalance The calculated balance\n */\n function borrowBalanceStored(address account) external view override returns (uint256) {\n return _borrowBalanceStored(account);\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 exchangeRate Calculated exchange rate scaled by 1e18\n */\n function exchangeRateStored() external view override returns (uint256) {\n return _exchangeRateStored();\n }\n\n /**\n * @notice Accrue interest then return the up-to-date exchange rate\n * @return exchangeRate Calculated exchange rate scaled by 1e18\n */\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\n accrueInterest();\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 slot(block or second)\n * up to the current slot(block or second) and writes new checkpoint to storage and\n * reduce spread reserves to protocol share reserve\n * if currentSlot - reduceReservesBlockNumber >= slotDelta\n * @return Always NO_ERROR\n * @custom:event Emits AccrueInterest event on success\n * @custom:access Not restricted\n */\n function accrueInterest() public virtual override returns (uint256) {\n /* Remember the initial block number or timestamp */\n uint256 currentSlotNumber = getBlockNumberOrTimestamp();\n uint256 accrualSlotNumberPrior = accrualBlockNumber;\n\n /* Short-circuit accumulating 0 interest */\n if (accrualSlotNumberPrior == currentSlotNumber) {\n return NO_ERROR;\n }\n\n /* Read the previous values out of storage */\n uint256 cashPrior = _getCashPrior();\n uint256 borrowsPrior = totalBorrows;\n uint256 reservesPrior = totalReserves;\n uint256 borrowIndexPrior = borrowIndex;\n\n /* Calculate the current borrow interest rate */\n uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt);\n require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, \"borrow rate is absurdly high\");\n\n /* Calculate the number of slots elapsed since the last accrual */\n uint256 slotDelta = currentSlotNumber - accrualSlotNumberPrior;\n\n /*\n * Calculate the interest accumulated into borrows and reserves and the new index:\n * simpleInterestFactor = borrowRate * slotDelta\n * interestAccumulated = simpleInterestFactor * totalBorrows\n * totalBorrowsNew = interestAccumulated + totalBorrows\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\n */\n\n Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), slotDelta);\n uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\n uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;\n uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\n Exp({ mantissa: reserveFactorMantissa }),\n interestAccumulated,\n reservesPrior\n );\n uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the previously calculated values into storage */\n accrualBlockNumber = currentSlotNumber;\n borrowIndex = borrowIndexNew;\n totalBorrows = totalBorrowsNew;\n totalReserves = totalReservesNew;\n\n if (currentSlotNumber - reduceReservesBlockNumber >= reduceReservesBlockDelta) {\n reduceReservesBlockNumber = currentSlotNumber;\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 NO_ERROR;\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 or timestamp\n * @param payer The address of the account which is sending the assets for supply\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 */\n function _mintFresh(address payer, address minter, uint256 mintAmount) internal {\n /* Fail if mint not allowed */\n comptroller.preMintHook(address(this), minter, mintAmount);\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert MintFreshnessCheck();\n }\n\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\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 * `_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 uint256 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 uint256 mintTokens = div_(actualMintAmount, exchangeRate);\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 * And write them into storage\n */\n totalSupply = totalSupply + mintTokens;\n uint256 balanceAfter = accountTokens[minter] + mintTokens;\n accountTokens[minter] = balanceAfter;\n\n /* We emit a Mint event, and a Transfer event */\n emit Mint(minter, actualMintAmount, mintTokens, balanceAfter);\n emit Transfer(address(0), minter, mintTokens);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.mintVerify(address(this), minter, actualMintAmount, mintTokens);\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 Comptroller.updateDelegate)\n * @dev Assumes interest has already been accrued up to the current slot(block or second)\n * @param redeemer The address of the account which is redeeming the tokens\n * @param receiver The receiver of the underlying 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 */\n function _redeemFresh(address redeemer, address receiver, uint256 redeemTokensIn, uint256 redeemAmountIn) internal {\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \"one of redeemTokensIn or redeemAmountIn must be zero\");\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert RedeemFreshnessCheck();\n }\n\n /* exchangeRate = invoke Exchange Rate Stored() */\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\n\n uint256 redeemTokens;\n uint256 redeemAmount;\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 */\n redeemTokens = redeemTokensIn;\n } else {\n /*\n * We get the current exchange rate and calculate the amount to be redeemed:\n * redeemTokens = redeemAmountIn / exchangeRate\n */\n redeemTokens = div_(redeemAmountIn, exchangeRate);\n\n uint256 _redeemAmount = mul_(redeemTokens, exchangeRate);\n if (_redeemAmount != 0 && _redeemAmount != redeemAmountIn) redeemTokens++; // round up\n }\n\n // redeemAmount = exchangeRate * redeemTokens\n redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokens);\n\n // Revert if amount is zero\n if (redeemAmount == 0) {\n revert(\"redeemAmount is zero\");\n }\n\n /* Fail if redeem not allowed */\n comptroller.preRedeemHook(address(this), redeemer, redeemTokens);\n\n /* Fail gracefully if protocol has insufficient cash */\n if (_getCashPrior() - totalReserves < redeemAmount) {\n revert RedeemTransferOutNotPossible();\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We write the previously calculated values into storage.\n * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\n */\n totalSupply = totalSupply - redeemTokens;\n uint256 balanceAfter = accountTokens[redeemer] - redeemTokens;\n accountTokens[redeemer] = balanceAfter;\n\n /*\n * We invoke _doTransferOut for the receiver and the redeemAmount.\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 _doTransferOut(receiver, redeemAmount);\n\n /* We emit a Transfer event, and a Redeem event */\n emit Transfer(redeemer, address(this), redeemTokens);\n emit Redeem(redeemer, redeemAmount, redeemTokens, balanceAfter);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.redeemVerify(address(this), redeemer, redeemAmount, redeemTokens);\n }\n\n /**\n * @notice Users or their delegates borrow assets from the protocol\n * @param borrower User who borrows the assets\n * @param receiver The receiver of the tokens, if called by a delegate\n * @param borrowAmount The amount of the underlying asset to borrow\n */\n function _borrowFresh(address borrower, address receiver, uint256 borrowAmount) internal {\n /* Fail if borrow not allowed */\n comptroller.preBorrowHook(address(this), borrower, borrowAmount);\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert BorrowFreshnessCheck();\n }\n\n /* Fail gracefully if protocol has insufficient underlying cash */\n if (_getCashPrior() - totalReserves < borrowAmount) {\n revert BorrowCashNotAvailable();\n }\n\n /*\n * We calculate the new borrower and total borrow balances, failing on overflow:\n * accountBorrowNew = accountBorrow + borrowAmount\n * totalBorrowsNew = totalBorrows + borrowAmount\n */\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;\n uint256 totalBorrowsNew = totalBorrows + borrowAmount;\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We write the previously calculated values into storage.\n * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\n `*/\n accountBorrows[borrower].principal = accountBorrowsNew;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n /*\n * We invoke _doTransferOut for the receiver and the borrowAmount.\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, accountBorrowsNew, totalBorrowsNew);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\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 underlying tokens being returned, or type(uint256).max for the full outstanding amount\n * @return (uint) the actual repayment amount.\n */\n function _repayBorrowFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256) {\n /* Fail if repayBorrow not allowed */\n comptroller.preRepayHook(address(this), borrower);\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert RepayBorrowFreshnessCheck();\n }\n\n /* We fetch the amount the borrower owes, with accumulated interest */\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n\n uint256 repayAmountFinal = repayAmount >= accountBorrowsPrev ? accountBorrowsPrev : 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 * 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 uint256 actualRepayAmount = _doTransferIn(payer, repayAmountFinal);\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 uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\n uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;\n\n /* We write the previously calculated values into storage */\n accountBorrows[borrower].principal = accountBorrowsNew;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n /* We emit a RepayBorrow event */\n emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.repayBorrowVerify(address(this), payer, borrower, actualRepayAmount, borrowIndex);\n\n return actualRepayAmount;\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n */\n function _liquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) internal nonReentrant {\n accrueInterest();\n\n uint256 error = vTokenCollateral.accrueInterest();\n if (error != NO_ERROR) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\n revert LiquidateAccrueCollateralInterestFailed(error);\n }\n\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\n }\n\n /**\n * @notice The liquidator liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n */\n function _liquidateBorrowFresh(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) internal {\n /* Fail if liquidate not allowed */\n comptroller.preLiquidateHook(\n address(this),\n address(vTokenCollateral),\n borrower,\n repayAmount,\n skipLiquidityCheck\n );\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert LiquidateFreshnessCheck();\n }\n\n /* Verify vTokenCollateral market's slot(block or second) number equals current slot(block or second) number */\n if (vTokenCollateral.accrualBlockNumber() != getBlockNumberOrTimestamp()) {\n revert LiquidateCollateralFreshnessCheck();\n }\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n revert LiquidateLiquidatorIsBorrower();\n }\n\n /* Fail if repayAmount = 0 */\n if (repayAmount == 0) {\n revert LiquidateCloseAmountIsZero();\n }\n\n /* Fail if repayAmount = type(uint256).max */\n if (repayAmount == type(uint256).max) {\n revert LiquidateCloseAmountIsUintMax();\n }\n\n /* Fail if repayBorrow fails */\n uint256 actualRepayAmount = _repayBorrowFresh(liquidator, borrower, repayAmount);\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.liquidateCalculateSeizeTokens(\n address(this),\n address(vTokenCollateral),\n actualRepayAmount\n );\n require(amountSeizeError == 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, call _seize internally to avoid re-entrancy, otherwise make an external call\n if (address(vTokenCollateral) == address(this)) {\n _seize(address(this), liquidator, borrower, seizeTokens);\n } else {\n vTokenCollateral.seize(liquidator, borrower, seizeTokens);\n }\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\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 * It's absolutely critical to use msg.sender as the seizer vToken and not a parameter.\n * @param seizerContract The contract seizing the collateral (either borrowed vToken or Comptroller)\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 */\n function _seize(address seizerContract, address liquidator, address borrower, uint256 seizeTokens) internal {\n /* Fail if seize not allowed */\n comptroller.preSeizeHook(address(this), seizerContract, liquidator, borrower);\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n revert LiquidateSeizeLiquidatorIsBorrower();\n }\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 uint256 liquidationIncentiveMantissa = ComptrollerViewInterface(address(comptroller))\n .liquidationIncentiveMantissa();\n uint256 numerator = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));\n uint256 protocolSeizeTokens = div_(numerator, Exp({ mantissa: liquidationIncentiveMantissa }));\n uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\n uint256 protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the calculated values into storage */\n totalSupply = totalSupply - protocolSeizeTokens;\n accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\n accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\n\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\n _doTransferOut(protocolShareReserve, protocolSeizeAmount);\n\n // Update the pool asset's state in the protocol share reserve for the above transfer.\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\n address(comptroller),\n underlying,\n IProtocolShareReserve.IncomeType.LIQUIDATION\n );\n\n /* Emit a Transfer event */\n emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\n emit ProtocolSeize(borrower, protocolShareReserve, protocolSeizeAmount);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.seizeVerify(address(this), seizerContract, liquidator, borrower, seizeTokens);\n }\n\n function _setComptroller(ComptrollerInterface newComptroller) internal {\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\n /**\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\n * @dev Admin function to set a new reserve factor\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\n */\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal {\n // Verify market's slot(block or second) number equals current slot(block or second) number\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert SetReserveFactorFreshCheck();\n }\n\n // Check newReserveFactor ≤ maxReserveFactor\n if (newReserveFactorMantissa > MAX_RESERVE_FACTOR_MANTISSA) {\n revert SetReserveFactorBoundsCheck();\n }\n\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\n reserveFactorMantissa = newReserveFactorMantissa;\n\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\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 actualAddAmount The actual amount added, excluding the potential token fees\n */\n function _addReservesFresh(uint256 addAmount) internal returns (uint256) {\n // totalReserves + actualAddAmount\n uint256 totalReservesNew;\n uint256 actualAddAmount;\n\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert AddReservesFactorFreshCheck(actualAddAmount);\n }\n\n actualAddAmount = _doTransferIn(msg.sender, addAmount);\n totalReservesNew = totalReserves + actualAddAmount;\n totalReserves = totalReservesNew;\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\n\n return actualAddAmount;\n }\n\n /**\n * @notice Reduces reserves by transferring to the protocol reserve contract\n * @dev Requires fresh interest accrual\n * @param reduceAmount Amount of reduction to reserves\n */\n function _reduceReservesFresh(uint256 reduceAmount) internal {\n if (reduceAmount == 0) {\n return;\n }\n // totalReserves - reduceAmount\n uint256 totalReservesNew;\n\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert ReduceReservesFreshCheck();\n }\n\n // Fail gracefully if protocol has insufficient underlying cash\n if (_getCashPrior() < reduceAmount) {\n revert ReduceReservesCashNotAvailable();\n }\n\n // Check reduceAmount ≤ reserves[n] (totalReserves)\n if (reduceAmount > totalReserves) {\n revert ReduceReservesCashValidation();\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 // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\n _doTransferOut(protocolShareReserve, reduceAmount);\n\n // Update the pool asset's state in the protocol share reserve for the above transfer.\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\n address(comptroller),\n underlying,\n IProtocolShareReserve.IncomeType.SPREAD\n );\n\n emit SpreadReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\n }\n\n /**\n * @notice updates the interest rate model (*requires fresh interest accrual)\n * @dev Admin function to update the interest rate model\n * @param newInterestRateModel the new interest rate model to use\n */\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal {\n // Used to store old model for use in the event that is emitted on success\n InterestRateModel oldInterestRateModel;\n\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert SetInterestRateModelFreshCheck();\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\n /**\n * Safe Token **\n */\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 returns (uint256) {\n IERC20Upgradeable token = IERC20Upgradeable(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 * @param to Receiver of the underlying tokens\n * @param amount Amount of underlying to transfer\n */\n function _doTransferOut(address to, uint256 amount) internal virtual {\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\n internalCash -= amount;\n token.safeTransfer(to, amount);\n }\n\n /**\n * @notice Transfer `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 */\n function _transferTokens(address spender, address src, address dst, uint256 tokens) internal {\n /* Fail if transfer not allowed */\n comptroller.preTransferHook(address(this), src, dst, tokens);\n\n /* Do not allow self-transfers */\n if (src == dst) {\n revert TransferNotAllowed();\n }\n\n /* Get the allowance, infinite for the account owner */\n uint256 startingAllowance;\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 uint256 allowanceNew = startingAllowance - tokens;\n uint256 srcTokensNew = accountTokens[src] - tokens;\n uint256 dstTokensNew = accountTokens[dst] + tokens;\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n\n accountTokens[src] = srcTokensNew;\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\n /**\n * @notice Initialize the 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_ ERC-20 name of this token\n * @param symbol_ ERC-20 symbol of this token\n * @param decimals_ ERC-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param accessControlManager_ AccessControlManager contract address\n * @param riskManagement Addresses of risk & income related contracts\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\n */\n function _initialize(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address admin_,\n address accessControlManager_,\n RiskManagementInit memory riskManagement,\n uint256 reserveFactorMantissa_\n ) internal onlyInitializing {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\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 _setComptroller(comptroller_);\n\n // Initialize slot(block or second) number and borrow index (slot(block or second) number mocks depend on comptroller being set)\n accrualBlockNumber = getBlockNumberOrTimestamp();\n borrowIndex = MANTISSA_ONE;\n\n // Set the interest rate model (depends on slot(block or second) number / borrow index)\n _setInterestRateModelFresh(interestRateModel_);\n\n _setReserveFactorFresh(reserveFactorMantissa_);\n\n name = name_;\n symbol = symbol_;\n decimals = decimals_;\n _setShortfallContract(riskManagement.shortfall);\n _setProtocolShareReserve(riskManagement.protocolShareReserve);\n protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA;\n\n // Set underlying and sanity check it\n underlying = underlying_;\n IERC20Upgradeable(underlying).totalSupply();\n\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\n _notEntered = true;\n _transferOwnership(admin_);\n }\n\n function _setShortfallContract(address shortfall_) internal {\n ensureNonzeroAddress(shortfall_);\n address oldShortfall = shortfall;\n shortfall = shortfall_;\n emit NewShortfallContract(oldShortfall, shortfall_);\n }\n\n function _setProtocolShareReserve(address payable protocolShareReserve_) internal {\n ensureNonzeroAddress(protocolShareReserve_);\n address oldProtocolShareReserve = address(protocolShareReserve);\n protocolShareReserve = protocolShareReserve_;\n emit NewProtocolShareReserve(oldProtocolShareReserve, address(protocolShareReserve_));\n }\n\n function _ensureSenderIsDelegateOf(address user) internal view {\n if (!ComptrollerViewInterface(address(comptroller)).approvedDelegates(user, msg.sender)) {\n revert DelegateNotApproved();\n }\n }\n\n /**\n * @notice Gets the internally tracked cash balance of this market\n * @dev Returns the internalCash state variable, which is updated on transfers in/out\n * @return The quantity of underlying tokens tracked internally by this contract\n */\n function _getCashPrior() internal view virtual returns (uint256) {\n return internalCash;\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 borrowBalance the calculated balance\n */\n function _borrowBalanceStored(address account) internal view returns (uint256) {\n /* Get borrowBalance and borrowIndex */\n BorrowSnapshot memory 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 0;\n }\n\n /* Calculate new borrow balance using the interest index:\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\n */\n uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;\n\n return principalTimesIndex / borrowSnapshot.interestIndex;\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 exchangeRate Calculated exchange rate scaled by 1e18\n */\n function _exchangeRateStored() internal view virtual returns (uint256) {\n uint256 _totalSupply = totalSupply;\n if (_totalSupply == 0) {\n /*\n * If there are no tokens minted:\n * exchangeRate = initialExchangeRate\n */\n return initialExchangeRateMantissa;\n }\n /*\n * Otherwise:\n * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply\n */\n uint256 totalCash = _getCashPrior();\n uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;\n uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply;\n\n return exchangeRate;\n }\n}\n" + }, + "contracts/VTokenInterfaces.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\nimport { ComptrollerInterface } from \"./ComptrollerInterface.sol\";\nimport { InterestRateModel } from \"./InterestRateModel.sol\";\n\n/**\n * @title VTokenStorage\n * @author Venus\n * @notice Storage layout used by the `VToken` contract\n */\n// solhint-disable-next-line max-states-count\ncontract VTokenStorage {\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 uint256 principal;\n uint256 interestIndex;\n }\n\n /**\n * @dev Guard variable for re-entrancy checks\n */\n bool internal _notEntered;\n\n /**\n * @notice Underlying asset for this VToken\n */\n address public underlying;\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 Protocol share Reserve contract address\n */\n address payable public protocolShareReserve;\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 InterestRateModel public interestRateModel;\n\n // Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\n uint256 internal initialExchangeRateMantissa;\n\n /**\n * @notice Fraction of interest currently set aside for reserves\n */\n uint256 public reserveFactorMantissa;\n\n /**\n * @notice Slot(block or second) number that interest was last accrued at\n */\n uint256 public accrualBlockNumber;\n\n /**\n * @notice Accumulator of the total earned interest rate since the opening of the market\n */\n uint256 public borrowIndex;\n\n /**\n * @notice Total amount of outstanding borrows of the underlying in this market\n */\n uint256 public totalBorrows;\n\n /**\n * @notice Total amount of reserves of the underlying held in this market\n */\n uint256 public totalReserves;\n\n /**\n * @notice Total number of tokens in circulation\n */\n uint256 public totalSupply;\n\n /**\n * @notice Total bad debt of the market\n */\n uint256 public badDebt;\n\n // Official record of token balances for each account\n mapping(address => uint256) internal accountTokens;\n\n // Approved token transfer amounts on behalf of others\n mapping(address => mapping(address => uint256)) internal transferAllowances;\n\n // Mapping of account addresses to outstanding borrow balances\n mapping(address => BorrowSnapshot) internal accountBorrows;\n\n /**\n * @notice Share of seized collateral that is added to reserves\n */\n uint256 public protocolSeizeShareMantissa;\n\n /**\n * @notice Storage of Shortfall contract address\n */\n address public shortfall;\n\n /**\n * @notice delta slot (block or second) after which reserves will be reduced\n */\n uint256 public reduceReservesBlockDelta;\n\n /**\n * @notice last slot (block or second) number at which reserves were reduced\n */\n uint256 public reduceReservesBlockNumber;\n\n /**\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\n * @dev Updated via _doTransferIn(), _doTransferOut(), syncCash(), and badDebtRecovered(). Must be initialized via syncCash() 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[47] private __gap;\n}\n\n/**\n * @title VTokenInterface\n * @author Venus\n * @notice Interface implemented by the `VToken` contract\n */\nabstract contract VTokenInterface is VTokenStorage {\n struct RiskManagementInit {\n address shortfall;\n address payable protocolShareReserve;\n }\n\n /*** Market Events ***/\n\n /**\n * @notice Event emitted when interest is accrued\n */\n event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\n\n /**\n * @notice Event emitted when tokens are minted\n */\n event Mint(address indexed minter, uint256 mintAmount, uint256 mintTokens, uint256 accountBalance);\n\n /**\n * @notice Event emitted when tokens are redeemed\n */\n event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens, uint256 accountBalance);\n\n /**\n * @notice Event emitted when underlying is borrowed\n */\n event Borrow(address indexed borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\n\n /**\n * @notice Event emitted when a borrow is repaid\n */\n event RepayBorrow(\n address indexed payer,\n address indexed borrower,\n uint256 repayAmount,\n uint256 accountBorrows,\n uint256 totalBorrows\n );\n\n /**\n * @notice Event emitted when bad debt is accumulated on a market\n * @param borrower borrower to \"forgive\"\n * @param badDebtDelta amount of new bad debt recorded\n * @param badDebtOld previous bad debt value\n * @param badDebtNew new bad debt value\n */\n event BadDebtIncreased(address indexed borrower, uint256 badDebtDelta, uint256 badDebtOld, uint256 badDebtNew);\n\n /**\n * @notice Event emitted when bad debt is recovered via an auction\n * @param badDebtOld previous bad debt value\n * @param badDebtNew new bad debt value\n */\n event BadDebtRecovered(uint256 badDebtOld, uint256 badDebtNew);\n\n /**\n * @notice Event emitted when a borrow is liquidated\n */\n event LiquidateBorrow(\n address indexed liquidator,\n address indexed borrower,\n uint256 repayAmount,\n address indexed vTokenCollateral,\n uint256 seizeTokens\n );\n\n /*** Admin Events ***/\n\n /**\n * @notice Event emitted when comptroller is changed\n */\n event NewComptroller(ComptrollerInterface indexed oldComptroller, ComptrollerInterface indexed newComptroller);\n\n /**\n * @notice Event emitted when shortfall contract address is changed\n */\n event NewShortfallContract(address indexed oldShortfall, address indexed newShortfall);\n\n /**\n * @notice Event emitted when protocol share reserve contract address is changed\n */\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\n\n /**\n * @notice Event emitted when interestRateModel is changed\n */\n event NewMarketInterestRateModel(\n InterestRateModel indexed oldInterestRateModel,\n InterestRateModel indexed newInterestRateModel\n );\n\n /**\n * @notice Event emitted when protocol seize share is changed\n */\n event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\n\n /**\n * @notice Event emitted when the reserve factor is changed\n */\n event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\n\n /**\n * @notice Event emitted when the reserves are added\n */\n event ReservesAdded(address indexed benefactor, uint256 addAmount, uint256 newTotalReserves);\n\n /**\n * @notice Event emitted when the spread reserves are reduced\n */\n event SpreadReservesReduced(address indexed protocolShareReserve, uint256 reduceAmount, uint256 newTotalReserves);\n\n /**\n * @notice EIP20 Transfer event\n */\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n /**\n * @notice EIP20 Approval event\n */\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /**\n * @notice Event emitted when healing the borrow\n */\n event HealBorrow(address indexed payer, address indexed borrower, uint256 repayAmount);\n\n /**\n * @notice Event emitted when tokens are swept\n */\n event SweepToken(address indexed token);\n\n /**\n * @notice Event emitted when reduce reserves slot (block or second) delta is changed\n */\n event NewReduceReservesBlockDelta(\n uint256 oldReduceReservesBlockOrTimestampDelta,\n uint256 newReduceReservesBlockOrTimestampDelta\n );\n\n /**\n * @notice Event emitted when liquidation reserves are reduced\n */\n event ProtocolSeize(address indexed from, address indexed to, uint256 amount);\n\n /**\n * @notice Event emitted when internalCash is synced with actual token balance\n */\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\n\n /*** User Interface ***/\n\n function mint(uint256 mintAmount) external virtual returns (uint256);\n\n function mintBehalf(address minter, uint256 mintAllowed) external virtual returns (uint256);\n\n function redeem(uint256 redeemTokens) external virtual returns (uint256);\n\n function redeemBehalf(address redeemer, uint256 redeemTokens) external virtual returns (uint256);\n\n function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);\n\n function redeemUnderlyingBehalf(address redeemer, uint256 redeemAmount) external virtual returns (uint256);\n\n function borrow(uint256 borrowAmount) external virtual returns (uint256);\n\n function borrowBehalf(address borrwwer, uint256 borrowAmount) external virtual returns (uint256);\n\n function repayBorrow(uint256 repayAmount) external virtual returns (uint256);\n\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);\n\n function liquidateBorrow(\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) external virtual returns (uint256);\n\n function healBorrow(address payer, address borrower, uint256 repayAmount) external virtual;\n\n function forceLiquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipCloseFactorCheck\n ) external virtual;\n\n function seize(address liquidator, address borrower, uint256 seizeTokens) external virtual;\n\n function transfer(address dst, uint256 amount) external virtual returns (bool);\n\n function transferFrom(address src, address dst, uint256 amount) external virtual returns (bool);\n\n function accrueInterest() external virtual returns (uint256);\n\n function sweepToken(IERC20Upgradeable token) external virtual;\n\n /*** Admin Functions ***/\n\n function setReserveFactor(uint256 newReserveFactorMantissa) external virtual;\n\n function reduceReserves(uint256 reduceAmount) external virtual;\n\n function exchangeRateCurrent() external virtual returns (uint256);\n\n function borrowBalanceCurrent(address account) external virtual returns (uint256);\n\n function setInterestRateModel(InterestRateModel newInterestRateModel) external virtual;\n\n function addReserves(uint256 addAmount) external virtual;\n\n function syncCash() external virtual;\n\n function totalBorrowsCurrent() external virtual returns (uint256);\n\n function balanceOfUnderlying(address owner) external virtual returns (uint256);\n\n function approve(address spender, uint256 amount) external virtual returns (bool);\n\n function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool);\n\n function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool);\n\n function allowance(address owner, address spender) external view virtual returns (uint256);\n\n function balanceOf(address owner) external view virtual returns (uint256);\n\n function getAccountSnapshot(address account) external view virtual returns (uint256, uint256, uint256, uint256);\n\n function borrowRatePerBlock() external view virtual returns (uint256);\n\n function supplyRatePerBlock() external view virtual returns (uint256);\n\n function borrowBalanceStored(address account) external view virtual returns (uint256);\n\n function exchangeRateStored() external view virtual returns (uint256);\n\n function getCash() external view virtual returns (uint256);\n\n /**\n * @notice Indicator that this is a VToken contract (for inspection)\n * @return Always true\n */\n function isVToken() external pure virtual returns (bool) {\n return true;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200, + "details": { + "yul": true + } + }, + "evmVersion": "paris", + "outputSelection": { + "*": { + "*": [ + "storageLayout", + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} diff --git a/deployments/ethereum_addresses.json b/deployments/ethereum_addresses.json index 925544c09..452946fa5 100644 --- a/deployments/ethereum_addresses.json +++ b/deployments/ethereum_addresses.json @@ -41,7 +41,7 @@ "JumpRateModel_base0bps_slope1000bps_jump25000bps_kink8000bps_bpy2628000": "0xd7fbFD2A36b8b388E6d04C7a05956Df91862E146", "NativeTokenGateway_vWETH_Core": "0x044dd75b9E043ACFD2d6EB56b6BB814df2a9c809", "NativeTokenGateway_vWETH_LiquidStakedETH": "0xBC1471308eb2287eBE137420Eb1664A964895D21", - "PoolLens": "0x277950603178BDD223eB53B9b7cF5D0053aa3473", + "PoolLens": "0x3716C24EA86A67cAf890d7C9e4C4505cDDC2F8A2", "PoolRegistry": "0x61CAff113CCaf05FFc6540302c37adcf077C5179", "PoolRegistry_Implementation": "0x08A2577611Ae63d1ba40188035eD6Ad21F8502A9", "PoolRegistry_Proxy": "0x61CAff113CCaf05FFc6540302c37adcf077C5179", diff --git a/deployments/opbnbmainnet.json b/deployments/opbnbmainnet.json index 3e13d2da4..ed5c93066 100644 --- a/deployments/opbnbmainnet.json +++ b/deployments/opbnbmainnet.json @@ -8424,7 +8424,7 @@ ] }, "PoolLens": { - "address": "0xA21E48d143818aB0b5231542A486609dFcc20Ee8", + "address": "0x3367FFCcbB15f00635a00b2B4B234f4c3966C9d4", "abi": [ { "inputs": [ @@ -8437,6 +8437,11 @@ "internalType": "uint256", "name": "blocksPerYear_", "type": "uint256" + }, + { + "internalType": "address", + "name": "corePoolComptroller_", + "type": "address" } ], "stateMutability": "nonpayable", @@ -8465,6 +8470,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "corePoolComptroller", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { diff --git a/deployments/opbnbmainnet/PoolLens.json b/deployments/opbnbmainnet/PoolLens.json index d2fa67ff4..90f2db502 100644 --- a/deployments/opbnbmainnet/PoolLens.json +++ b/deployments/opbnbmainnet/PoolLens.json @@ -1,5 +1,5 @@ { - "address": "0xA21E48d143818aB0b5231542A486609dFcc20Ee8", + "address": "0x3367FFCcbB15f00635a00b2B4B234f4c3966C9d4", "abi": [ { "inputs": [ @@ -12,6 +12,11 @@ "internalType": "uint256", "name": "blocksPerYear_", "type": "uint256" + }, + { + "internalType": "address", + "name": "corePoolComptroller_", + "type": "address" } ], "stateMutability": "nonpayable", @@ -40,6 +45,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "corePoolComptroller", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -1168,28 +1186,28 @@ "type": "function" } ], - "transactionHash": "0xfcded4151290e3528c17977627e39c47c4113fddba481a2fe33faa40e7d841cd", + "transactionHash": "0x2203ccce2d67685e0a9ecf4b011318cf70d0f49dcbcf0ab636c3b5d5bf03b364", "receipt": { "to": null, - "from": "0x2e75bCC2d3b742c582Bf502Ee02eE966b29A3238", - "contractAddress": "0xA21E48d143818aB0b5231542A486609dFcc20Ee8", - "transactionIndex": 1, - "gasUsed": "3548913", + "from": "0x8A584E48Cfd2274dE0e861Ec08D3a000435F71fc", + "contractAddress": "0x3367FFCcbB15f00635a00b2B4B234f4c3966C9d4", + "transactionIndex": 6, + "gasUsed": "3593167", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x46da308f0204b07fb60ab2127ff3d42452415f74f0094d1ee47d58bcd799fd65", - "transactionHash": "0xfcded4151290e3528c17977627e39c47c4113fddba481a2fe33faa40e7d841cd", + "blockHash": "0x7f30002e3f3d1aee7f75d469f4656c3f7003579f59e1b7ee36887f940a3d0ce6", + "transactionHash": "0x2203ccce2d67685e0a9ecf4b011318cf70d0f49dcbcf0ab636c3b5d5bf03b364", "logs": [], - "blockNumber": 88770104, - "cumulativeGasUsed": "3592764", + "blockNumber": 127379479, + "cumulativeGasUsed": "3864293", "status": 1, "byzantium": true }, - "args": [false, 126144000], - "numDeployments": 1, - "solcInputHash": "24e26f90177591fc3322952340f1c287", - "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"timeBased_\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"blocksPerYear_\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidBlocksPerYear\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTimeBasedConfiguration\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"blocksOrSecondsPerYear\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"}],\"name\":\"getAllPools\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockNumberOrTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getPendingRewards\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"distributorAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"rewardTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalRewards\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.PendingReward[]\",\"name\":\"pendingRewards\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.RewardSummary[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getPoolBadDebt\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalBadDebtUsd\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"badDebtUsd\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.BadDebt[]\",\"name\":\"badDebts\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.BadDebtSummary\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolByComptroller\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolRegistryInterface.VenusPool\",\"name\":\"venusPool\",\"type\":\"tuple\"}],\"name\":\"getPoolDataFromVenusPool\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getPoolsSupportedByAsset\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getVTokenForAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isTimeBased\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"vTokenBalances\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalanceCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balanceOfUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenAllowance\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenBalances\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"vTokenBalancesAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalanceCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balanceOfUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenAllowance\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenBalances[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"vTokenMetadata\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"vTokenMetadataAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"vTokenUnderlyingPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"underlyingPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenUnderlyingPrice\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"vTokenUnderlyingPriceAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"underlyingPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenUnderlyingPrice[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"params\":{\"blocksPerYear_\":\"The number of blocks per year\",\"timeBased_\":\"A boolean indicating whether the contract is based on time or block.\"}},\"getAllPools(address)\":{\"details\":\"This function is not designed to be called in a transaction: it is too gas-intensive\",\"params\":{\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"Arrays of all Venus pools' data\"}},\"getBlockNumberOrTimestamp()\":{\"details\":\"Function to simply retrieve block number or block timestamp\",\"returns\":{\"_0\":\"Current block number or block timestamp\"}},\"getPendingRewards(address,address)\":{\"params\":{\"account\":\"The user account.\",\"comptrollerAddress\":\"address\"},\"returns\":{\"_0\":\"Pending rewards array\"}},\"getPoolBadDebt(address)\":{\"params\":{\"comptrollerAddress\":\"Address of the comptroller\"},\"returns\":{\"_0\":\"badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and a break down of bad debt by market\"}},\"getPoolByComptroller(address,address)\":{\"params\":{\"comptroller\":\"The Comptroller implementation address\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"PoolData structure containing the details of the pool\"}},\"getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))\":{\"params\":{\"poolRegistryAddress\":\"Address of the PoolRegistry\",\"venusPool\":\"The VenusPool Object from PoolRegistry\"},\"returns\":{\"_0\":\"Enriched PoolData\"}},\"getPoolsSupportedByAsset(address,address)\":{\"params\":{\"asset\":\"The underlying asset of vToken\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"A list of Comptroller contracts\"}},\"getVTokenForAsset(address,address,address)\":{\"params\":{\"asset\":\"The underlyingAsset of VToken\",\"comptroller\":\"The pool comptroller\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"Address of the vToken\"}},\"vTokenBalances(address,address)\":{\"params\":{\"account\":\"The user Account\",\"vToken\":\"vToken address\"},\"returns\":{\"_0\":\"A struct containing the balances data\"}},\"vTokenBalancesAll(address[],address)\":{\"params\":{\"account\":\"The user Account\",\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"A list of structs containing balances data\"}},\"vTokenMetadata(address)\":{\"params\":{\"vToken\":\"The address of vToken\"},\"returns\":{\"_0\":\"VTokenMetadata struct\"}},\"vTokenMetadataAll(address[])\":{\"params\":{\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"An array of VTokenMetadata structs\"}},\"vTokenUnderlyingPrice(address)\":{\"params\":{\"vToken\":\"vToken address\"},\"returns\":{\"_0\":\"The price data for each asset\"}},\"vTokenUnderlyingPriceAll(address[])\":{\"params\":{\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"An array containing the price data for each asset\"}}},\"title\":\"PoolLens\",\"version\":1},\"userdoc\":{\"errors\":{\"InvalidBlocksPerYear()\":[{\"notice\":\"Thrown when blocks per year is invalid\"}],\"InvalidTimeBasedConfiguration()\":[{\"notice\":\"Thrown when time based but blocks per year is provided\"}]},\"kind\":\"user\",\"methods\":{\"blocksOrSecondsPerYear()\":{\"notice\":\"Stores blocksPerYear if isTimeBased is true else secondsPerYear is stored\"},\"getAllPools(address)\":{\"notice\":\"Queries all pools with addtional details for each of them\"},\"getPendingRewards(address,address)\":{\"notice\":\"Returns the pending rewards for a user for a given pool.\"},\"getPoolBadDebt(address)\":{\"notice\":\"Returns a summary of a pool's bad debt broken down by market\"},\"getPoolByComptroller(address,address)\":{\"notice\":\"Queries the details of a pool identified by Comptroller address\"},\"getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))\":{\"notice\":\"Queries additional information for the pool\"},\"getPoolsSupportedByAsset(address,address)\":{\"notice\":\"Returns all pools that support the specified underlying asset\"},\"getVTokenForAsset(address,address,address)\":{\"notice\":\"Returns vToken holding the specified underlying asset in the specified pool\"},\"isTimeBased()\":{\"notice\":\"Acknowledges if a contract is time based or not\"},\"vTokenBalances(address,address)\":{\"notice\":\"Queries the user's supply/borrow balances in the specified vToken\"},\"vTokenBalancesAll(address[],address)\":{\"notice\":\"Queries the user's supply/borrow balances in vTokens\"},\"vTokenMetadata(address)\":{\"notice\":\"Returns the metadata of VToken\"},\"vTokenMetadataAll(address[])\":{\"notice\":\"Returns the metadata of all VTokens\"},\"vTokenUnderlyingPrice(address)\":{\"notice\":\"Returns the price data for the underlying asset of the specified vToken\"},\"vTokenUnderlyingPriceAll(address[])\":{\"notice\":\"Returns the price data for the underlying assets of the specified vTokens\"}},\"notice\":\"The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be looked up for specific pools and markets: - the vToken balance of a given user; - the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address; - the vToken address in a pool for a given asset; - a list of all pools that support an asset; - the underlying asset price of a vToken; - the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Lens/PoolLens.sol\":\"PoolLens\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"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\",\"keccak256\":\"0x9140dabc466abab21b48b72dbda26736b1183a310d0e677d3719d201df026510\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x359a1ab89b46b9aba7bcad3fb651924baf4893d15153049b9976b0fc9be1358e\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x07e881de3b9f6d2c07909f193f24b96c7fe4ea60013260f3f25aecd8bab3c2f8\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x75097e35253e7fb282ee4d7f27a80eaacfa759923185bf17302a89cbc059c5ef\",\"license\":\"MIT\"},\"@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\"},\"@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\",\"keccak256\":\"0xfe0fd441c84ac907cabc88db69ef04f6d7532d770c7e6a1dfe6e7d6305debb49\",\"license\":\"BSD-3-Clause\"},\"@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 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/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface IProtocolShareReserve {\\n /// @notice it represents the type of vToken income\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(\\n address comptroller,\\n address asset,\\n IncomeType incomeType\\n ) external;\\n}\\n\",\"keccak256\":\"0x0f341bbef8f12885d79b7acaad7aaf11b84809e8f6b059ef4efc011c8f6c39a5\",\"license\":\"BSD-3-Clause\"},\"@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\",\"keccak256\":\"0x57a2bbb9b8e02b1c0a5c0e305fef1328a22db56c3d4b148c362010a6e767243c\",\"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\"},\"@venusprotocol/venus-protocol/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\",\"keccak256\":\"0xd112f60183416ad796093b4a83a80ddc1b8b655965f02ae55ca82e2a0c68f97d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/venus-protocol/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\",\"keccak256\":\"0x5285c875114db2ea2be0b81b65722d5761806217022db733323c4e03365a95e7\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IPrime } from \\\"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\\\";\\n\\nimport { ComptrollerInterface, Action } from \\\"./ComptrollerInterface.sol\\\";\\nimport { ComptrollerStorage } from \\\"./ComptrollerStorage.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"./MaxLoopsLimitHelper.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title Comptroller\\n * @author Venus\\n * @notice The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating,\\n * and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts\\n * with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows\\n * or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing\\n * liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow,\\n * as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the\\n * markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market\\u2019s corresponding liquidation threshold,\\n * the borrow is eligible for liquidation.\\n *\\n * The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed\\n * the `minLiquidatableCollateral` for the `Comptroller`:\\n *\\n * - `healAccount()`: This function is called to seize all of a given user\\u2019s collateral, requiring the `msg.sender` repay a certain percentage\\n * of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed\\n * 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt\\n * and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool.\\n * - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation\\n * incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic\\n * verifying that the repay amount does not exceed the close factor.\\n */\\ncontract Comptroller is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n ComptrollerStorage,\\n ComptrollerInterface,\\n ExponentialNoError,\\n MaxLoopsLimitHelper\\n{\\n // PoolRegistry, immutable to save on gas\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable poolRegistry;\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(VToken indexed vToken, address indexed account);\\n\\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(VToken vToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa);\\n\\n /// @notice Emitted when liquidation threshold is changed by admin\\n event NewLiquidationThreshold(\\n VToken vToken,\\n uint256 oldLiquidationThresholdMantissa,\\n uint256 newLiquidationThresholdMantissa\\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 an action is paused on a market\\n event ActionPausedMarket(VToken vToken, Action action, bool pauseState);\\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 the collateral threshold (in USD) for non-batch liquidations is changed\\n event NewMinLiquidatableCollateral(uint256 oldMinLiquidatableCollateral, uint256 newMinLiquidatableCollateral);\\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 a rewards distributor is added\\n event NewRewardsDistributor(address indexed rewardsDistributor, address indexed rewardToken);\\n\\n /// @notice Emitted when a market is supported\\n event MarketSupported(VToken vToken);\\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 a market\\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\\n\\n /// @notice Emitted when a market is unlisted\\n event MarketUnlisted(address indexed vToken);\\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 Thrown when collateral factor exceeds the upper bound\\n error InvalidCollateralFactor();\\n\\n /// @notice Thrown when liquidation threshold exceeds the collateral factor\\n error InvalidLiquidationThreshold();\\n\\n /// @notice Thrown when the action is only available to specific sender, but the real sender was different\\n error UnexpectedSender(address expectedSender, address actualSender);\\n\\n /// @notice Thrown when the oracle returns an invalid price for some asset\\n error PriceError(address vToken);\\n\\n /// @notice Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\\n error SnapshotError(address vToken, address user);\\n\\n /// @notice Thrown when the market is not listed\\n error MarketNotListed(address market);\\n\\n /// @notice Thrown when a market has an unexpected comptroller\\n error ComptrollerMismatch();\\n\\n /// @notice Thrown when user is not member of market\\n error MarketNotCollateral(address vToken, address user);\\n\\n /// @notice Thrown when borrow action is not paused\\n error BorrowActionNotPaused();\\n\\n /// @notice Thrown when mint action is not paused\\n error MintActionNotPaused();\\n\\n /// @notice Thrown when redeem action is not paused\\n error RedeemActionNotPaused();\\n\\n /// @notice Thrown when repay action is not paused\\n error RepayActionNotPaused();\\n\\n /// @notice Thrown when seize action is not paused\\n error SeizeActionNotPaused();\\n\\n /// @notice Thrown when exit market action is not paused\\n error ExitMarketActionNotPaused();\\n\\n /// @notice Thrown when transfer action is not paused\\n error TransferActionNotPaused();\\n\\n /// @notice Thrown when enter market action is not paused\\n error EnterMarketActionNotPaused();\\n\\n /// @notice Thrown when liquidate action is not paused\\n error LiquidateActionNotPaused();\\n\\n /// @notice Thrown when borrow cap is not zero\\n error BorrowCapIsNotZero();\\n\\n /// @notice Thrown when supply cap is not zero\\n error SupplyCapIsNotZero();\\n\\n /// @notice Thrown when collateral factor is not zero\\n error CollateralFactorIsNotZero();\\n\\n /**\\n * @notice Thrown during the liquidation if user's total collateral amount is lower than\\n * a predefined threshold. In this case only batch liquidations (either liquidateAccount\\n * or healAccount) are available.\\n */\\n error MinimalCollateralViolated(uint256 expectedGreaterThan, uint256 actual);\\n error CollateralExceedsThreshold(uint256 expectedLessThanOrEqualTo, uint256 actual);\\n error InsufficientCollateral(uint256 collateralToSeize, uint256 availableCollateral);\\n\\n /// @notice Thrown when the account doesn't have enough liquidity to redeem or borrow\\n error InsufficientLiquidity();\\n\\n /// @notice Thrown when trying to liquidate a healthy account\\n error InsufficientShortfall();\\n\\n /// @notice Thrown when trying to repay more than allowed by close factor\\n error TooMuchRepay();\\n\\n /// @notice Thrown if the user is trying to exit a market in which they have an outstanding debt\\n error NonzeroBorrowBalance();\\n\\n /// @notice Thrown when trying to perform an action that is paused\\n error ActionPaused(address market, Action action);\\n\\n /// @notice Thrown when trying to add a market that is already listed\\n error MarketAlreadyListed(address market);\\n\\n /// @notice Thrown if the supply cap is exceeded\\n error SupplyCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if the borrow cap is exceeded\\n error BorrowCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if delegate approval status is already set to the requested value\\n error DelegationStatusUnchanged();\\n\\n /// @param poolRegistry_ Pool registry address\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n constructor(address poolRegistry_) {\\n ensureNonzeroAddress(poolRegistry_);\\n\\n poolRegistry = poolRegistry_;\\n _disableInitializers();\\n }\\n\\n /**\\n * @param loopLimit Limit for the loops can iterate to avoid the DOS\\n * @param accessControlManager Access control manager contract address\\n */\\n function initialize(uint256 loopLimit, address accessControlManager) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager);\\n\\n _setMaxLoopsLimit(loopLimit);\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation; enabling them to be used as collateral\\n * @param vTokens The list of addresses of the vToken markets to be enabled\\n * @return errors An array of NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketEntered is emitted for each market on success\\n * @custom:error ActionPaused error is thrown if entering any of the markets is paused\\n * @custom:error MarketNotListed error is thrown if any of the markets is not listed\\n * @custom:access Not restricted\\n */\\n function enterMarkets(address[] memory vTokens) external override returns (uint256[] memory) {\\n uint256 len = vTokens.length;\\n\\n uint256[] memory results = new uint256[](len);\\n for (uint256 i; i < len; ++i) {\\n VToken vToken = VToken(vTokens[i]);\\n\\n _addToMarket(vToken, msg.sender);\\n results[i] = NO_ERROR;\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Unlist a market by setting isListed to false\\n * @dev Checks if all actions are paused, borrow/supply caps is set to 0 and collateral factor is to 0.\\n * @param market The address of the market (token) to unlist\\n * @return uint256 Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketUnlisted is emitted on success\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error BorrowActionNotPaused error is thrown if borrow action is not paused\\n * @custom:error MintActionNotPaused error is thrown if mint action is not paused\\n * @custom:error RedeemActionNotPaused error is thrown if redeem action is not paused\\n * @custom:error RepayActionNotPaused error is thrown if repay action is not paused\\n * @custom:error EnterMarketActionNotPaused error is thrown if enter market action is not paused\\n * @custom:error LiquidateActionNotPaused error is thrown if liquidate action is not paused\\n * @custom:error BorrowCapIsNotZero error is thrown if borrow cap is not zero\\n * @custom:error SupplyCapIsNotZero error is thrown if supply cap is not zero\\n * @custom:error CollateralFactorIsNotZero error is thrown if collateral factor is not zero\\n */\\n function unlistMarket(address market) external returns (uint256) {\\n _checkAccessAllowed(\\\"unlistMarket(address)\\\");\\n\\n Market storage _market = markets[market];\\n\\n if (!_market.isListed) {\\n revert MarketNotListed(market);\\n }\\n\\n if (!actionPaused(market, Action.BORROW)) {\\n revert BorrowActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.MINT)) {\\n revert MintActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.REDEEM)) {\\n revert RedeemActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.REPAY)) {\\n revert RepayActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.SEIZE)) {\\n revert SeizeActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.ENTER_MARKET)) {\\n revert EnterMarketActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.LIQUIDATE)) {\\n revert LiquidateActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.TRANSFER)) {\\n revert TransferActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.EXIT_MARKET)) {\\n revert ExitMarketActionNotPaused();\\n }\\n\\n if (borrowCaps[market] != 0) {\\n revert BorrowCapIsNotZero();\\n }\\n\\n if (supplyCaps[market] != 0) {\\n revert SupplyCapIsNotZero();\\n }\\n\\n if (_market.collateralFactorMantissa != 0) {\\n revert CollateralFactorIsNotZero();\\n }\\n\\n _market.isListed = false;\\n emit MarketUnlisted(market);\\n\\n return NO_ERROR;\\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 * @custom:event DelegateUpdated emits on success\\n * @custom:error ZeroAddressNotAllowed is thrown when delegate address is zero\\n * @custom:error DelegationStatusUnchanged is thrown if approval status is already set to the requested value\\n * @custom:access Not restricted\\n */\\n function updateDelegate(address delegate, bool approved) external {\\n ensureNonzeroAddress(delegate);\\n if (approvedDelegates[msg.sender][delegate] == approved) {\\n revert DelegationStatusUnchanged();\\n }\\n\\n approvedDelegates[msg.sender][delegate] = approved;\\n emit DelegateUpdated(msg.sender, delegate, approved);\\n }\\n\\n /**\\n * @notice Removes asset from sender's account liquidity calculation; disabling them as collateral\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketExited is emitted on success\\n * @custom:error ActionPaused error is thrown if exiting the market is paused\\n * @custom:error NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function exitMarket(address vTokenAddress) external override returns (uint256) {\\n _checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\\n VToken vToken = VToken(vTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\\n (uint256 tokensHeld, uint256 amountOwed, ) = _safeGetAccountSnapshot(vToken, msg.sender);\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n revert NonzeroBorrowBalance();\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n _checkRedeemAllowed(vTokenAddress, msg.sender, tokensHeld);\\n\\n Market storage marketToExit = markets[address(vToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return 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 // load into memory for faster iteration\\n VToken[] memory userAssetList = accountAssets[msg.sender];\\n uint256 len = userAssetList.length;\\n\\n uint256 assetIndex = len;\\n for (uint256 i; i < len; ++i) {\\n if (userAssetList[i] == vToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n VToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.pop();\\n\\n emit MarketExited(vToken, msg.sender);\\n\\n return NO_ERROR;\\n }\\n\\n /*** Policy Hooks ***/\\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 * @custom:error ActionPaused error is thrown if supplying to this market is paused\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\\n * @custom:access Not restricted\\n */\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external override {\\n _checkActionPauseState(vToken, Action.MINT);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n uint256 supplyCap = supplyCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (supplyCap != type(uint256).max) {\\n uint256 vTokenSupply = VToken(vToken).totalSupply();\\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\\n if (nextTotalSupply > supplyCap) {\\n revert SupplyCapExceeded(vToken, supplyCap);\\n }\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, minter);\\n }\\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external override {\\n _checkActionPauseState(vToken, Action.REDEEM);\\n\\n _checkRedeemAllowed(vToken, redeemer, redeemTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, redeemer);\\n }\\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 if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(redeemer, vToken);\\n }\\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 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 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 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 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 * @custom:error ActionPaused error is thrown if borrowing is paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if there is not enough collateral to borrow\\n * @custom:error BorrowCapExceeded is thrown if the borrow cap will be exceeded should this borrow succeed\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted if vToken is enabled as collateral, otherwise only vToken\\n */\\n /// disable-eslint\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external override {\\n _checkActionPauseState(vToken, Action.BORROW);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (!markets[vToken].accountMembership[borrower]) {\\n // only vTokens may call borrowAllowed if borrower not in market\\n _checkSenderIs(vToken);\\n\\n // attempt to add borrower to the market or revert\\n _addToMarket(VToken(msg.sender), borrower);\\n }\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (oracle.getUnderlyingPrice(vToken) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 borrowCap = borrowCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (borrowCap != type(uint256).max) {\\n uint256 totalBorrows = VToken(vToken).totalBorrows();\\n uint256 badDebt = VToken(vToken).badDebt();\\n uint256 nextTotalBorrows = totalBorrows + borrowAmount + badDebt;\\n if (nextTotalBorrows > borrowCap) {\\n revert BorrowCapExceeded(vToken, borrowCap);\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n borrower,\\n VToken(vToken),\\n 0,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\n }\\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 borrower The account which would borrowed the asset\\n * @custom:error ActionPaused error is thrown if repayments are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:access Not restricted\\n */\\n function preRepayHook(address vToken, address borrower) external override {\\n _checkActionPauseState(vToken, Action.REPAY);\\n\\n oracle.updatePrice(vToken);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\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 borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n * @param skipLiquidityCheck Allows the borrow to be liquidated regardless of the account liquidity\\n * @custom:error ActionPaused error is thrown if liquidations are paused in this market\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor\\n * @custom:error MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations\\n * @custom:error InsufficientShortfall is thrown when trying to liquidate a healthy account\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n */\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external override {\\n // Pause Action.LIQUIDATE on BORROWED TOKEN to prevent liquidating it.\\n // If we want to pause liquidating to vTokenCollateral, we should pause\\n // Action.SEIZE on it\\n _checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(address(vTokenBorrowed));\\n }\\n if (!markets[vTokenCollateral].isListed) {\\n revert MarketNotListed(address(vTokenCollateral));\\n }\\n\\n uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\\n\\n /* Allow accounts to be liquidated if it is a forced liquidation */\\n if (skipLiquidityCheck || isForcedLiquidationEnabled[vTokenBorrowed]) {\\n if (repayAmount > borrowBalance) {\\n revert TooMuchRepay();\\n }\\n return;\\n }\\n\\n /* The borrower must have shortfall and collateral > threshold in order to be liquidatable */\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral <= minLiquidatableCollateral) {\\n /* The liquidator should use either liquidateAccount or healAccount */\\n revert MinimalCollateralViolated(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint256 maxClose = mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance);\\n if (repayAmount > maxClose) {\\n revert TooMuchRepay();\\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 seizerContract Contract that tries to seize the asset (either borrowed vToken or Comptroller)\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @custom:error ActionPaused error is thrown if seizing this type of collateral is paused\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error ComptrollerMismatch error is when seizer contract or seized asset belong to different pools\\n * @custom:access Not restricted\\n */\\n function preSeizeHook(\\n address vTokenCollateral,\\n address seizerContract,\\n address liquidator,\\n address borrower\\n ) external override {\\n // Pause Action.SEIZE on COLLATERAL to prevent seizing it.\\n // If we want to pause liquidating vTokenBorrowed, we should pause\\n // Action.LIQUIDATE on it\\n _checkActionPauseState(vTokenCollateral, Action.SEIZE);\\n\\n Market storage market = markets[vTokenCollateral];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(vTokenCollateral);\\n }\\n\\n if (seizerContract == address(this)) {\\n // If Comptroller is the seizer, just check if collateral's comptroller\\n // is equal to the current address\\n if (address(VToken(vTokenCollateral).comptroller()) != address(this)) {\\n revert ComptrollerMismatch();\\n }\\n } else {\\n // If the seizer is not the Comptroller, check that the seizer is a\\n // listed market, and that the markets' comptrollers match\\n if (!markets[seizerContract].isListed) {\\n revert MarketNotListed(seizerContract);\\n }\\n if (VToken(vTokenCollateral).comptroller() != VToken(seizerContract).comptroller()) {\\n revert ComptrollerMismatch();\\n }\\n }\\n\\n if (!market.accountMembership[borrower]) {\\n revert MarketNotCollateral(vTokenCollateral, borrower);\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vTokenCollateral);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, borrower);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, liquidator);\\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external override {\\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 _checkRedeemAllowed(vToken, src, transferTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, src);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, dst);\\n }\\n }\\n\\n /*** Pool-level operations ***/\\n\\n /**\\n * @notice Seizes all the remaining collateral, makes msg.sender repay the existing\\n * borrows, and treats the rest of the debt as bad debt (for each market).\\n * The sender has to repay a certain percentage of the debt, computed as\\n * collateral / (borrows * liquidationIncentive).\\n * @param user account to heal\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for healing\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function healAccount(address user) external {\\n VToken[] memory userAssets = getAssetsIn(user);\\n uint256 userAssetsCount = userAssets.length;\\n\\n address liquidator = msg.sender;\\n {\\n ResilientOracleInterface oracle_ = oracle;\\n // We need all user's markets to be fresh for the computations to be correct\\n for (uint256 i; i < userAssetsCount; ++i) {\\n userAssets[i].accrueInterest();\\n oracle_.updatePrice(address(userAssets[i]));\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(user, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n // percentage = collateral / (borrows * liquidation incentive)\\n Exp memory collateral = Exp({ mantissa: snapshot.totalCollateral });\\n Exp memory scaledBorrows = mul_(\\n Exp({ mantissa: snapshot.borrows }),\\n Exp({ mantissa: liquidationIncentiveMantissa })\\n );\\n\\n Exp memory percentage = div_(collateral, scaledBorrows);\\n if (lessThanExp(Exp({ mantissa: MANTISSA_ONE }), percentage)) {\\n revert CollateralExceedsThreshold(scaledBorrows.mantissa, collateral.mantissa);\\n }\\n\\n for (uint256 i; i < userAssetsCount; ++i) {\\n VToken market = userAssets[i];\\n\\n (uint256 tokens, uint256 borrowBalance, ) = _safeGetAccountSnapshot(market, user);\\n uint256 repaymentAmount = mul_ScalarTruncate(percentage, borrowBalance);\\n\\n // Seize the entire collateral\\n if (tokens != 0) {\\n market.seize(liquidator, user, tokens);\\n }\\n // Repay a certain percentage of the borrow, forgive the rest\\n if (borrowBalance != 0) {\\n market.healBorrow(liquidator, user, repaymentAmount);\\n }\\n }\\n }\\n\\n /**\\n * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than\\n * a predefined threshold, and the account collateral can be seized to cover all borrows. If\\n * the collateral is higher than the threshold, use regular liquidations. If the collateral is\\n * below the threshold, and the account is insolvent, use healAccount.\\n * @param borrower the borrower address\\n * @param orders an array of liquidation orders\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation\\n * @custom:error InsufficientCollateral error is thrown when there is not enough collateral to cover the debt\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function liquidateAccount(address borrower, LiquidationOrder[] calldata orders) external {\\n // We will accrue interest and update the oracle prices later during the liquidation\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n // You should use the regular vToken.liquidateBorrow(...) call\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n uint256 collateralToSeize = mul_ScalarTruncate(\\n Exp({ mantissa: liquidationIncentiveMantissa }),\\n snapshot.borrows\\n );\\n if (collateralToSeize >= snapshot.totalCollateral) {\\n // There is not enough collateral to seize. Use healBorrow to repay some part of the borrow\\n // and record bad debt.\\n revert InsufficientCollateral(collateralToSeize, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n uint256 ordersCount = orders.length;\\n\\n _ensureMaxLoops(ordersCount / 2);\\n\\n for (uint256 i; i < ordersCount; ++i) {\\n if (!markets[address(orders[i].vTokenBorrowed)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenBorrowed));\\n }\\n if (!markets[address(orders[i].vTokenCollateral)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenCollateral));\\n }\\n\\n LiquidationOrder calldata order = orders[i];\\n order.vTokenBorrowed.forceLiquidateBorrow(\\n msg.sender,\\n borrower,\\n order.repayAmount,\\n order.vTokenCollateral,\\n true\\n );\\n }\\n\\n VToken[] memory borrowMarkets = getAssetsIn(borrower);\\n uint256 marketsCount = borrowMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower);\\n require(borrowBalance == 0, \\\"Nonzero borrow balance after liquidation\\\");\\n }\\n }\\n\\n /**\\n * @notice Sets the closeFactor to use when liquidating borrows\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @custom:event Emits NewCloseFactor on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCloseFactor(uint256 newCloseFactorMantissa) external {\\n _checkAccessAllowed(\\\"setCloseFactor(uint256)\\\");\\n require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, \\\"Close factor greater than maximum close factor\\\");\\n require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, \\\"Close factor smaller than minimum close factor\\\");\\n\\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev This function is restricted by the AccessControlManager\\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 * @custom:event Emits NewCollateralFactor when collateral factor is updated\\n * and NewLiquidationThreshold when liquidation threshold is updated\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InvalidCollateralFactor error is thrown when collateral factor is too high\\n * @custom:error InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor\\n * @custom:error PriceError is thrown when the oracle returns an invalid price for the asset\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCollateralFactor(\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external {\\n _checkAccessAllowed(\\\"setCollateralFactor(address,uint256,uint256)\\\");\\n\\n // Verify market is listed\\n Market storage market = markets[address(vToken)];\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Check collateral factor <= 0.9\\n if (newCollateralFactorMantissa > MAX_COLLATERAL_FACTOR_MANTISSA) {\\n revert InvalidCollateralFactor();\\n }\\n\\n // Ensure that liquidation threshold <= 1\\n if (newLiquidationThresholdMantissa > MANTISSA_ONE) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // Ensure that liquidation threshold >= CF\\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n }\\n\\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\\n emit NewLiquidationThreshold(vToken, oldLiquidationThresholdMantissa, newLiquidationThresholdMantissa);\\n }\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev This function is restricted by the AccessControlManager\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @custom:event Emits NewLiquidationIncentive on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external {\\n require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, \\\"liquidation incentive should be greater than 1e18\\\");\\n\\n _checkAccessAllowed(\\\"setLiquidationIncentive(uint256)\\\");\\n\\n // Save current value for use in log\\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\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\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Only callable by the PoolRegistry\\n * @param vToken The address of the market (token) to list\\n * @custom:error MarketAlreadyListed is thrown if the market is already listed in this pool\\n * @custom:access Only PoolRegistry\\n */\\n function supportMarket(VToken vToken) external {\\n _checkSenderIs(poolRegistry);\\n\\n if (markets[address(vToken)].isListed) {\\n revert MarketAlreadyListed(address(vToken));\\n }\\n\\n require(vToken.isVToken(), \\\"Comptroller: Invalid vToken\\\"); // Sanity check to make sure its really a VToken\\n\\n Market storage newMarket = markets[address(vToken)];\\n newMarket.isListed = true;\\n newMarket.collateralFactorMantissa = 0;\\n newMarket.liquidationThresholdMantissa = 0;\\n\\n _addMarket(address(vToken));\\n\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n rewardsDistributors[i].initializeMarket(address(vToken));\\n }\\n\\n emit MarketSupported(vToken);\\n }\\n\\n /**\\n * @notice Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A borrow cap of type(uint256).max corresponds to unlimited borrowing.\\n * @dev Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed\\n until the total borrows amount goes below the new borrow cap\\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 type(uint256).max corresponds to unlimited borrowing.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\\n _checkAccessAllowed(\\\"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 _ensureMaxLoops(numMarkets);\\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 * @notice Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A supply cap of type(uint256).max corresponds to unlimited supply.\\n * @dev Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed\\n until the total supplies amount goes below the new supply cap\\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 type(uint256).max corresponds to unlimited supply.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\\n _checkAccessAllowed(\\\"setMarketSupplyCaps(address[],uint256[])\\\");\\n uint256 vTokensCount = vTokens.length;\\n\\n require(vTokensCount != 0, \\\"invalid number of markets\\\");\\n require(vTokensCount == newSupplyCaps.length, \\\"invalid number of markets\\\");\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Pause/unpause specified actions\\n * @dev This function is restricted by the AccessControlManager\\n * @param marketsList Markets to pause/unpause the actions on\\n * @param actionsList List of action ids to pause/unpause\\n * @param paused The new paused state (true=paused, false=unpaused)\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setActionsPaused(VToken[] calldata marketsList, Action[] calldata actionsList, bool paused) external {\\n _checkAccessAllowed(\\\"setActionsPaused(address[],uint256[],bool)\\\");\\n\\n uint256 marketsCount = marketsList.length;\\n uint256 actionsCount = actionsList.length;\\n\\n _ensureMaxLoops(marketsCount * actionsCount);\\n\\n for (uint256 marketIdx; marketIdx < marketsCount; ++marketIdx) {\\n for (uint256 actionIdx; actionIdx < actionsCount; ++actionIdx) {\\n _setActionPaused(address(marketsList[marketIdx]), actionsList[actionIdx], paused);\\n }\\n }\\n }\\n\\n /**\\n * @notice Set the given collateral threshold for non-batch liquidations. Regular liquidations\\n * will fail if the collateral amount is less than this threshold. Liquidators should use batch\\n * operations like liquidateAccount or healAccount.\\n * @dev This function is restricted by the AccessControlManager\\n * @param newMinLiquidatableCollateral The new min liquidatable collateral (in USD).\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external {\\n _checkAccessAllowed(\\\"setMinLiquidatableCollateral(uint256)\\\");\\n\\n uint256 oldMinLiquidatableCollateral = minLiquidatableCollateral;\\n minLiquidatableCollateral = newMinLiquidatableCollateral;\\n emit NewMinLiquidatableCollateral(oldMinLiquidatableCollateral, newMinLiquidatableCollateral);\\n }\\n\\n /**\\n * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor\\n * contracts with the same rewardToken, and there could be overlaping among them considering the last reward slot (block or second)\\n * @dev Only callable by the admin\\n * @param _rewardsDistributor Address of the RewardDistributor contract to add\\n * @custom:access Only Governance\\n * @custom:event Emits NewRewardsDistributor with distributor address\\n */\\n function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner {\\n require(!rewardsDistributorExists[address(_rewardsDistributor)], \\\"already exists\\\");\\n\\n uint256 rewardsDistributorsLen = rewardsDistributors.length;\\n _ensureMaxLoops(rewardsDistributorsLen + 1);\\n\\n rewardsDistributors.push(_rewardsDistributor);\\n rewardsDistributorExists[address(_rewardsDistributor)] = true;\\n\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n _rewardsDistributor.initializeMarket(address(allMarkets[i]));\\n }\\n\\n emit NewRewardsDistributor(address(_rewardsDistributor), address(_rewardsDistributor.rewardToken()));\\n }\\n\\n /**\\n * @notice Sets a new price oracle for the Comptroller\\n * @dev Only callable by the admin\\n * @param newOracle Address of the new price oracle to set\\n * @custom:event Emits NewPriceOracle on success\\n * @custom:error ZeroAddressNotAllowed is thrown when the new oracle address is zero\\n */\\n function setPriceOracle(ResilientOracleInterface newOracle) external onlyOwner {\\n ensureNonzeroAddress(address(newOracle));\\n\\n ResilientOracleInterface oldOracle = oracle;\\n oracle = newOracle;\\n emit NewPriceOracle(oldOracle, newOracle);\\n }\\n\\n /**\\n * @notice Set the for loop iteration limit to avoid DOS\\n * @param limit Limit for the max loops can execute at a time\\n */\\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Sets the prime token contract for the comptroller\\n * @param _prime Address of the Prime contract\\n */\\n function setPrimeToken(IPrime _prime) external onlyOwner {\\n ensureNonzeroAddress(address(_prime));\\n\\n emit NewPrimeToken(prime, _prime);\\n prime = _prime;\\n }\\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 * @param vTokenBorrowed Borrowed vToken\\n * @param enable Whether to enable forced liquidations\\n */\\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\\n _checkAccessAllowed(\\\"setForcedLiquidation(address,bool)\\\");\\n ensureNonzeroAddress(vTokenBorrowed);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(vTokenBorrowed);\\n }\\n\\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to liquidation threshold requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of liquidation threshold requirements,\\n * @return shortfall Account shortfall below liquidation threshold requirements\\n */\\n function getAccountLiquidity(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getLiquidationThreshold);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to collateral requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of collateral requirements,\\n * @return shortfall Account shortfall below collateral requirements\\n */\\n function getBorrowingPower(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getCollateralFactor);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Hypothetical account liquidity in excess of collateral requirements,\\n * @return shortfall 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 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n account,\\n VToken(vTokenModify),\\n redeemTokens,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\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 markets The list of market addresses\\n */\\n function getAllMarkets() external view override returns (VToken[] memory) {\\n return allMarkets;\\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 /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns whether the given account is entered in a given market\\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 market specified, 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 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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return tokensToSeize Number of vTokenCollateral tokens to be seized in a liquidation\\n * @custom:error PriceError if the oracle returns an invalid price\\n */\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view override returns (uint256 error, uint256 tokensToSeize) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint256 priceBorrowedMantissa = _safeGetUnderlyingPrice(VToken(vTokenBorrowed));\\n uint256 priceCollateralMantissa = _safeGetUnderlyingPrice(VToken(vTokenCollateral));\\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 uint256 exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint256 seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n\\n numerator = mul_(Exp({ mantissa: liquidationIncentiveMantissa }), Exp({ mantissa: priceBorrowedMantissa }));\\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\\n ratio = div_(numerator, denominator);\\n\\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\\n\\n return (NO_ERROR, seizeTokens);\\n }\\n\\n /**\\n * @notice Returns reward speed given a vToken\\n * @param vToken The vToken to get the reward speeds for\\n * @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors\\n */\\n function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {\\n uint256 rewardsDistributorsLength = rewardsDistributors.length;\\n rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);\\n for (uint256 i; i < rewardsDistributorsLength; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n address rewardToken = address(rewardsDistributor.rewardToken());\\n rewardSpeeds[i] = RewardSpeeds({\\n rewardToken: rewardToken,\\n supplySpeed: rewardsDistributor.rewardTokenSupplySpeeds(vToken),\\n borrowSpeed: rewardsDistributor.rewardTokenBorrowSpeeds(vToken)\\n });\\n }\\n return rewardSpeeds;\\n }\\n\\n /**\\n * @notice Return all reward distributors for this pool\\n * @return Array of RewardDistributor addresses\\n */\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory) {\\n return rewardsDistributors;\\n }\\n\\n /**\\n * @notice A marker method that returns true for a valid Comptroller contract\\n * @return Always true\\n */\\n function isComptroller() external pure override returns (bool) {\\n return true;\\n }\\n\\n /**\\n * @notice Update the prices of all the tokens associated with the provided account\\n * @param account Address of the account to get associated tokens with\\n */\\n function updatePrices(address account) public {\\n VToken[] memory vTokens = getAssetsIn(account);\\n uint256 vTokensCount = vTokens.length;\\n\\n ResilientOracleInterface oracle_ = oracle;\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n oracle_.updatePrice(address(vTokens[i]));\\n }\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param market vToken address\\n * @param action Action to check\\n * @return paused True if the action is paused otherwise false\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][action];\\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 list with the assets the account has entered\\n */\\n function getAssetsIn(address account) public 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 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 */\\n function _addToMarket(VToken vToken, address borrower) internal {\\n _checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = markets[address(vToken)];\\n\\n if (!marketToJoin.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return;\\n }\\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\\n /**\\n * @notice Internal function to validate that a market hasn't already been added\\n * and if it hasn't adds it\\n * @param vToken The market to support\\n */\\n function _addMarket(address vToken) internal {\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n if (allMarkets[i] == VToken(vToken)) {\\n revert MarketAlreadyListed(vToken);\\n }\\n }\\n allMarkets.push(VToken(vToken));\\n marketsCount = allMarkets.length;\\n _ensureMaxLoops(marketsCount);\\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 _setActionPaused(address market, Action action, bool paused) internal {\\n require(markets[market].isListed, \\\"cannot pause a market that is not listed\\\");\\n _actionPaused[market][action] = paused;\\n emit ActionPausedMarket(VToken(market), action, paused);\\n }\\n\\n /**\\n * @dev Internal function to check that vTokens can be safely redeemed for the underlying asset.\\n * @param vToken Address of the vTokens to redeem\\n * @param redeemer Account redeeming the tokens\\n * @param redeemTokens The number of tokens to redeem\\n */\\n function _checkRedeemAllowed(address vToken, address redeemer, uint256 redeemTokens) internal {\\n Market storage market = markets[vToken];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!market.accountMembership[redeemer]) {\\n return;\\n }\\n\\n // Update the prices of tokens\\n updatePrices(redeemer);\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n _getCollateralFactor\\n );\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n }\\n\\n /**\\n * @notice Get the total collateral, weighted collateral, borrow balance, liquidity, shortfall\\n * @param account The account to get the snapshot for\\n * @param weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n * liquidation threshold. Accepts the address of the vToken and returns the weight as Exp.\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getCurrentLiquiditySnapshot(\\n address account,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n return _getHypotheticalLiquiditySnapshot(account, VToken(address(0)), 0, 0, weight);\\n }\\n\\n /**\\n * @notice Determine what the supply/borrow balances 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 weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n liquidation threshold. Accepts the address of the VToken and returns the weight\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getHypotheticalLiquiditySnapshot(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n // For each asset the account is in\\n VToken[] memory assets = getAssetsIn(account);\\n uint256 assetsCount = assets.length;\\n\\n for (uint256 i; i < assetsCount; ++i) {\\n VToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the vToken\\n (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) = _safeGetAccountSnapshot(\\n asset,\\n account\\n );\\n\\n // Get the normalized price of the asset\\n Exp memory oraclePrice = Exp({ mantissa: _safeGetUnderlyingPrice(asset) });\\n\\n // Pre-compute conversion factors from vTokens -> usd\\n Exp memory vTokenPrice = mul_(Exp({ mantissa: exchangeRateMantissa }), oraclePrice);\\n Exp memory weightedVTokenPrice = mul_(weight(asset), vTokenPrice);\\n\\n // weightedCollateral += weightedVTokenPrice * vTokenBalance\\n snapshot.weightedCollateral = mul_ScalarTruncateAddUInt(\\n weightedVTokenPrice,\\n vTokenBalance,\\n snapshot.weightedCollateral\\n );\\n\\n // totalCollateral += vTokenPrice * vTokenBalance\\n snapshot.totalCollateral = mul_ScalarTruncateAddUInt(vTokenPrice, vTokenBalance, snapshot.totalCollateral);\\n\\n // borrows += oraclePrice * borrowBalance\\n snapshot.borrows = mul_ScalarTruncateAddUInt(oraclePrice, borrowBalance, snapshot.borrows);\\n\\n // Calculate effects of interacting with vTokenModify\\n if (asset == vTokenModify) {\\n // redeem effect\\n // effects += tokensToDenom * redeemTokens\\n snapshot.effects = mul_ScalarTruncateAddUInt(weightedVTokenPrice, redeemTokens, snapshot.effects);\\n\\n // borrow effect\\n // effects += oraclePrice * borrowAmount\\n snapshot.effects = mul_ScalarTruncateAddUInt(oraclePrice, borrowAmount, snapshot.effects);\\n }\\n }\\n\\n uint256 borrowPlusEffects = snapshot.borrows + snapshot.effects;\\n // These are safe, as the underflow condition is checked first\\n unchecked {\\n if (snapshot.weightedCollateral > borrowPlusEffects) {\\n snapshot.liquidity = snapshot.weightedCollateral - borrowPlusEffects;\\n snapshot.shortfall = 0;\\n } else {\\n snapshot.liquidity = 0;\\n snapshot.shortfall = borrowPlusEffects - snapshot.weightedCollateral;\\n }\\n }\\n\\n return snapshot;\\n }\\n\\n /**\\n * @dev Retrieves price from oracle for an asset and checks it is nonzero\\n * @param asset Address for asset to query price\\n * @return Underlying price\\n */\\n function _safeGetUnderlyingPrice(VToken asset) internal view returns (uint256) {\\n uint256 oraclePriceMantissa = oracle.getUnderlyingPrice(address(asset));\\n if (oraclePriceMantissa == 0) {\\n revert PriceError(address(asset));\\n }\\n return oraclePriceMantissa;\\n }\\n\\n /**\\n * @dev Return collateral factor for a market\\n * @param asset Address for asset\\n * @return Collateral factor as exponential\\n */\\n function _getCollateralFactor(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].collateralFactorMantissa });\\n }\\n\\n /**\\n * @dev Retrieves liquidation threshold for a market as an exponential\\n * @param asset Address for asset to liquidation threshold\\n * @return Liquidation threshold as exponential\\n */\\n function _getLiquidationThreshold(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].liquidationThresholdMantissa });\\n }\\n\\n /**\\n * @dev Returns supply and borrow balances of user in vToken, reverts on failure\\n * @param vToken Market to query\\n * @param user Account address\\n * @return vTokenBalance Balance of vTokens, the same as vToken.balanceOf(user)\\n * @return borrowBalance Borrowed amount, including the interest\\n * @return exchangeRateMantissa Stored exchange rate\\n */\\n function _safeGetAccountSnapshot(\\n VToken vToken,\\n address user\\n ) internal view returns (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) {\\n uint256 err;\\n (err, vTokenBalance, borrowBalance, exchangeRateMantissa) = vToken.getAccountSnapshot(user);\\n if (err != 0) {\\n revert SnapshotError(address(vToken), user);\\n }\\n return (vTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /// @notice Reverts if the call is not from expectedSender\\n /// @param expectedSender Expected transaction sender\\n function _checkSenderIs(address expectedSender) internal view {\\n if (msg.sender != expectedSender) {\\n revert UnexpectedSender(expectedSender, msg.sender);\\n }\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n /// @param market Market to check\\n /// @param action Action to check\\n function _checkActionPauseState(address market, Action action) private view {\\n if (actionPaused(market, action)) {\\n revert ActionPaused(market, action);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7c6e1c6264e4681f82a9ac1bcd9155197a930033291ee5561ad97a56006f5e9c\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.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\\n/**\\n * @title ComptrollerInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract.\\n */\\ninterface ComptrollerInterface {\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\\n\\n function exitMarket(address vToken) external returns (uint256);\\n\\n /*** Policy Hooks ***/\\n\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external;\\n\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external;\\n\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external;\\n\\n function preRepayHook(address vToken, address borrower) external;\\n\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external;\\n\\n function preSeizeHook(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower\\n ) external;\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\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 seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external;\\n\\n function isComptroller() external view returns (bool);\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 repayAmount\\n ) external view returns (uint256, uint256);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n}\\n\\n/**\\n * @title ComptrollerViewInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract, including only some util view functions.\\n */\\ninterface ComptrollerViewInterface {\\n function markets(address) external view returns (bool, uint256);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function closeFactorMantissa() external view returns (uint256);\\n\\n function liquidationIncentiveMantissa() external view returns (uint256);\\n\\n function minLiquidatableCollateral() external view returns (uint256);\\n\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function borrowCaps(address) external view returns (uint256);\\n\\n function supplyCaps(address) external view returns (uint256);\\n\\n function approvedDelegates(address user, address delegate) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xcbf7f9977472650c61345b7cbde23e81f626e1f8863bab4c6ce3dacfc7604919\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { IPrime } from \\\"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\\\";\\nimport { Action } from \\\"./ComptrollerInterface.sol\\\";\\n\\n/**\\n * @title ComptrollerStorage\\n * @author Venus\\n * @notice Storage layout for the `Comptroller` contract.\\n */\\ncontract ComptrollerStorage {\\n struct LiquidationOrder {\\n VToken vTokenCollateral;\\n VToken vTokenBorrowed;\\n uint256 repayAmount;\\n }\\n\\n struct AccountLiquiditySnapshot {\\n uint256 totalCollateral;\\n uint256 weightedCollateral;\\n uint256 borrows;\\n uint256 effects;\\n uint256 liquidity;\\n uint256 shortfall;\\n }\\n\\n struct RewardSpeeds {\\n address rewardToken;\\n uint256 supplySpeed;\\n uint256 borrowSpeed;\\n }\\n\\n struct Market {\\n // Whether or not this market is listed\\n bool isListed;\\n // 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 uint256 collateralFactorMantissa;\\n // 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 uint256 liquidationThresholdMantissa;\\n // Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n }\\n\\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 Per-account mapping of \\\"assets you are in\\\"\\n */\\n mapping(address => VToken[]) public accountAssets;\\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 /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\\n mapping(address => uint256) public borrowCaps;\\n\\n /// @notice Minimal collateral required for regular (non-batch) liquidations\\n uint256 public minLiquidatableCollateral;\\n\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\\n mapping(address => uint256) public supplyCaps;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(Action => bool)) internal _actionPaused;\\n\\n // List of Reward Distributors added\\n RewardsDistributor[] internal rewardsDistributors;\\n\\n // Used to check if rewards distributor is added\\n mapping(address => bool) internal rewardsDistributorExists;\\n\\n /// @notice Flag indicating whether forced liquidation enabled for a market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n\\n uint256 internal constant NO_ERROR = 0;\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant MIN_CLOSE_FACTOR_MANTISSA = 0.05e18; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant MAX_CLOSE_FACTOR_MANTISSA = 0.9e18; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.95e18; // 0.95\\n\\n /// Prime token address\\n IPrime public prime;\\n\\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 /**\\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[47] private __gap;\\n}\\n\",\"keccak256\":\"0x4df44cb65ac152bac2be4b4545430e703005a74a55b72e144100b16421bd8bfd\",\"license\":\"BSD-3-Clause\"},\"contracts/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title TokenErrorReporter\\n * @author Venus\\n * @notice Errors that can be thrown by the `VToken` contract.\\n */\\ncontract TokenErrorReporter {\\n uint256 public constant NO_ERROR = 0; // support legacy return codes\\n\\n error TransferNotAllowed();\\n\\n error MintFreshnessCheck();\\n\\n error RedeemFreshnessCheck();\\n error RedeemTransferOutNotPossible();\\n\\n error BorrowFreshnessCheck();\\n error BorrowCashNotAvailable();\\n error DelegateNotApproved();\\n\\n error RepayBorrowFreshnessCheck();\\n\\n error HealBorrowUnauthorized();\\n error ForceLiquidateBorrowUnauthorized();\\n\\n error LiquidateFreshnessCheck();\\n error LiquidateCollateralFreshnessCheck();\\n error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\\n error LiquidateLiquidatorIsBorrower();\\n error LiquidateCloseAmountIsZero();\\n error LiquidateCloseAmountIsUintMax();\\n\\n error LiquidateSeizeLiquidatorIsBorrower();\\n\\n error ProtocolSeizeShareTooBig();\\n\\n error SetReserveFactorFreshCheck();\\n error SetReserveFactorBoundsCheck();\\n\\n error AddReservesFactorFreshCheck(uint256 actualAddAmount);\\n\\n error ReduceReservesFreshCheck();\\n error ReduceReservesCashNotAvailable();\\n error ReduceReservesCashValidation();\\n\\n error SetInterestRateModelFreshCheck();\\n}\\n\",\"keccak256\":\"0x7a7ced1caaac2d9242659ebd50b99f308c725ce958ac9e11f7ada404b1d97a7b\",\"license\":\"BSD-3-Clause\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from \\\"./lib/constants.sol\\\";\\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 struct Exp {\\n uint256 mantissa;\\n }\\n\\n struct Double {\\n uint256 mantissa;\\n }\\n\\n uint256 internal constant EXP_SCALE = EXP_SCALE_;\\n uint256 internal constant DOUBLE_SCALE = 1e36;\\n uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;\\n uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint256) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / EXP_SCALE;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\\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 // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint256 scalar, uint256 addend) internal pure returns (uint256) {\\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 function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\\n require(n <= type(uint224).max, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\\n require(n <= type(uint32).max, 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_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a + b;\\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_(uint256 a, uint256 b) internal pure returns (uint256) {\\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) / EXP_SCALE });\\n }\\n\\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / EXP_SCALE;\\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) / DOUBLE_SCALE });\\n }\\n\\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / DOUBLE_SCALE;\\n }\\n\\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a * b;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return div_(mul_(a, EXP_SCALE), 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, DOUBLE_SCALE), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return div_(mul_(a, DOUBLE_SCALE), b.mantissa);\\n }\\n\\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a / b;\\n }\\n\\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });\\n }\\n}\\n\",\"keccak256\":\"0x8afbe8a24fe3539c124e718681ed3dcebd24c40dd53095786c0155998213b9b0\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModel.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\nabstract contract InterestRateModel {\\n /**\\n * @notice Calculates the current borrow interest rate per slot (block or second)\\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 amount of reserves the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per slot (block or second)\\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 amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\\n * @return Always true\\n */\\n function isInterestRateModel() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xc4fda1ab75ebe4b187b707c4f10c58780f343cf343c537f641dc75d3cd28ab51\",\"license\":\"BSD-3-Clause\"},\"contracts/Lens/PoolLens.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { IERC20Metadata } from \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Action, ComptrollerInterface, ComptrollerViewInterface } from \\\"../ComptrollerInterface.sol\\\";\\nimport { PoolRegistryInterface } from \\\"../Pool/PoolRegistryInterface.sol\\\";\\nimport { PoolRegistry } from \\\"../Pool/PoolRegistry.sol\\\";\\nimport { RewardsDistributor } from \\\"../Rewards/RewardsDistributor.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\n\\n/**\\n * @title PoolLens\\n * @author Venus\\n * @notice The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information\\n * for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be\\n * looked up for specific pools and markets:\\n- the vToken balance of a given user;\\n- the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address;\\n- the vToken address in a pool for a given asset;\\n- a list of all pools that support an asset;\\n- the underlying asset price of a vToken;\\n- the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\\n */\\ncontract PoolLens is ExponentialNoError, TimeManagerV8 {\\n /**\\n * @dev Struct for PoolDetails.\\n */\\n struct PoolData {\\n string name;\\n address creator;\\n address comptroller;\\n uint256 blockPosted;\\n uint256 timestampPosted;\\n string category;\\n string logoURL;\\n string description;\\n address priceOracle;\\n uint256 closeFactor;\\n uint256 liquidationIncentive;\\n uint256 minLiquidatableCollateral;\\n VTokenMetadata[] vTokens;\\n }\\n\\n /**\\n * @dev Struct for VToken.\\n */\\n struct VTokenMetadata {\\n address vToken;\\n uint256 exchangeRateCurrent;\\n uint256 supplyRatePerBlockOrTimestamp;\\n uint256 borrowRatePerBlockOrTimestamp;\\n uint256 reserveFactorMantissa;\\n uint256 supplyCaps;\\n uint256 borrowCaps;\\n uint256 totalBorrows;\\n uint256 totalReserves;\\n uint256 totalSupply;\\n uint256 totalCash;\\n bool isListed;\\n uint256 collateralFactorMantissa;\\n address underlyingAssetAddress;\\n uint256 vTokenDecimals;\\n uint256 underlyingDecimals;\\n uint256 pausedActions;\\n }\\n\\n /**\\n * @dev Struct for VTokenBalance.\\n */\\n struct VTokenBalances {\\n address vToken;\\n uint256 balanceOf;\\n uint256 borrowBalanceCurrent;\\n uint256 balanceOfUnderlying;\\n uint256 tokenBalance;\\n uint256 tokenAllowance;\\n }\\n\\n /**\\n * @dev Struct for underlyingPrice of VToken.\\n */\\n struct VTokenUnderlyingPrice {\\n address vToken;\\n uint256 underlyingPrice;\\n }\\n\\n /**\\n * @dev Struct with pending reward info for a market.\\n */\\n struct PendingReward {\\n address vTokenAddress;\\n uint256 amount;\\n }\\n\\n /**\\n * @dev Struct with reward distribution totals for a single reward token and distributor.\\n */\\n struct RewardSummary {\\n address distributorAddress;\\n address rewardTokenAddress;\\n uint256 totalRewards;\\n PendingReward[] pendingRewards;\\n }\\n\\n /**\\n * @dev Struct used in RewardDistributor to save last updated market state.\\n */\\n struct RewardTokenState {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number or timestamp the index was last updated at\\n uint256 blockOrTimestamp;\\n // The block number or timestamp at which to stop rewards\\n uint256 lastRewardingBlockOrTimestamp;\\n }\\n\\n /**\\n * @dev Struct with bad debt of a market denominated\\n */\\n struct BadDebt {\\n address vTokenAddress;\\n uint256 badDebtUsd;\\n }\\n\\n /**\\n * @dev Struct with bad debt total denominated in usd for a pool and an array of BadDebt structs for each market\\n */\\n struct BadDebtSummary {\\n address comptroller;\\n uint256 totalBadDebtUsd;\\n BadDebt[] badDebts;\\n }\\n\\n /**\\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) {}\\n\\n /**\\n * @notice Queries the user's supply/borrow balances in vTokens\\n * @param vTokens The list of vToken addresses\\n * @param account The user Account\\n * @return A list of structs containing balances data\\n */\\n function vTokenBalancesAll(VToken[] calldata vTokens, address account) external returns (VTokenBalances[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenBalances[] memory res = new VTokenBalances[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenBalances(vTokens[i], account);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Queries all pools with addtional details for each of them\\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @return Arrays of all Venus pools' data\\n */\\n function getAllPools(address poolRegistryAddress) external view returns (PoolData[] memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n PoolRegistry.VenusPool[] memory venusPools = poolRegistryInterface.getAllPools();\\n uint256 poolLength = venusPools.length;\\n\\n PoolData[] memory poolDataItems = new PoolData[](poolLength);\\n\\n for (uint256 i; i < poolLength; ++i) {\\n PoolRegistry.VenusPool memory venusPool = venusPools[i];\\n PoolData memory poolData = getPoolDataFromVenusPool(poolRegistryAddress, venusPool);\\n poolDataItems[i] = poolData;\\n }\\n\\n return poolDataItems;\\n }\\n\\n /**\\n * @notice Queries the details of a pool identified by Comptroller address\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param comptroller The Comptroller implementation address\\n * @return PoolData structure containing the details of the pool\\n */\\n function getPoolByComptroller(\\n address poolRegistryAddress,\\n address comptroller\\n ) external view returns (PoolData memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return getPoolDataFromVenusPool(poolRegistryAddress, poolRegistryInterface.getPoolByComptroller(comptroller));\\n }\\n\\n /**\\n * @notice Returns vToken holding the specified underlying asset in the specified pool\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param comptroller The pool comptroller\\n * @param asset The underlyingAsset of VToken\\n * @return Address of the vToken\\n */\\n function getVTokenForAsset(\\n address poolRegistryAddress,\\n address comptroller,\\n address asset\\n ) external view returns (address) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return poolRegistryInterface.getVTokenForAsset(comptroller, asset);\\n }\\n\\n /**\\n * @notice Returns all pools that support the specified underlying asset\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param asset The underlying asset of vToken\\n * @return A list of Comptroller contracts\\n */\\n function getPoolsSupportedByAsset(\\n address poolRegistryAddress,\\n address asset\\n ) external view returns (address[] memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return poolRegistryInterface.getPoolsSupportedByAsset(asset);\\n }\\n\\n /**\\n * @notice Returns the price data for the underlying assets of the specified vTokens\\n * @param vTokens The list of vToken addresses\\n * @return An array containing the price data for each asset\\n */\\n function vTokenUnderlyingPriceAll(\\n VToken[] calldata vTokens\\n ) external view returns (VTokenUnderlyingPrice[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenUnderlyingPrice[] memory res = new VTokenUnderlyingPrice[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenUnderlyingPrice(vTokens[i]);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Returns the pending rewards for a user for a given pool.\\n * @param account The user account.\\n * @param comptrollerAddress address\\n * @return Pending rewards array\\n */\\n function getPendingRewards(\\n address account,\\n address comptrollerAddress\\n ) external view returns (RewardSummary[] memory) {\\n VToken[] memory markets = ComptrollerInterface(comptrollerAddress).getAllMarkets();\\n RewardsDistributor[] memory rewardsDistributors = ComptrollerViewInterface(comptrollerAddress)\\n .getRewardDistributors();\\n RewardSummary[] memory rewardSummary = new RewardSummary[](rewardsDistributors.length);\\n for (uint256 i; i < rewardsDistributors.length; ++i) {\\n RewardSummary memory reward;\\n reward.distributorAddress = address(rewardsDistributors[i]);\\n reward.rewardTokenAddress = address(rewardsDistributors[i].rewardToken());\\n reward.totalRewards = rewardsDistributors[i].rewardTokenAccrued(account);\\n reward.pendingRewards = _calculateNotDistributedAwards(account, markets, rewardsDistributors[i]);\\n rewardSummary[i] = reward;\\n }\\n return rewardSummary;\\n }\\n\\n /**\\n * @notice Returns a summary of a pool's bad debt broken down by market\\n *\\n * @param comptrollerAddress Address of the comptroller\\n *\\n * @return badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and\\n * a break down of bad debt by market\\n */\\n function getPoolBadDebt(address comptrollerAddress) external view returns (BadDebtSummary memory) {\\n uint256 totalBadDebtUsd;\\n\\n // Get every market in the pool\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\\n VToken[] memory markets = comptroller.getAllMarkets();\\n ResilientOracleInterface priceOracle = comptroller.oracle();\\n\\n BadDebt[] memory badDebts = new BadDebt[](markets.length);\\n\\n BadDebtSummary memory badDebtSummary;\\n badDebtSummary.comptroller = comptrollerAddress;\\n badDebtSummary.badDebts = badDebts;\\n\\n // // Calculate the bad debt is USD per market\\n for (uint256 i; i < markets.length; ++i) {\\n BadDebt memory badDebt;\\n badDebt.vTokenAddress = address(markets[i]);\\n badDebt.badDebtUsd =\\n (VToken(address(markets[i])).badDebt() * priceOracle.getUnderlyingPrice(address(markets[i]))) /\\n EXP_SCALE;\\n badDebtSummary.badDebts[i] = badDebt;\\n totalBadDebtUsd = totalBadDebtUsd + badDebt.badDebtUsd;\\n }\\n\\n badDebtSummary.totalBadDebtUsd = totalBadDebtUsd;\\n\\n return badDebtSummary;\\n }\\n\\n /**\\n * @notice Queries the user's supply/borrow balances in the specified vToken\\n * @param vToken vToken address\\n * @param account The user Account\\n * @return A struct containing the balances data\\n */\\n function vTokenBalances(VToken vToken, address account) public returns (VTokenBalances memory) {\\n uint256 balanceOf = vToken.balanceOf(account);\\n uint256 borrowBalanceCurrent = vToken.borrowBalanceCurrent(account);\\n uint256 balanceOfUnderlying = vToken.balanceOfUnderlying(account);\\n uint256 tokenBalance;\\n uint256 tokenAllowance;\\n\\n IERC20 underlying = IERC20(vToken.underlying());\\n tokenBalance = underlying.balanceOf(account);\\n tokenAllowance = underlying.allowance(account, address(vToken));\\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 Queries additional information for the pool\\n * @param poolRegistryAddress Address of the PoolRegistry\\n * @param venusPool The VenusPool Object from PoolRegistry\\n * @return Enriched PoolData\\n */\\n function getPoolDataFromVenusPool(\\n address poolRegistryAddress,\\n PoolRegistry.VenusPool memory venusPool\\n ) public view returns (PoolData memory) {\\n // Get tokens in the Pool\\n ComptrollerInterface comptrollerInstance = ComptrollerInterface(venusPool.comptroller);\\n\\n VToken[] memory vTokens = comptrollerInstance.getAllMarkets();\\n\\n VTokenMetadata[] memory vTokenMetadataItems = vTokenMetadataAll(vTokens);\\n\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n\\n PoolRegistry.VenusPoolMetaData memory venusPoolMetaData = poolRegistryInterface.getVenusPoolMetadata(\\n venusPool.comptroller\\n );\\n\\n ComptrollerViewInterface comptrollerViewInstance = ComptrollerViewInterface(venusPool.comptroller);\\n\\n PoolData memory poolData = PoolData({\\n name: venusPool.name,\\n creator: venusPool.creator,\\n comptroller: venusPool.comptroller,\\n blockPosted: venusPool.blockPosted,\\n timestampPosted: venusPool.timestampPosted,\\n category: venusPoolMetaData.category,\\n logoURL: venusPoolMetaData.logoURL,\\n description: venusPoolMetaData.description,\\n vTokens: vTokenMetadataItems,\\n priceOracle: address(comptrollerViewInstance.oracle()),\\n closeFactor: comptrollerViewInstance.closeFactorMantissa(),\\n liquidationIncentive: comptrollerViewInstance.liquidationIncentiveMantissa(),\\n minLiquidatableCollateral: comptrollerViewInstance.minLiquidatableCollateral()\\n });\\n\\n return poolData;\\n }\\n\\n /**\\n * @notice Returns the metadata of VToken\\n * @param vToken The address of vToken\\n * @return VTokenMetadata struct\\n */\\n function vTokenMetadata(VToken vToken) public view returns (VTokenMetadata memory) {\\n uint256 exchangeRateCurrent = vToken.exchangeRateStored();\\n address comptrollerAddress = address(vToken.comptroller());\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\\n (bool isListed, uint256 collateralFactorMantissa) = comptroller.markets(address(vToken));\\n\\n address underlyingAssetAddress = vToken.underlying();\\n uint256 underlyingDecimals = IERC20Metadata(underlyingAssetAddress).decimals();\\n\\n uint256 pausedActions;\\n for (uint8 i; i <= uint8(type(Action).max); ++i) {\\n uint256 paused = ComptrollerInterface(comptrollerAddress).actionPaused(address(vToken), Action(i)) ? 1 : 0;\\n pausedActions |= paused << i;\\n }\\n\\n uint256 supplyRatePerBlock;\\n\\n if (vToken.totalSupply() > 0) {\\n supplyRatePerBlock = vToken.supplyRatePerBlock();\\n }\\n\\n return\\n VTokenMetadata({\\n vToken: address(vToken),\\n exchangeRateCurrent: exchangeRateCurrent,\\n supplyRatePerBlockOrTimestamp: supplyRatePerBlock,\\n borrowRatePerBlockOrTimestamp: vToken.borrowRatePerBlock(),\\n reserveFactorMantissa: vToken.reserveFactorMantissa(),\\n supplyCaps: comptroller.supplyCaps(address(vToken)),\\n borrowCaps: comptroller.borrowCaps(address(vToken)),\\n totalBorrows: vToken.totalBorrows(),\\n totalReserves: vToken.totalReserves(),\\n totalSupply: vToken.totalSupply(),\\n totalCash: vToken.getCash(),\\n isListed: isListed,\\n collateralFactorMantissa: collateralFactorMantissa,\\n underlyingAssetAddress: underlyingAssetAddress,\\n vTokenDecimals: vToken.decimals(),\\n underlyingDecimals: underlyingDecimals,\\n pausedActions: pausedActions\\n });\\n }\\n\\n /**\\n * @notice Returns the metadata of all VTokens\\n * @param vTokens The list of vToken addresses\\n * @return An array of VTokenMetadata structs\\n */\\n function vTokenMetadataAll(VToken[] memory vTokens) public view returns (VTokenMetadata[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenMetadata[] memory res = new VTokenMetadata[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenMetadata(vTokens[i]);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Returns the price data for the underlying asset of the specified vToken\\n * @param vToken vToken address\\n * @return The price data for each asset\\n */\\n function vTokenUnderlyingPrice(VToken vToken) public view returns (VTokenUnderlyingPrice memory) {\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(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 function _calculateNotDistributedAwards(\\n address account,\\n VToken[] memory markets,\\n RewardsDistributor rewardsDistributor\\n ) internal view returns (PendingReward[] memory) {\\n PendingReward[] memory pendingRewards = new PendingReward[](markets.length);\\n\\n for (uint256 i; i < markets.length; ++i) {\\n // Market borrow and supply state we will modify update in-memory, in order to not modify storage\\n RewardTokenState memory borrowState;\\n RewardTokenState memory supplyState;\\n\\n if (isTimeBased) {\\n (\\n borrowState.index,\\n borrowState.blockOrTimestamp,\\n borrowState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenBorrowStateTimeBased(address(markets[i]));\\n (\\n supplyState.index,\\n supplyState.blockOrTimestamp,\\n supplyState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenSupplyStateTimeBased(address(markets[i]));\\n } else {\\n (\\n borrowState.index,\\n borrowState.blockOrTimestamp,\\n borrowState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenBorrowState(address(markets[i]));\\n (\\n supplyState.index,\\n supplyState.blockOrTimestamp,\\n supplyState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenSupplyState(address(markets[i]));\\n }\\n\\n Exp memory marketBorrowIndex = Exp({ mantissa: markets[i].borrowIndex() });\\n\\n // Update market supply and borrow index in-memory\\n updateMarketBorrowIndex(address(markets[i]), rewardsDistributor, borrowState, marketBorrowIndex);\\n updateMarketSupplyIndex(address(markets[i]), rewardsDistributor, supplyState);\\n\\n // Calculate pending rewards\\n uint256 borrowReward = calculateBorrowerReward(\\n address(markets[i]),\\n rewardsDistributor,\\n account,\\n borrowState,\\n marketBorrowIndex\\n );\\n uint256 supplyReward = calculateSupplierReward(\\n address(markets[i]),\\n rewardsDistributor,\\n account,\\n supplyState\\n );\\n\\n PendingReward memory pendingReward;\\n pendingReward.vTokenAddress = address(markets[i]);\\n pendingReward.amount = borrowReward + supplyReward;\\n pendingRewards[i] = pendingReward;\\n }\\n return pendingRewards;\\n }\\n\\n function updateMarketBorrowIndex(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n RewardTokenState memory borrowState,\\n Exp memory marketBorrowIndex\\n ) internal view {\\n uint256 borrowSpeed = rewardsDistributor.rewardTokenBorrowSpeeds(vToken);\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (\\n borrowState.lastRewardingBlockOrTimestamp > 0 &&\\n blockNumberOrTimestamp > borrowState.lastRewardingBlockOrTimestamp\\n ) {\\n blockNumberOrTimestamp = borrowState.lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, borrowState.blockOrTimestamp);\\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\\n // Remove the total earned interest rate since the opening of the market from total borrows\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, borrowSpeed);\\n Double memory ratio = borrowAmount > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\\n } else if (deltaBlocksOrTimestamp > 0) {\\n borrowState.blockOrTimestamp = blockNumberOrTimestamp;\\n }\\n }\\n\\n function updateMarketSupplyIndex(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n RewardTokenState memory supplyState\\n ) internal view {\\n uint256 supplySpeed = rewardsDistributor.rewardTokenSupplySpeeds(vToken);\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (\\n supplyState.lastRewardingBlockOrTimestamp > 0 &&\\n blockNumberOrTimestamp > supplyState.lastRewardingBlockOrTimestamp\\n ) {\\n blockNumberOrTimestamp = supplyState.lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, supplyState.blockOrTimestamp);\\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, supplySpeed);\\n Double memory ratio = supplyTokens > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\\n } else if (deltaBlocksOrTimestamp > 0) {\\n supplyState.blockOrTimestamp = blockNumberOrTimestamp;\\n }\\n }\\n\\n function calculateBorrowerReward(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n address borrower,\\n RewardTokenState memory borrowState,\\n Exp memory marketBorrowIndex\\n ) internal view returns (uint256) {\\n Double memory borrowIndex = Double({ mantissa: borrowState.index });\\n Double memory borrowerIndex = Double({\\n mantissa: rewardsDistributor.rewardTokenBorrowerIndex(vToken, borrower)\\n });\\n if (borrowerIndex.mantissa == 0 && borrowIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set\\n borrowerIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\\n }\\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n return borrowerDelta;\\n }\\n\\n function calculateSupplierReward(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n address supplier,\\n RewardTokenState memory supplyState\\n ) internal view returns (uint256) {\\n Double memory supplyIndex = Double({ mantissa: supplyState.index });\\n Double memory supplierIndex = Double({\\n mantissa: rewardsDistributor.rewardTokenSupplierIndex(vToken, supplier)\\n });\\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\\n // Covers the case where users supplied tokens before the market's supply state index was set\\n supplierIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\\n }\\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n return supplierDelta;\\n }\\n}\\n\",\"keccak256\":\"0x2c696c531d8aeb2c58dbf3631f01602937621ac15c59080affe5b0808ba5f421\",\"license\":\"BSD-3-Clause\"},\"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\",\"keccak256\":\"0x4c25e30635485d162177effa384eee51768b0141a567a0da16ff6ad673274166\",\"license\":\"BSD-3-Clause\"},\"contracts/Pool/PoolRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\nimport { PoolRegistryInterface } from \\\"./PoolRegistryInterface.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"../lib/validators.sol\\\";\\n\\n/**\\n * @title PoolRegistry\\n * @author Venus\\n * @notice The Isolated Pools architecture centers around the `PoolRegistry` contract. The `PoolRegistry` maintains a directory of isolated lending\\n * pools and can perform actions like creating and registering new pools, adding new markets to existing pools, setting and updating the pool's required\\n * metadata, and providing the getter methods to get information on the pools.\\n *\\n * Isolated lending has three main components: PoolRegistry, pools, and markets. The PoolRegistry is responsible for managing pools.\\n * It can create new pools, update pool metadata and manage markets within pools. PoolRegistry contains getter methods to get the details of\\n * any existing pool like `getVTokenForAsset` and `getPoolsSupportedByAsset`. It also contains methods for updating pool metadata (`updatePoolMetadata`)\\n * and setting pool name (`setPoolName`).\\n *\\n * The directory of pools is managed through two mappings: `_poolByComptroller` which is a hashmap with the comptroller address as the key and `VenusPool` as\\n * the value and `_poolsByID` which is an array of comptroller addresses. Individual pools can be accessed by calling `getPoolByComptroller` with the pool's\\n * comptroller address. `_poolsByID` is used to iterate through all of the pools.\\n *\\n * PoolRegistry also contains a map of asset addresses called `_supportedPools` that maps to an array of assets suppored by each pool. This array of pools by\\n * asset is retrieved by calling `getPoolsSupportedByAsset`.\\n *\\n * PoolRegistry registers new isolated pools in the directory with the `createRegistryPool` method. Isolated pools are composed of independent markets with\\n * specific assets and custom risk management configurations according to their markets.\\n */\\ncontract PoolRegistry is Ownable2StepUpgradeable, AccessControlledV8, PoolRegistryInterface {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n struct AddMarketInput {\\n VToken vToken;\\n uint256 collateralFactor;\\n uint256 liquidationThreshold;\\n uint256 initialSupply;\\n address vTokenReceiver;\\n uint256 supplyCap;\\n uint256 borrowCap;\\n }\\n\\n uint256 internal constant MAX_POOL_NAME_LENGTH = 100;\\n\\n /**\\n * @notice Maps pool's comptroller address to metadata.\\n */\\n mapping(address => VenusPoolMetaData) public metadata;\\n\\n /**\\n * @dev Maps pool ID to pool's comptroller address\\n */\\n mapping(uint256 => address) private _poolsByID;\\n\\n /**\\n * @dev Total number of pools created.\\n */\\n uint256 private _numberOfPools;\\n\\n /**\\n * @dev Maps comptroller address to Venus pool Index.\\n */\\n mapping(address => VenusPool) private _poolByComptroller;\\n\\n /**\\n * @dev Maps pool's comptroller address to asset to vToken.\\n */\\n mapping(address => mapping(address => address)) private _vTokens;\\n\\n /**\\n * @dev Maps asset to list of supported pools.\\n */\\n mapping(address => address[]) private _supportedPools;\\n\\n /**\\n * @notice Emitted when a new Venus pool is added to the directory.\\n */\\n event PoolRegistered(address indexed comptroller, VenusPool pool);\\n\\n /**\\n * @notice Emitted when a pool name is set.\\n */\\n event PoolNameSet(address indexed comptroller, string oldName, string newName);\\n\\n /**\\n * @notice Emitted when a pool metadata is updated.\\n */\\n event PoolMetadataUpdated(\\n address indexed comptroller,\\n VenusPoolMetaData oldMetadata,\\n VenusPoolMetaData newMetadata\\n );\\n\\n /**\\n * @notice Emitted when a Market is added to the pool.\\n */\\n event MarketAdded(address indexed comptroller, address indexed vTokenAddress);\\n\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor() {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializes the deployer to owner\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(address accessControlManager_) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n /**\\n * @notice Adds a new Venus pool to the directory\\n * @dev Price oracle must be configured before adding a pool\\n * @param name The name of the pool\\n * @param comptroller Pool's Comptroller contract\\n * @param closeFactor The pool's close factor (scaled by 1e18)\\n * @param liquidationIncentive The pool's liquidation incentive (scaled by 1e18)\\n * @param minLiquidatableCollateral Minimal collateral for regular (non-batch) liquidations flow\\n * @return index The index of the registered Venus pool\\n * @custom:error ZeroAddressNotAllowed is thrown when Comptroller address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\\n */\\n function addPool(\\n string calldata name,\\n Comptroller comptroller,\\n uint256 closeFactor,\\n uint256 liquidationIncentive,\\n uint256 minLiquidatableCollateral\\n ) external virtual returns (uint256 index) {\\n _checkAccessAllowed(\\\"addPool(string,address,uint256,uint256,uint256)\\\");\\n // Input validation\\n ensureNonzeroAddress(address(comptroller));\\n ensureNonzeroAddress(address(comptroller.oracle()));\\n\\n uint256 poolId = _registerPool(name, address(comptroller));\\n\\n // Set Venus pool parameters\\n comptroller.setCloseFactor(closeFactor);\\n comptroller.setLiquidationIncentive(liquidationIncentive);\\n comptroller.setMinLiquidatableCollateral(minLiquidatableCollateral);\\n\\n return poolId;\\n }\\n\\n /**\\n * @notice Add a market to an existing pool and then mint to provide initial supply\\n * @param input The structure describing the parameters for adding a market to a pool\\n * @custom:error ZeroAddressNotAllowed is thrown when vToken address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when vTokenReceiver address is zero\\n */\\n function addMarket(AddMarketInput memory input) external {\\n _checkAccessAllowed(\\\"addMarket(AddMarketInput)\\\");\\n ensureNonzeroAddress(address(input.vToken));\\n ensureNonzeroAddress(input.vTokenReceiver);\\n require(input.initialSupply > 0, \\\"PoolRegistry: initialSupply is zero\\\");\\n\\n VToken vToken = input.vToken;\\n address vTokenAddress = address(vToken);\\n address comptrollerAddress = address(vToken.comptroller());\\n Comptroller comptroller = Comptroller(comptrollerAddress);\\n address underlyingAddress = vToken.underlying();\\n IERC20Upgradeable underlying = IERC20Upgradeable(underlyingAddress);\\n\\n require(_poolByComptroller[comptrollerAddress].creator != address(0), \\\"PoolRegistry: Pool not registered\\\");\\n // solhint-disable-next-line reason-string\\n require(\\n _vTokens[comptrollerAddress][underlyingAddress] == address(0),\\n \\\"PoolRegistry: Market already added for asset comptroller combination\\\"\\n );\\n\\n comptroller.supportMarket(vToken);\\n comptroller.setCollateralFactor(vToken, input.collateralFactor, input.liquidationThreshold);\\n\\n uint256[] memory newSupplyCaps = new uint256[](1);\\n uint256[] memory newBorrowCaps = new uint256[](1);\\n VToken[] memory vTokens = new VToken[](1);\\n\\n newSupplyCaps[0] = input.supplyCap;\\n newBorrowCaps[0] = input.borrowCap;\\n vTokens[0] = vToken;\\n\\n comptroller.setMarketSupplyCaps(vTokens, newSupplyCaps);\\n comptroller.setMarketBorrowCaps(vTokens, newBorrowCaps);\\n\\n _vTokens[comptrollerAddress][underlyingAddress] = vTokenAddress;\\n _supportedPools[underlyingAddress].push(comptrollerAddress);\\n\\n uint256 amountToSupply = _transferIn(underlying, msg.sender, input.initialSupply);\\n underlying.forceApprove(vTokenAddress, 0);\\n underlying.forceApprove(vTokenAddress, amountToSupply);\\n vToken.mintBehalf(input.vTokenReceiver, amountToSupply);\\n\\n emit MarketAdded(comptrollerAddress, vTokenAddress);\\n }\\n\\n /**\\n * @notice Modify existing Venus pool name\\n * @param comptroller Pool's Comptroller\\n * @param name New pool name\\n */\\n function setPoolName(address comptroller, string calldata name) external {\\n _checkAccessAllowed(\\\"setPoolName(address,string)\\\");\\n _ensureValidName(name);\\n VenusPool storage pool = _poolByComptroller[comptroller];\\n string memory oldName = pool.name;\\n pool.name = name;\\n emit PoolNameSet(comptroller, oldName, name);\\n }\\n\\n /**\\n * @notice Update metadata of an existing pool\\n * @param comptroller Pool's Comptroller\\n * @param metadata_ New pool metadata\\n */\\n function updatePoolMetadata(address comptroller, VenusPoolMetaData calldata metadata_) external {\\n _checkAccessAllowed(\\\"updatePoolMetadata(address,VenusPoolMetaData)\\\");\\n VenusPoolMetaData memory oldMetadata = metadata[comptroller];\\n metadata[comptroller] = metadata_;\\n emit PoolMetadataUpdated(comptroller, oldMetadata, metadata_);\\n }\\n\\n /**\\n * @notice Returns arrays of all Venus pools' data\\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\\n * @return A list of all pools within PoolRegistry, with details for each pool\\n */\\n function getAllPools() external view override returns (VenusPool[] memory) {\\n uint256 numberOfPools_ = _numberOfPools; // storage load to save gas\\n VenusPool[] memory _pools = new VenusPool[](numberOfPools_);\\n for (uint256 i = 1; i <= numberOfPools_; ++i) {\\n address comptroller = _poolsByID[i];\\n _pools[i - 1] = (_poolByComptroller[comptroller]);\\n }\\n return _pools;\\n }\\n\\n /**\\n * @param comptroller The comptroller proxy address associated to the pool\\n * @return Returns Venus pool\\n */\\n function getPoolByComptroller(address comptroller) external view override returns (VenusPool memory) {\\n return _poolByComptroller[comptroller];\\n }\\n\\n /**\\n * @param comptroller comptroller of Venus pool\\n * @return Returns Metadata of Venus pool\\n */\\n function getVenusPoolMetadata(address comptroller) external view override returns (VenusPoolMetaData memory) {\\n return metadata[comptroller];\\n }\\n\\n function getVTokenForAsset(address comptroller, address asset) external view override returns (address) {\\n return _vTokens[comptroller][asset];\\n }\\n\\n function getPoolsSupportedByAsset(address asset) external view override returns (address[] memory) {\\n return _supportedPools[asset];\\n }\\n\\n /**\\n * @dev Adds a new Venus pool to the directory (without checking msg.sender).\\n * @param name The name of the pool\\n * @param comptroller The pool's Comptroller proxy contract address\\n * @return The index of the registered Venus pool\\n */\\n function _registerPool(string calldata name, address comptroller) internal returns (uint256) {\\n VenusPool storage storedPool = _poolByComptroller[comptroller];\\n\\n require(storedPool.creator == address(0), \\\"PoolRegistry: Pool already exists in the directory.\\\");\\n _ensureValidName(name);\\n\\n ++_numberOfPools;\\n uint256 numberOfPools_ = _numberOfPools; // cache on stack to save storage read gas\\n\\n VenusPool memory pool = VenusPool(name, msg.sender, comptroller, block.number, block.timestamp);\\n\\n _poolsByID[numberOfPools_] = comptroller;\\n _poolByComptroller[comptroller] = pool;\\n\\n emit PoolRegistered(comptroller, pool);\\n return numberOfPools_;\\n }\\n\\n function _transferIn(IERC20Upgradeable token, address from, uint256 amount) internal returns (uint256) {\\n uint256 balanceBefore = token.balanceOf(address(this));\\n token.safeTransferFrom(from, address(this), amount);\\n uint256 balanceAfter = token.balanceOf(address(this));\\n return balanceAfter - balanceBefore;\\n }\\n\\n function _ensureValidName(string calldata name) internal pure {\\n require(bytes(name).length <= MAX_POOL_NAME_LENGTH, \\\"Pool's name is too large\\\");\\n }\\n}\\n\",\"keccak256\":\"0xafbb871f7b4db3ef439d846baa5f18a136192f9b43ea695c81262a77b06c4b25\",\"license\":\"BSD-3-Clause\"},\"contracts/Pool/PoolRegistryInterface.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 /**\\n * @notice Struct for a Venus interest rate pool metadata.\\n */\\n struct VenusPoolMetaData {\\n string category;\\n string logoURL;\\n string description;\\n }\\n\\n /// @notice Get all pools in PoolRegistry\\n function getAllPools() external view returns (VenusPool[] memory);\\n\\n /// @notice Get a pool by comptroller address\\n function getPoolByComptroller(address comptroller) external view returns (VenusPool memory);\\n\\n /// @notice Get the address of the VToken contract in the Pool where the underlying token is the provided 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 /// @notice Get the metadata of a Pool by comptroller address\\n function getVenusPoolMetadata(address comptroller) external view returns (VenusPoolMetaData memory);\\n}\\n\",\"keccak256\":\"0x7b39cda3b372a686501ce3c2aad288c6af410148110318249d75d4516729c92c\",\"license\":\"BSD-3-Clause\"},\"contracts/Rewards/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\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 { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"../MaxLoopsLimitHelper.sol\\\";\\nimport { RewardsDistributorStorage } from \\\"./RewardsDistributorStorage.sol\\\";\\n\\n/**\\n * @title `RewardsDistributor`\\n * @author Venus\\n * @notice Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol.\\n * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward\\n * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool.\\n * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward\\n * token to be released each slot (block or second) for borrowers and suppliers, which is distributed based on a user\\u2019s percentage of the borrows or supplies\\n * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting\\n * their contributor reward token speed, which similarly allocates a fixed amount of reward token per slot (block or second).\\n *\\n * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed\\n * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized\\n * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\\n */\\ncontract RewardsDistributor is\\n ExponentialNoError,\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n MaxLoopsLimitHelper,\\n RewardsDistributorStorage,\\n TimeManagerV8\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice The initial REWARD TOKEN index for a market\\n uint224 public constant INITIAL_INDEX = 1e36;\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a supplier\\n event DistributedSupplierRewardToken(\\n VToken indexed vToken,\\n address indexed supplier,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenSupplyIndex\\n );\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a borrower\\n event DistributedBorrowerRewardToken(\\n VToken indexed vToken,\\n address indexed borrower,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenBorrowIndex\\n );\\n\\n /// @notice Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when REWARD TOKEN is granted by admin\\n event RewardTokenGranted(address indexed recipient, uint256 amount);\\n\\n /// @notice Emitted when a new REWARD TOKEN speed is set for a contributor\\n event ContributorRewardTokenSpeedUpdated(address indexed contributor, uint256 newSpeed);\\n\\n /// @notice Emitted when a market is initialized\\n event MarketInitialized(address indexed vToken);\\n\\n /// @notice Emitted when a reward token supply index is updated\\n event RewardTokenSupplyIndexUpdated(address indexed vToken);\\n\\n /// @notice Emitted when a reward token borrow index is updated\\n event RewardTokenBorrowIndexUpdated(address indexed vToken, Exp marketBorrowIndex);\\n\\n /// @notice Emitted when a reward for contributor is updated\\n event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued);\\n\\n /// @notice Emitted when a reward token last rewarding block for supply is updated\\n event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding block for borrow is updated\\n event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding timestamp for supply is updated\\n event SupplyLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\\n\\n /// @notice Emitted when a reward token last rewarding timestamp for borrow is updated\\n event BorrowLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\\n\\n modifier onlyComptroller() {\\n require(address(comptroller) == msg.sender, \\\"Only comptroller can call this function\\\");\\n _;\\n }\\n\\n /**\\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice RewardsDistributor initializer\\n * @dev Initializes the deployer to owner\\n * @param comptroller_ Comptroller to attach the reward distributor to\\n * @param rewardToken_ Reward token to distribute\\n * @param loopsLimit_ Maximum number of iterations for the loops in this contract\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(\\n Comptroller comptroller_,\\n IERC20Upgradeable rewardToken_,\\n uint256 loopsLimit_,\\n address accessControlManager_\\n ) external initializer {\\n comptroller = comptroller_;\\n rewardToken = rewardToken_;\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n\\n _setMaxLoopsLimit(loopsLimit_);\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken\\n * @param vToken The address of the vToken to be initialized\\n * @custom:event MarketInitialized emits on success\\n * @custom:access Only Comptroller\\n */\\n function initializeMarket(address vToken) external onlyComptroller {\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n isTimeBased\\n ? _initializeMarketTimestampBased(vToken, blockNumberOrTimestamp)\\n : _initializeMarketBlockBased(vToken, safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\"));\\n\\n emit MarketInitialized(vToken);\\n }\\n\\n /*** Reward Token Distribution ***/\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them\\n * Borrowers will begin to accrue after the first interaction with the protocol.\\n * @dev This function should only be called when the user has a borrow position in the market\\n * (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook)\\n * We avoid an external call to check if they are in the market to save gas because this function is called in many places\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function distributeBorrowerRewardToken(\\n address vToken,\\n address borrower,\\n Exp memory marketBorrowIndex\\n ) external onlyComptroller {\\n _distributeBorrowerRewardToken(vToken, borrower, marketBorrowIndex);\\n }\\n\\n function updateRewardTokenSupplyIndex(address vToken) external onlyComptroller {\\n _updateRewardTokenSupplyIndex(vToken);\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the recipient\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\\n * @param recipient The address of the recipient to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n */\\n function grantRewardToken(address recipient, uint256 amount) external onlyOwner {\\n uint256 amountLeft = _grantRewardToken(recipient, amount);\\n require(amountLeft == 0, \\\"insufficient rewardToken for grant\\\");\\n emit RewardTokenGranted(recipient, amount);\\n }\\n\\n function updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) external onlyComptroller {\\n _updateRewardTokenBorrowIndex(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN borrow and supply speeds for the specified markets\\n * @param vTokens The markets whose REWARD TOKEN speed to update\\n * @param supplySpeeds New supply-side REWARD TOKEN speed for the corresponding market\\n * @param borrowSpeeds New borrow-side REWARD TOKEN speed for the corresponding market\\n */\\n function setRewardTokenSpeeds(\\n VToken[] memory vTokens,\\n uint256[] memory supplySpeeds,\\n uint256[] memory borrowSpeeds\\n ) external {\\n _checkAccessAllowed(\\\"setRewardTokenSpeeds(address[],uint256[],uint256[])\\\");\\n uint256 numTokens = vTokens.length;\\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \\\"invalid setRewardTokenSpeeds\\\");\\n\\n for (uint256 i; i < numTokens; ++i) {\\n _setRewardTokenSpeed(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for the specified markets, used when contract is block based\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market\\n * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market\\n */\\n function setLastRewardingBlocks(\\n VToken[] calldata vTokens,\\n uint32[] calldata supplyLastRewardingBlocks,\\n uint32[] calldata borrowLastRewardingBlocks\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlocks(address[],uint32[],uint32[])\\\");\\n require(!isTimeBased, \\\"Block-based operation only\\\");\\n\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length,\\n \\\"RewardsDistributor::setLastRewardingBlocks invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlock(vTokens[i], supplyLastRewardingBlocks[i], borrowLastRewardingBlocks[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block timestamp for the specified markets, used when contract is time based\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlockTimestamps New supply-side REWARD TOKEN last rewarding block timestamp for the corresponding market\\n * @param borrowLastRewardingBlockTimestamps New borrow-side REWARD TOKEN last rewarding block timestamp for the corresponding market\\n */\\n function setLastRewardingBlockTimestamps(\\n VToken[] calldata vTokens,\\n uint256[] calldata supplyLastRewardingBlockTimestamps,\\n uint256[] calldata borrowLastRewardingBlockTimestamps\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlockTimestamps(address[],uint256[],uint256[])\\\");\\n require(isTimeBased, \\\"Time-based operation only\\\");\\n\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlockTimestamps.length &&\\n numTokens == borrowLastRewardingBlockTimestamps.length,\\n \\\"RewardsDistributor::setLastRewardingBlockTimestamps invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlockTimestamp(\\n vTokens[i],\\n supplyLastRewardingBlockTimestamps[i],\\n borrowLastRewardingBlockTimestamps[i]\\n );\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single contributor\\n * @param contributor The contributor whose REWARD TOKEN speed to update\\n * @param rewardTokenSpeed New REWARD TOKEN speed for contributor\\n */\\n function setContributorRewardTokenSpeed(address contributor, uint256 rewardTokenSpeed) external onlyOwner {\\n // note that REWARD TOKEN speed could be set to 0 to halt liquidity rewards for a contributor\\n updateContributorRewards(contributor);\\n if (rewardTokenSpeed == 0) {\\n // release storage\\n delete lastContributorBlock[contributor];\\n } else {\\n lastContributorBlock[contributor] = getBlockNumberOrTimestamp();\\n }\\n rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed;\\n\\n emit ContributorRewardTokenSpeedUpdated(contributor, rewardTokenSpeed);\\n }\\n\\n function distributeSupplierRewardToken(address vToken, address supplier) external onlyComptroller {\\n _distributeSupplierRewardToken(vToken, supplier);\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in all markets\\n * @param holder The address to claim REWARD TOKEN for\\n */\\n function claimRewardToken(address holder) external {\\n return claimRewardToken(holder, comptroller.getAllMarkets());\\n }\\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) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Calculate additional accrued REWARD TOKEN for a contributor since last accrual\\n * @param contributor The address to calculate contributor rewards for\\n */\\n function updateContributorRewards(address contributor) public {\\n uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, lastContributorBlock[contributor]);\\n if (deltaBlocksOrTimestamp > 0 && rewardTokenSpeed > 0) {\\n uint256 newAccrued = mul_(deltaBlocksOrTimestamp, rewardTokenSpeed);\\n uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued);\\n\\n rewardTokenAccrued[contributor] = contributorAccrued;\\n lastContributorBlock[contributor] = blockNumberOrTimestamp;\\n\\n emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]);\\n }\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in the specified markets\\n * @param holder The address to claim REWARD TOKEN for\\n * @param vTokens The list of markets to claim REWARD TOKEN in\\n */\\n function claimRewardToken(address holder, VToken[] memory vTokens) public {\\n uint256 vTokensCount = vTokens.length;\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n VToken vToken = vTokens[i];\\n require(comptroller.isMarketListed(vToken), \\\"market must be listed\\\");\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n _distributeBorrowerRewardToken(address(vToken), holder, borrowIndex);\\n _updateRewardTokenSupplyIndex(address(vToken));\\n _distributeSupplierRewardToken(address(vToken), holder);\\n }\\n rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for a single market.\\n * @param vToken market's whose reward token last rewarding block to be updated\\n * @param supplyLastRewardingBlock New supply-side REWARD TOKEN last rewarding block for market\\n * @param borrowLastRewardingBlock New borrow-side REWARD TOKEN last rewarding block for market\\n */\\n function _setLastRewardingBlock(\\n VToken vToken,\\n uint32 supplyLastRewardingBlock,\\n uint32 borrowLastRewardingBlock\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockNumber = getBlockNumberOrTimestamp();\\n\\n require(supplyLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n require(borrowLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n\\n uint32 currentSupplyLastRewardingBlock = rewardTokenSupplyState[address(vToken)].lastRewardingBlock;\\n uint32 currentBorrowLastRewardingBlock = rewardTokenBorrowState[address(vToken)].lastRewardingBlock;\\n\\n require(\\n currentSupplyLastRewardingBlock == 0 || currentSupplyLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlock == 0 || currentBorrowLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlock != supplyLastRewardingBlock) {\\n rewardTokenSupplyState[address(vToken)].lastRewardingBlock = supplyLastRewardingBlock;\\n emit SupplyLastRewardingBlockUpdated(address(vToken), supplyLastRewardingBlock);\\n }\\n\\n if (currentBorrowLastRewardingBlock != borrowLastRewardingBlock) {\\n rewardTokenBorrowState[address(vToken)].lastRewardingBlock = borrowLastRewardingBlock;\\n emit BorrowLastRewardingBlockUpdated(address(vToken), borrowLastRewardingBlock);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding timestamp for a single market.\\n * @param vToken market's whose reward token last rewarding timestamp to be updated\\n * @param supplyLastRewardingBlockTimestamp New supply-side REWARD TOKEN last rewarding timestamp for market\\n * @param borrowLastRewardingBlockTimestamp New borrow-side REWARD TOKEN last rewarding timestamp for market\\n */\\n function _setLastRewardingBlockTimestamp(\\n VToken vToken,\\n uint256 supplyLastRewardingBlockTimestamp,\\n uint256 borrowLastRewardingBlockTimestamp\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockTimestamp = getBlockNumberOrTimestamp();\\n\\n require(\\n supplyLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"setting last rewarding timestamp in the past is not allowed\\\"\\n );\\n require(\\n borrowLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"setting last rewarding timestamp in the past is not allowed\\\"\\n );\\n\\n uint256 currentSupplyLastRewardingBlockTimestamp = rewardTokenSupplyStateTimeBased[address(vToken)]\\n .lastRewardingTimestamp;\\n uint256 currentBorrowLastRewardingBlockTimestamp = rewardTokenBorrowStateTimeBased[address(vToken)]\\n .lastRewardingTimestamp;\\n\\n require(\\n currentSupplyLastRewardingBlockTimestamp == 0 || currentSupplyLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlockTimestamp == 0 || currentBorrowLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlockTimestamp != supplyLastRewardingBlockTimestamp) {\\n rewardTokenSupplyStateTimeBased[address(vToken)].lastRewardingTimestamp = supplyLastRewardingBlockTimestamp;\\n emit SupplyLastRewardingBlockTimestampUpdated(address(vToken), supplyLastRewardingBlockTimestamp);\\n }\\n\\n if (currentBorrowLastRewardingBlockTimestamp != borrowLastRewardingBlockTimestamp) {\\n rewardTokenBorrowStateTimeBased[address(vToken)].lastRewardingTimestamp = borrowLastRewardingBlockTimestamp;\\n emit BorrowLastRewardingBlockTimestampUpdated(address(vToken), borrowLastRewardingBlockTimestamp);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single market.\\n * @param vToken market's whose reward token rate to be updated\\n * @param supplySpeed New supply-side REWARD TOKEN speed for market\\n * @param borrowSpeed New borrow-side REWARD TOKEN speed for market\\n */\\n function _setRewardTokenSpeed(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n if (rewardTokenSupplySpeeds[address(vToken)] != supplySpeed) {\\n // Supply speed updated so let's update supply state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n _updateRewardTokenSupplyIndex(address(vToken));\\n\\n // Update speed and emit event\\n rewardTokenSupplySpeeds[address(vToken)] = supplySpeed;\\n emit RewardTokenSupplySpeedUpdated(vToken, supplySpeed);\\n }\\n\\n if (rewardTokenBorrowSpeeds[address(vToken)] != borrowSpeed) {\\n // Borrow speed updated so let's update borrow state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n\\n // Update speed and emit event\\n rewardTokenBorrowSpeeds[address(vToken)] = borrowSpeed;\\n emit RewardTokenBorrowSpeedUpdated(vToken, borrowSpeed);\\n }\\n }\\n\\n /**\\n * @notice Calculate REWARD TOKEN 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 REWARD TOKEN to\\n */\\n function _distributeSupplierRewardToken(address vToken, address supplier) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\\n\\n uint256 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\\n uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier];\\n\\n // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenSupplierIndex[vToken][supplier] = supplyIndex;\\n\\n if (supplierIndex == 0 && supplyIndex >= INITIAL_INDEX) {\\n // Covers the case where users supplied tokens before the market's supply state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when supplier rewards were first\\n // set for the market.\\n supplierIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per vToken accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\\n\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerVToken\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n\\n uint256 supplierAccrued = add_(rewardTokenAccrued[supplier], supplierDelta);\\n rewardTokenAccrued[supplier] = supplierAccrued;\\n\\n emit DistributedSupplierRewardToken(VToken(vToken), supplier, supplierDelta, supplierAccrued, supplyIndex);\\n }\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them.\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function _distributeBorrowerRewardToken(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\\n\\n uint256 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\\n uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower];\\n\\n // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenBorrowerIndex[vToken][borrower] = borrowIndex;\\n\\n if (borrowerIndex == 0 && borrowIndex >= INITIAL_INDEX) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when borrower rewards were first\\n // set for the market.\\n borrowerIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per borrowed unit accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\\n\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerBorrowedUnit\\n if (borrowerAmount != 0) {\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n\\n uint256 borrowerAccrued = add_(rewardTokenAccrued[borrower], borrowerDelta);\\n rewardTokenAccrued[borrower] = borrowerAccrued;\\n\\n emit DistributedBorrowerRewardToken(VToken(vToken), borrower, borrowerDelta, borrowerAccrued, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the user.\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all.\\n * @param user The address of the user to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n * @return The amount of REWARD TOKEN which was NOT transferred to the user\\n */\\n function _grantRewardToken(address user, uint256 amount) internal returns (uint256) {\\n uint256 rewardTokenRemaining = rewardToken.balanceOf(address(this));\\n if (amount > 0 && amount <= rewardTokenRemaining) {\\n rewardToken.safeTransfer(user, amount);\\n return 0;\\n }\\n return amount;\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the supply index\\n * @param vToken The market whose supply index to update\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenSupplyIndex(address vToken) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\\n\\n uint256 supplySpeed = rewardTokenSupplySpeeds[vToken];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (!isTimeBased) {\\n safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\");\\n }\\n\\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\\n ? supplyStateTimeBased.lastRewardingTimestamp\\n : uint256(supplyState.lastRewardingBlock);\\n\\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(\\n blockNumberOrTimestamp,\\n (isTimeBased ? supplyStateTimeBased.timestamp : uint256(supplyState.block))\\n );\\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, supplySpeed);\\n Double memory ratio = supplyTokens > 0\\n ? fraction(accruedSinceUpdate, supplyTokens)\\n : Double({ mantissa: 0 });\\n uint224 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\\n uint224 index = safe224(\\n add_(Double({ mantissa: supplyIndex }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n\\n if (isTimeBased) {\\n supplyStateTimeBased.index = index;\\n supplyStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n supplyState.index = index;\\n supplyState.block = uint32(blockNumberOrTimestamp);\\n }\\n } else if (deltaBlocksOrTimestamp > 0) {\\n isTimeBased ? supplyStateTimeBased.timestamp = blockNumberOrTimestamp : supplyState.block = uint32(\\n blockNumberOrTimestamp\\n );\\n }\\n\\n emit RewardTokenSupplyIndexUpdated(vToken);\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the borrow index\\n * @param vToken The market whose borrow index to update\\n * @param marketBorrowIndex The current global borrow index of vToken\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\\n\\n uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (!isTimeBased) {\\n safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\");\\n }\\n\\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\\n ? borrowStateTimeBased.lastRewardingTimestamp\\n : uint256(borrowState.lastRewardingBlock);\\n\\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(\\n blockNumberOrTimestamp,\\n (isTimeBased ? borrowStateTimeBased.timestamp : uint256(borrowState.block))\\n );\\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, borrowSpeed);\\n Double memory ratio = borrowAmount > 0\\n ? fraction(accruedSinceUpdate, borrowAmount)\\n : Double({ mantissa: 0 });\\n uint224 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\\n uint224 index = safe224(\\n add_(Double({ mantissa: borrowIndex }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n\\n if (isTimeBased) {\\n borrowStateTimeBased.index = index;\\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n borrowState.index = index;\\n borrowState.block = uint32(blockNumberOrTimestamp);\\n }\\n } else if (deltaBlocksOrTimestamp > 0) {\\n if (isTimeBased) {\\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n borrowState.block = uint32(blockNumberOrTimestamp);\\n }\\n }\\n\\n emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken called when contract is block-based\\n * @param vToken The address of the vToken to be initialized\\n * @param blockNumber current block number\\n */\\n function _initializeMarketBlockBased(address vToken, uint32 blockNumber) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n RewardToken storage borrowState = rewardTokenBorrowState[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 = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block numbers\\n */\\n supplyState.block = borrowState.block = blockNumber;\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken called when contract is time-based\\n * @param vToken The address of the vToken to be initialized\\n * @param blockTimestamp current block timestamp\\n */\\n function _initializeMarketTimestampBased(address vToken, uint256 blockTimestamp) internal {\\n TimeBasedRewardToken storage supplyState = rewardTokenSupplyStateTimeBased[vToken];\\n TimeBasedRewardToken storage borrowState = rewardTokenBorrowStateTimeBased[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 = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block timestamp\\n */\\n supplyState.timestamp = borrowState.timestamp = blockTimestamp;\\n }\\n}\\n\",\"keccak256\":\"0x3cc824e59c923cfe25c4f1a875959b7e9410cde8e73cd405de13f301298c697f\",\"license\":\"BSD-3-Clause\"},\"contracts/Rewards/RewardsDistributorStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\n\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\n\\n/**\\n * @title RewardsDistributorStorage\\n * @author Venus\\n * @dev Storage for RewardsDistributor\\n */\\ncontract RewardsDistributorStorage {\\n struct RewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number the index was last updated at\\n uint32 block;\\n // The block number at which to stop rewards\\n uint32 lastRewardingBlock;\\n }\\n\\n struct TimeBasedRewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block timestamp the index was last updated at\\n uint256 timestamp;\\n // The block timestamp at which to stop rewards\\n uint256 lastRewardingTimestamp;\\n }\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => RewardToken) public rewardTokenSupplyState;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex;\\n\\n /// @notice The REWARD TOKEN accrued but not yet transferred to each user\\n mapping(address => uint256) public rewardTokenAccrued;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding borrow market per slot (block or second)\\n mapping(address => uint256) public rewardTokenBorrowSpeeds;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding supply market per slot (block or second)\\n mapping(address => uint256) public rewardTokenSupplySpeeds;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => RewardToken) public rewardTokenBorrowState;\\n\\n /// @notice The portion of REWARD TOKEN that each contributor receives per slot (block or second)\\n mapping(address => uint256) public rewardTokenContributorSpeeds;\\n\\n /// @notice Last slot (block or second) at which a contributor's REWARD TOKEN rewards have been allocated\\n mapping(address => uint256) public lastContributorBlock;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex;\\n\\n Comptroller internal comptroller;\\n\\n IERC20Upgradeable public rewardToken;\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => TimeBasedRewardToken) public rewardTokenSupplyStateTimeBased;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => TimeBasedRewardToken) public rewardTokenBorrowStateTimeBased;\\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[37] private __gap;\\n}\\n\",\"keccak256\":\"0x70e5015a78a2acf95277949c8b4796e10b9ac194130be006d5e5217e158070c0\",\"license\":\"BSD-3-Clause\"},\"contracts/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\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 { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"@venusprotocol/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\\\";\\n\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { ComptrollerInterface, ComptrollerViewInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"./ErrorReporter.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title VToken\\n * @author Venus\\n * @notice Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview,\\n * each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of\\n * the pool. The main actions a user regularly interacts with in a market are:\\n\\n- mint/redeem of vTokens;\\n- transfer of vTokens;\\n- borrow/repay a loan on an underlying asset;\\n- liquidate a borrow or liquidate/heal an account.\\n\\n * A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`.\\n * The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted\\n * `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken`\\n * as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that\\n * a user may borrow up to a portion of their collateral determined by the market\\u2019s collateral factor. However, if their borrowed amount exceeds an amount\\n * calculated using the market\\u2019s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also\\n * pay off interest accrued on the borrow.\\n * \\n * The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller`\\n * and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a\\n * total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`.\\n * Both functions settle all of an account\\u2019s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of\\n * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\\n */\\ncontract VToken is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n VTokenInterface,\\n ExponentialNoError,\\n TokenErrorReporter,\\n TimeManagerV8\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5%\\n\\n // Maximum fraction of interest that can be set aside for reserves\\n uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18;\\n\\n // Maximum borrow rate that can ever be applied per slot(block or second)\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n uint256 internal immutable MAX_BORROW_RATE_MANTISSA;\\n\\n /**\\n * Reentrancy Guard **\\n */\\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 * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @param maxBorrowRateMantissa_ The maximum value of borrowing rate mantissa\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(\\n bool timeBased_,\\n uint256 blocksPerYear_,\\n uint256 maxBorrowRateMantissa_\\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n require(maxBorrowRateMantissa_ <= 1e18, \\\"Max borrow rate must be <= 1e18\\\");\\n\\n MAX_BORROW_RATE_MANTISSA = maxBorrowRateMantissa_;\\n _disableInitializers();\\n }\\n\\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_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n */\\n function initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) external initializer {\\n ensureNonzeroAddress(admin_);\\n\\n // Initialize the market\\n _initialize(\\n underlying_,\\n comptroller_,\\n interestRateModel_,\\n initialExchangeRateMantissa_,\\n name_,\\n symbol_,\\n decimals_,\\n admin_,\\n accessControlManager_,\\n riskManagement,\\n reserveFactorMantissa_\\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 * @return success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, msg.sender, dst, amount);\\n return true;\\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 success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, src, dst, amount);\\n return true;\\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 (uint256.max means infinite)\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Increase approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param addedValue The number of additional tokens spender can transfer\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function increaseAllowance(address spender, uint256 addedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 newAllowance = transferAllowances[src][spender];\\n newAllowance += addedValue;\\n transferAllowances[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n return true;\\n }\\n\\n /**\\n * @notice Decreases approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param subtractedValue The number of tokens to remove from total approval\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 currentAllowance = transferAllowances[src][spender];\\n require(currentAllowance >= subtractedValue, \\\"decreased allowance below zero\\\");\\n unchecked {\\n currentAllowance -= subtractedValue;\\n }\\n\\n transferAllowances[src][spender] = currentAllowance;\\n\\n emit Approval(src, spender, currentAllowance);\\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 amount The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint256) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return totalBorrows The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\\n accrueInterest();\\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 borrowBalance The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n return _borrowBalanceStored(account);\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function mint(uint256 mintAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _mintFresh(msg.sender, msg.sender, mintAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param minter User whom the supply will be attributed to\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when minter address is zero\\n */\\n function mintBehalf(address minter, uint256 mintAmount) external override nonReentrant returns (uint256) {\\n ensureNonzeroAddress(minter);\\n\\n accrueInterest();\\n\\n _mintFresh(msg.sender, minter, mintAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function redeem(uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _redeemFresh(msg.sender, msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function redeemBehalf(address redeemer, uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n _ensureSenderIsDelegateOf(redeemer);\\n\\n accrueInterest();\\n\\n _redeemFresh(redeemer, msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\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 receive from redeeming vTokens\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n */\\n function redeemUnderlying(uint256 redeemAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _redeemFresh(msg.sender, msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function redeemUnderlyingBehalf(\\n address redeemer,\\n uint256 redeemAmount\\n ) external override nonReentrant returns (uint256) {\\n _ensureSenderIsDelegateOf(redeemer);\\n\\n accrueInterest();\\n\\n _redeemFresh(redeemer, msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function borrow(uint256 borrowAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _borrowFresh(msg.sender, msg.sender, borrowAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error DelegateNotApproved is thrown if caller is not approved delegate\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function borrowBehalf(address borrower, uint256 borrowAmount) external override returns (uint256) {\\n _ensureSenderIsDelegateOf(borrower);\\n accrueInterest();\\n\\n _borrowFresh(borrower, msg.sender, borrowAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrow(uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n return NO_ERROR;\\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, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _repayBorrowFresh(msg.sender, borrower, repayAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Not restricted\\n */\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external override returns (uint256) {\\n _liquidateBorrow(msg.sender, borrower, repayAmount, vTokenCollateral, false);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice sets protocol share accumulated from liquidations\\n * @dev must be equal or less than liquidation incentive - 1\\n * @param newProtocolSeizeShareMantissa_ new protocol share mantissa\\n * @custom:event Emits NewProtocolSeizeShare event on success\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error ProtocolSeizeShareTooBig is thrown when the new seize share is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa_) external {\\n _checkAccessAllowed(\\\"setProtocolSeizeShare(uint256)\\\");\\n uint256 liquidationIncentive = ComptrollerViewInterface(address(comptroller)).liquidationIncentiveMantissa();\\n if (newProtocolSeizeShareMantissa_ + MANTISSA_ONE > liquidationIncentive) {\\n revert ProtocolSeizeShareTooBig();\\n }\\n\\n uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\\n protocolSeizeShareMantissa = newProtocolSeizeShareMantissa_;\\n emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa_);\\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 * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n * @custom:event Emits NewReserveFactor event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant {\\n _checkAccessAllowed(\\\"setReserveFactor(uint256)\\\");\\n\\n accrueInterest();\\n _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to the protocol reserve contract\\n * @dev Gracefully return if reserves already reduced in accrueInterest\\n * @param reduceAmount Amount of reduction to reserves\\n * @custom:event Emits ReservesReduced event; may emit AccrueInterest\\n * @custom:error ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash\\n * @custom:error ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\\n * @custom:access Not restricted\\n */\\n function reduceReserves(uint256 reduceAmount) external override nonReentrant {\\n accrueInterest();\\n if (reduceReservesBlockNumber == getBlockNumberOrTimestamp()) return;\\n _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice The sender adds to reserves.\\n * @param addAmount The amount of underlying token to add as reserves\\n * @custom:event Emits ReservesAdded event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function addReserves(uint256 addAmount) external override nonReentrant {\\n accrueInterest();\\n _addReservesFresh(addAmount);\\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 * @custom:event Emits NewMarketInterestRateModel event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external override {\\n _checkAccessAllowed(\\\"setInterestRateModel(address)\\\");\\n\\n accrueInterest();\\n _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially\\n * \\\"forgiving\\\" the borrower. Healing is a situation that should rarely happen. However, some pools\\n * may list risky assets or be configured improperly \\u2013 we want to still handle such cases gracefully.\\n * We assume that Comptroller does the seizing, so this function is only available to Comptroller.\\n * @dev This function does not call any Comptroller hooks (like \\\"healAllowed\\\"), because we assume\\n * the Comptroller does all the necessary checks before calling this function.\\n * @param payer account who repays the debt\\n * @param borrower account to heal\\n * @param repayAmount amount to repay\\n * @custom:event Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\\n * @custom:error HealBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:access Only Comptroller\\n */\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external override nonReentrant {\\n if (repayAmount != 0) {\\n comptroller.preRepayHook(address(this), borrower);\\n }\\n\\n if (msg.sender != address(comptroller)) {\\n revert HealBorrowUnauthorized();\\n }\\n\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 totalBorrowsNew = totalBorrows;\\n\\n uint256 actualRepayAmount;\\n if (repayAmount != 0) {\\n // _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // We violate checks-effects-interactions here to account for tokens that take transfer fees\\n actualRepayAmount = _doTransferIn(payer, repayAmount);\\n totalBorrowsNew = totalBorrowsNew - actualRepayAmount;\\n emit RepayBorrow(\\n payer,\\n borrower,\\n actualRepayAmount,\\n accountBorrowsPrev - actualRepayAmount,\\n totalBorrowsNew\\n );\\n }\\n\\n // The transaction will fail if trying to repay too much\\n uint256 badDebtDelta = accountBorrowsPrev - actualRepayAmount;\\n if (badDebtDelta != 0) {\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld + badDebtDelta;\\n totalBorrowsNew = totalBorrowsNew - badDebtDelta;\\n badDebt = badDebtNew;\\n\\n // We treat healing as \\\"repayment\\\", where vToken is the payer\\n emit RepayBorrow(address(this), borrower, badDebtDelta, 0, totalBorrowsNew);\\n emit BadDebtIncreased(borrower, badDebtDelta, badDebtOld, badDebtNew);\\n }\\n\\n accountBorrows[borrower].principal = 0;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n emit HealBorrow(payer, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice The extended version of liquidations, callable only by Comptroller. May skip\\n * the close factor check. The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Only Comptroller\\n */\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) external override {\\n if (msg.sender != address(comptroller)) {\\n revert ForceLiquidateBorrowUnauthorized();\\n }\\n _liquidateBorrow(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\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 * @custom:event Emits Transfer, ReservesAdded events\\n * @custom:error LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:access Not restricted\\n */\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external override nonReentrant {\\n _seize(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Updates bad debt\\n * @dev Called only when bad debt is recovered from auction\\n * @param recoveredAmount_ The amount of bad debt recovered\\n * @custom:event Emits BadDebtRecovered event\\n * @custom:access Only Shortfall contract\\n */\\n function badDebtRecovered(uint256 recoveredAmount_) external {\\n require(msg.sender == shortfall, \\\"only shortfall contract can update bad debt\\\");\\n require(recoveredAmount_ <= badDebt, \\\"more than bad debt recovered from auction\\\");\\n\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld - recoveredAmount_;\\n badDebt = badDebtNew;\\n\\n emit BadDebtRecovered(badDebtOld, badDebtNew);\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protocolShareReserve_ The address of the protocol share reserve contract\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n * @custom:access Only Governance\\n */\\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\\n _setProtocolShareReserve(protocolShareReserve_);\\n }\\n\\n /**\\n * @notice Sets shortfall contract address\\n * @param shortfall_ The address of the shortfall contract\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:access Only Governance\\n */\\n function setShortfallContract(address shortfall_) external onlyOwner {\\n _setShortfallContract(shortfall_);\\n }\\n\\n /**\\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\\n * @param token The address of the ERC-20 token to sweep\\n * @custom:access Only Governance\\n */\\n function sweepToken(IERC20Upgradeable token) external override {\\n require(msg.sender == owner(), \\\"VToken::sweepToken: only admin can sweep tokens\\\");\\n require(address(token) != underlying, \\\"VToken::sweepToken: can not sweep underlying token\\\");\\n uint256 balance = token.balanceOf(address(this));\\n token.safeTransfer(owner(), balance);\\n\\n emit SweepToken(address(token));\\n }\\n\\n /**\\n * @notice A public function to set new threshold of slot(block or second) difference after which funds will be sent to the protocol share reserve\\n * @param _newReduceReservesBlockOrTimestampDelta slot(block or second) difference value\\n * @custom:access Only Governance\\n */\\n function setReduceReservesBlockDelta(uint256 _newReduceReservesBlockOrTimestampDelta) external {\\n _checkAccessAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n require(_newReduceReservesBlockOrTimestampDelta > 0, \\\"Invalid Input\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, _newReduceReservesBlockOrTimestampDelta);\\n reduceReservesBlockDelta = _newReduceReservesBlockOrTimestampDelta;\\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 amount 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 amount 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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return vTokenBalance User's balance of vTokens\\n * @return borrowBalance Amount owed in terms of underlying\\n * @return exchangeRate Stored exchange rate\\n */\\n function getAccountSnapshot(\\n address account\\n )\\n external\\n view\\n override\\n returns (uint256 error, uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRate)\\n {\\n return (NO_ERROR, accountTokens[account], _borrowBalanceStored(account), _exchangeRateStored());\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return cash The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint256) {\\n return _getCashPrior();\\n }\\n\\n /**\\n * @notice Returns the current per slot(block or second) borrow interest rate for this vToken\\n * @return rate The borrow interest rate per slot(block or second), scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint256) {\\n return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt);\\n }\\n\\n /**\\n * @notice Returns the current per-slot(block or second) supply interest rate for this v\\n * @return rate The supply interest rate per slot(block or second), scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint256) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPrior(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa,\\n badDebt\\n );\\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 borrowBalance The calculated balance\\n */\\n function borrowBalanceStored(address account) external view override returns (uint256) {\\n return _borrowBalanceStored(account);\\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 exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() external view override returns (uint256) {\\n return _exchangeRateStored();\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\\n accrueInterest();\\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 slot(block or second)\\n * up to the current slot(block or second) and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentSlot - reduceReservesBlockNumber >= slotDelta\\n * @return Always NO_ERROR\\n * @custom:event Emits AccrueInterest event on success\\n * @custom:access Not restricted\\n */\\n function accrueInterest() public virtual override returns (uint256) {\\n /* Remember the initial block number or timestamp */\\n uint256 currentSlotNumber = getBlockNumberOrTimestamp();\\n uint256 accrualSlotNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualSlotNumberPrior == currentSlotNumber) {\\n return NO_ERROR;\\n }\\n\\n /* Read the previous values out of storage */\\n uint256 cashPrior = _getCashPrior();\\n uint256 borrowsPrior = totalBorrows;\\n uint256 reservesPrior = totalReserves;\\n uint256 borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt);\\n require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of slots elapsed since the last accrual */\\n uint256 slotDelta = currentSlotNumber - accrualSlotNumberPrior;\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * slotDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), slotDelta);\\n uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\\n uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;\\n uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentSlotNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n if (currentSlotNumber - reduceReservesBlockNumber >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentSlotNumber;\\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 NO_ERROR;\\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 or timestamp\\n * @param payer The address of the account which is sending the assets for supply\\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 */\\n function _mintFresh(address payer, address minter, uint256 mintAmount) internal {\\n /* Fail if mint not allowed */\\n comptroller.preMintHook(address(this), minter, mintAmount);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert MintFreshnessCheck();\\n }\\n\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\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 * `_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 uint256 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 uint256 mintTokens = div_(actualMintAmount, exchangeRate);\\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 * And write them into storage\\n */\\n totalSupply = totalSupply + mintTokens;\\n uint256 balanceAfter = accountTokens[minter] + mintTokens;\\n accountTokens[minter] = balanceAfter;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, actualMintAmount, mintTokens, balanceAfter);\\n emit Transfer(address(0), minter, mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, actualMintAmount, mintTokens);\\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 Comptroller.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current slot(block or second)\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the underlying 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 */\\n function _redeemFresh(address redeemer, address receiver, uint256 redeemTokensIn, uint256 redeemAmountIn) internal {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert RedeemFreshnessCheck();\\n }\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n\\n uint256 redeemTokens;\\n uint256 redeemAmount;\\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 */\\n redeemTokens = redeemTokensIn;\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n */\\n redeemTokens = div_(redeemAmountIn, exchangeRate);\\n\\n uint256 _redeemAmount = mul_(redeemTokens, exchangeRate);\\n if (_redeemAmount != 0 && _redeemAmount != redeemAmountIn) redeemTokens++; // round up\\n }\\n\\n // redeemAmount = exchangeRate * redeemTokens\\n redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokens);\\n\\n // Revert if amount is zero\\n if (redeemAmount == 0) {\\n revert(\\\"redeemAmount is zero\\\");\\n }\\n\\n /* Fail if redeem not allowed */\\n comptroller.preRedeemHook(address(this), redeemer, redeemTokens);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (_getCashPrior() - totalReserves < redeemAmount) {\\n revert RedeemTransferOutNotPossible();\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\\n */\\n totalSupply = totalSupply - redeemTokens;\\n uint256 balanceAfter = accountTokens[redeemer] - redeemTokens;\\n accountTokens[redeemer] = balanceAfter;\\n\\n /*\\n * We invoke _doTransferOut for the receiver and the redeemAmount.\\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 _doTransferOut(receiver, redeemAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), redeemTokens);\\n emit Redeem(redeemer, redeemAmount, redeemTokens, balanceAfter);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, redeemAmount, redeemTokens);\\n }\\n\\n /**\\n * @notice Users or their delegates borrow assets from the protocol\\n * @param borrower User who borrows the assets\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param borrowAmount The amount of the underlying asset to borrow\\n */\\n function _borrowFresh(address borrower, address receiver, uint256 borrowAmount) internal {\\n /* Fail if borrow not allowed */\\n comptroller.preBorrowHook(address(this), borrower, borrowAmount);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert BorrowFreshnessCheck();\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (_getCashPrior() - totalReserves < borrowAmount) {\\n revert BorrowCashNotAvailable();\\n }\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowNew = accountBorrow + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;\\n uint256 totalBorrowsNew = totalBorrows + borrowAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\\n `*/\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /*\\n * We invoke _doTransferOut for the receiver and the borrowAmount.\\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, accountBorrowsNew, totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\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 underlying tokens being returned, or type(uint256).max for the full outstanding amount\\n * @return (uint) the actual repayment amount.\\n */\\n function _repayBorrowFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256) {\\n /* Fail if repayBorrow not allowed */\\n comptroller.preRepayHook(address(this), borrower);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert RepayBorrowFreshnessCheck();\\n }\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n\\n uint256 repayAmountFinal = repayAmount >= accountBorrowsPrev ? accountBorrowsPrev : 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 * 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 uint256 actualRepayAmount = _doTransferIn(payer, repayAmountFinal);\\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 uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\\n uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, actualRepayAmount, borrowIndex);\\n\\n return actualRepayAmount;\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal nonReentrant {\\n accrueInterest();\\n\\n uint256 error = vTokenCollateral.accrueInterest();\\n if (error != NO_ERROR) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n revert LiquidateAccrueCollateralInterestFailed(error);\\n }\\n\\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal {\\n /* Fail if liquidate not allowed */\\n comptroller.preLiquidateHook(\\n address(this),\\n address(vTokenCollateral),\\n borrower,\\n repayAmount,\\n skipLiquidityCheck\\n );\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert LiquidateFreshnessCheck();\\n }\\n\\n /* Verify vTokenCollateral market's slot(block or second) number equals current slot(block or second) number */\\n if (vTokenCollateral.accrualBlockNumber() != getBlockNumberOrTimestamp()) {\\n revert LiquidateCollateralFreshnessCheck();\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateLiquidatorIsBorrower();\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n revert LiquidateCloseAmountIsZero();\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n revert LiquidateCloseAmountIsUintMax();\\n }\\n\\n /* Fail if repayBorrow fails */\\n uint256 actualRepayAmount = _repayBorrowFresh(liquidator, borrower, repayAmount);\\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.liquidateCalculateSeizeTokens(\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n require(amountSeizeError == 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, call _seize internally to avoid re-entrancy, otherwise make an external call\\n if (address(vTokenCollateral) == address(this)) {\\n _seize(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\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\\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 * It's absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerContract The contract seizing the collateral (either borrowed vToken or Comptroller)\\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 */\\n function _seize(address seizerContract, address liquidator, address borrower, uint256 seizeTokens) internal {\\n /* Fail if seize not allowed */\\n comptroller.preSeizeHook(address(this), seizerContract, liquidator, borrower);\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateSeizeLiquidatorIsBorrower();\\n }\\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 uint256 liquidationIncentiveMantissa = ComptrollerViewInterface(address(comptroller))\\n .liquidationIncentiveMantissa();\\n uint256 numerator = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));\\n uint256 protocolSeizeTokens = div_(numerator, Exp({ mantissa: liquidationIncentiveMantissa }));\\n uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n uint256 protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the calculated values into storage */\\n totalSupply = totalSupply - protocolSeizeTokens;\\n accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\\n accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\\n\\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, protocolSeizeAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.LIQUIDATION\\n );\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\\n emit ProtocolSeize(borrower, protocolShareReserve, protocolSeizeAmount);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerContract, liquidator, borrower, seizeTokens);\\n }\\n\\n function _setComptroller(ComptrollerInterface newComptroller) internal {\\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\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n */\\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal {\\n // Verify market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert SetReserveFactorFreshCheck();\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > MAX_RESERVE_FACTOR_MANTISSA) {\\n revert SetReserveFactorBoundsCheck();\\n }\\n\\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\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 actualAddAmount The actual amount added, excluding the potential token fees\\n */\\n function _addReservesFresh(uint256 addAmount) internal returns (uint256) {\\n // totalReserves + actualAddAmount\\n uint256 totalReservesNew;\\n uint256 actualAddAmount;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert AddReservesFactorFreshCheck(actualAddAmount);\\n }\\n\\n actualAddAmount = _doTransferIn(msg.sender, addAmount);\\n totalReservesNew = totalReserves + actualAddAmount;\\n totalReserves = totalReservesNew;\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n return actualAddAmount;\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to the protocol reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n */\\n function _reduceReservesFresh(uint256 reduceAmount) internal {\\n if (reduceAmount == 0) {\\n return;\\n }\\n // totalReserves - reduceAmount\\n uint256 totalReservesNew;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert ReduceReservesFreshCheck();\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (_getCashPrior() < reduceAmount) {\\n revert ReduceReservesCashNotAvailable();\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n revert ReduceReservesCashValidation();\\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 // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, reduceAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit SpreadReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal {\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert SetInterestRateModelFreshCheck();\\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\\n /**\\n * Safe Token **\\n */\\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 returns (uint256) {\\n IERC20Upgradeable token = IERC20Upgradeable(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 to, uint256 amount) internal virtual {\\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\\n token.safeTransfer(to, amount);\\n }\\n\\n /**\\n * @notice Transfer `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 */\\n function _transferTokens(address spender, address src, address dst, uint256 tokens) internal {\\n /* Fail if transfer not allowed */\\n comptroller.preTransferHook(address(this), src, dst, tokens);\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n revert TransferNotAllowed();\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint256 startingAllowance;\\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 uint256 allowanceNew = startingAllowance - tokens;\\n uint256 srcTokensNew = accountTokens[src] - tokens;\\n uint256 dstTokensNew = accountTokens[dst] + tokens;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n\\n accountTokens[src] = srcTokensNew;\\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\\n /**\\n * @notice Initialize the 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_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n */\\n function _initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\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 _setComptroller(comptroller_);\\n\\n // Initialize slot(block or second) number and borrow index (slot(block or second) number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumberOrTimestamp();\\n borrowIndex = MANTISSA_ONE;\\n\\n // Set the interest rate model (depends on slot(block or second) number / borrow index)\\n _setInterestRateModelFresh(interestRateModel_);\\n\\n _setReserveFactorFresh(reserveFactorMantissa_);\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n _setShortfallContract(riskManagement.shortfall);\\n _setProtocolShareReserve(riskManagement.protocolShareReserve);\\n protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA;\\n\\n // Set underlying and sanity check it\\n underlying = underlying_;\\n IERC20Upgradeable(underlying).totalSupply();\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n _transferOwnership(admin_);\\n }\\n\\n function _setShortfallContract(address shortfall_) internal {\\n ensureNonzeroAddress(shortfall_);\\n address oldShortfall = shortfall;\\n shortfall = shortfall_;\\n emit NewShortfallContract(oldShortfall, shortfall_);\\n }\\n\\n function _setProtocolShareReserve(address payable protocolShareReserve_) internal {\\n ensureNonzeroAddress(protocolShareReserve_);\\n address oldProtocolShareReserve = address(protocolShareReserve);\\n protocolShareReserve = protocolShareReserve_;\\n emit NewProtocolShareReserve(oldProtocolShareReserve, address(protocolShareReserve_));\\n }\\n\\n function _ensureSenderIsDelegateOf(address user) internal view {\\n if (!ComptrollerViewInterface(address(comptroller)).approvedDelegates(user, msg.sender)) {\\n revert DelegateNotApproved();\\n }\\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 virtual returns (uint256) {\\n return IERC20Upgradeable(underlying).balanceOf(address(this));\\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 borrowBalance the calculated balance\\n */\\n function _borrowBalanceStored(address account) internal view returns (uint256) {\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot memory 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 0;\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;\\n\\n return principalTimesIndex / borrowSnapshot.interestIndex;\\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 exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function _exchangeRateStored() internal view virtual returns (uint256) {\\n uint256 _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return initialExchangeRateMantissa;\\n }\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply\\n */\\n uint256 totalCash = _getCashPrior();\\n uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;\\n uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply;\\n\\n return exchangeRate;\\n }\\n}\\n\",\"keccak256\":\"0xa220ca317fe69b920b86e43f054c43b5f891f12160fd312c9a21668f969ee056\",\"license\":\"BSD-3-Clause\"},\"contracts/VTokenInterfaces.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\\nimport { ComptrollerInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title VTokenStorage\\n * @author Venus\\n * @notice Storage layout used by the `VToken` contract\\n */\\n// solhint-disable-next-line max-states-count\\ncontract VTokenStorage {\\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 uint256 principal;\\n uint256 interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\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 Protocol share Reserve contract address\\n */\\n address payable public protocolShareReserve;\\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 InterestRateModel public interestRateModel;\\n\\n // Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n uint256 internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint256 public reserveFactorMantissa;\\n\\n /**\\n * @notice Slot(block or second) number that interest was last accrued at\\n */\\n uint256 public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint256 public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint256 public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint256 public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint256 public totalSupply;\\n\\n /**\\n * @notice Total bad debt of the market\\n */\\n uint256 public badDebt;\\n\\n // Official record of token balances for each account\\n mapping(address => uint256) internal accountTokens;\\n\\n // Approved token transfer amounts on behalf of others\\n mapping(address => mapping(address => uint256)) internal transferAllowances;\\n\\n // Mapping of account addresses to outstanding borrow balances\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint256 public protocolSeizeShareMantissa;\\n\\n /**\\n * @notice Storage of Shortfall contract address\\n */\\n address public shortfall;\\n\\n /**\\n * @notice delta slot (block or second) after which reserves will be reduced\\n */\\n uint256 public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last slot (block or second) number at which reserves were reduced\\n */\\n uint256 public reduceReservesBlockNumber;\\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\\n/**\\n * @title VTokenInterface\\n * @author Venus\\n * @notice Interface implemented by the `VToken` contract\\n */\\nabstract contract VTokenInterface is VTokenStorage {\\n struct RiskManagementInit {\\n address shortfall;\\n address payable protocolShareReserve;\\n }\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address indexed minter, uint256 mintAmount, uint256 mintTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address indexed borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(\\n address indexed payer,\\n address indexed borrower,\\n uint256 repayAmount,\\n uint256 accountBorrows,\\n uint256 totalBorrows\\n );\\n\\n /**\\n * @notice Event emitted when bad debt is accumulated on a market\\n * @param borrower borrower to \\\"forgive\\\"\\n * @param badDebtDelta amount of new bad debt recorded\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtIncreased(address indexed borrower, uint256 badDebtDelta, uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when bad debt is recovered via an auction\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtRecovered(uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address indexed liquidator,\\n address indexed borrower,\\n uint256 repayAmount,\\n address indexed vTokenCollateral,\\n uint256 seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface indexed oldComptroller, ComptrollerInterface indexed newComptroller);\\n\\n /**\\n * @notice Event emitted when shortfall contract address is changed\\n */\\n event NewShortfallContract(address indexed oldShortfall, address indexed newShortfall);\\n\\n /**\\n * @notice Event emitted when protocol share reserve contract address is changed\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModel indexed oldInterestRateModel,\\n InterestRateModel indexed newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when protocol seize share is changed\\n */\\n event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address indexed benefactor, uint256 addAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the spread reserves are reduced\\n */\\n event SpreadReservesReduced(address indexed protocolShareReserve, uint256 reduceAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /**\\n * @notice Event emitted when healing the borrow\\n */\\n event HealBorrow(address indexed payer, address indexed borrower, uint256 repayAmount);\\n\\n /**\\n * @notice Event emitted when tokens are swept\\n */\\n event SweepToken(address indexed token);\\n\\n /**\\n * @notice Event emitted when reduce reserves slot (block or second) delta is changed\\n */\\n event NewReduceReservesBlockDelta(\\n uint256 oldReduceReservesBlockOrTimestampDelta,\\n uint256 newReduceReservesBlockOrTimestampDelta\\n );\\n\\n /**\\n * @notice Event emitted when liquidation reserves are reduced\\n */\\n event ProtocolSeize(address indexed from, address indexed to, uint256 amount);\\n\\n /*** User Interface ***/\\n\\n function mint(uint256 mintAmount) external virtual returns (uint256);\\n\\n function mintBehalf(address minter, uint256 mintAllowed) external virtual returns (uint256);\\n\\n function redeem(uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemBehalf(address redeemer, uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);\\n\\n function redeemUnderlyingBehalf(address redeemer, uint256 redeemAmount) external virtual returns (uint256);\\n\\n function borrow(uint256 borrowAmount) external virtual returns (uint256);\\n\\n function borrowBehalf(address borrwwer, uint256 borrowAmount) external virtual returns (uint256);\\n\\n function repayBorrow(uint256 repayAmount) external virtual returns (uint256);\\n\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external virtual returns (uint256);\\n\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external virtual;\\n\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipCloseFactorCheck\\n ) external virtual;\\n\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external virtual;\\n\\n function transfer(address dst, uint256 amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint256 amount) external virtual returns (bool);\\n\\n function accrueInterest() external virtual returns (uint256);\\n\\n function sweepToken(IERC20Upgradeable token) external virtual;\\n\\n /*** Admin Functions ***/\\n\\n function setReserveFactor(uint256 newReserveFactorMantissa) external virtual;\\n\\n function reduceReserves(uint256 reduceAmount) external virtual;\\n\\n function exchangeRateCurrent() external virtual returns (uint256);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint256);\\n\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external virtual;\\n\\n function addReserves(uint256 addAmount) external virtual;\\n\\n function totalBorrowsCurrent() external virtual returns (uint256);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint256);\\n\\n function approve(address spender, uint256 amount) external virtual returns (bool);\\n\\n function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool);\\n\\n function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint256);\\n\\n function balanceOf(address owner) external view virtual returns (uint256);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint256, uint256, uint256, uint256);\\n\\n function borrowRatePerBlock() external view virtual returns (uint256);\\n\\n function supplyRatePerBlock() external view virtual returns (uint256);\\n\\n function borrowBalanceStored(address account) external view virtual returns (uint256);\\n\\n function exchangeRateStored() external view virtual returns (uint256);\\n\\n function getCash() external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is a VToken contract (for inspection)\\n * @return Always true\\n */\\n function isVToken() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x7c4cbb879e3a931cfee4fa7a9eb1978eddff18087a1c4f56decedb84c2479f1e\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\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\",\"keccak256\":\"0x54ab3a6f3bc87569ed12370f3470a1ec84cea9796d4d0ccf3d07dd4280c044aa\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/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 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\",\"keccak256\":\"0x93bdd5cfb100f0f9a1d446857e23c3633df6ab12c266333c978428edd96b1367\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x60e060405234801561001057600080fd5b5060405161406e38038061406e83398101604081905261002f916100dc565b81818115801561003d575080155b1561005b576040516302723dfb60e21b815260040160405180910390fd5b81801561006757508015155b156100855760405163ae0fcab360e01b815260040160405180910390fd5b81151560a05281610096578061009c565b6301e133805b608052816100b3576100d460201b611dfb176100be565b6100d860201b611dff175b6001600160401b031660c0525061010f92505050565b4390565b4290565b600080604083850312156100ef57600080fd5b825180151581146100ff57600080fd5b6020939093015192949293505050565b60805160a05160c051613f296101456000396000611dcf0152600081816102a60152611ed0015260006101d10152613f296000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c80637c51b64211610097578063c7ad089511610066578063c7ad0895146102a1578063d77ebf96146102d8578063e0a67f11146102f8578063e1d146fb1461031857600080fd5b80637c51b642146102215780637c84e3b314610241578063aa5dbd2314610261578063b31242391461028157600080fd5b806347d86a81116100d357806347d86a811461018e57806355dd9515146101a15780636857249c146101cc5780637a27db571461020157600080fd5b80630d3ae318146101055780631f884fdf1461012e578063345954dc1461014e5780633e3e399c1461016e575b600080fd5b610118610113366004612f40565b610320565b60405161012591906132ad565b60405180910390f35b61014161013c36600461330b565b610655565b604051610125919061334c565b61016161015c3660046133ac565b61071d565b60405161012591906133c9565b61018161017c3660046133ac565b610850565b604051610125919061342d565b61011861019c3660046134b7565b610bc2565b6101b46101af3660046134f0565b610c49565b6040516001600160a01b039091168152602001610125565b6101f37f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610125565b61021461020f3660046134b7565b610cc9565b604051610125919061353b565b61023461022f366004613617565b610fd6565b60405161012591906136a2565b61025461024f3660046133ac565b61108f565b60405161012591906136f0565b61027461026f3660046133ac565b6111f9565b6040516101259190613710565b61029461028f3660046134b7565b6119b9565b604051610125919061371f565b6102c87f000000000000000000000000000000000000000000000000000000000000000081565b6040519015158152602001610125565b6102eb6102e63660046134b7565b611ca0565b604051610125919061372d565b61030b610306366004613791565b611d13565b604051610125919061382a565b6101f3611dc8565b610328612d07565b6000826040015190506000816001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610371573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610399919081019061386d565b905060006103a682611d13565b60408681015190516328ebbe8b60e21b81526001600160a01b039182166004820152919250879160009183169063a3aefa2c90602401600060405180830381865afa1580156103f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526104219190810190613940565b90506000876040015190506000604051806101a001604052808a6000015181526020018a602001516001600160a01b031681526020018a604001516001600160a01b031681526020018a6060015181526020018a608001518152602001846000015181526020018460200151815260200184604001518152602001836001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104fe91906139f4565b6001600160a01b03168152602001836001600160a01b031663e87554466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561054a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061056e9190613a11565b8152602001836001600160a01b0316634ada90af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d59190613a11565b8152602001836001600160a01b031663db5c65de6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610618573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063c9190613a11565b8152602001959095525092955050505050505b92915050565b6060816000816001600160401b0381111561067257610672612e89565b6040519080825280602002602001820160405280156106b757816020015b60408051808201909152600080825260208201528152602001906001900390816106905790505b50905060005b82811015610714576106ef8686838181106106da576106da613a2a565b905060200201602081019061024f91906133ac565b82828151811061070157610701613a2a565b60209081029190910101526001016106bd565b50949350505050565b606060008290506000816001600160a01b031663d88ff1f46040518163ffffffff1660e01b8152600401600060405180830381865afa158015610764573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261078c9190810190613ac3565b80519091506000816001600160401b038111156107ab576107ab612e89565b6040519080825280602002602001820160405280156107e457816020015b6107d1612d07565b8152602001906001900390816107c95790505b50905060005b8281101561084657600084828151811061080657610806613a2a565b60200260200101519050600061081c8983610320565b90508084848151811061083157610831613a2a565b602090810291909101015250506001016107ea565b5095945050505050565b604080516060808201835260008083526020830152918101919091526000808390506000816001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156108b2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108da919081019061386d565b90506000826001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561091c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094091906139f4565b9050600082516001600160401b0381111561095d5761095d612e89565b6040519080825280602002602001820160405280156109a257816020015b604080518082019091526000808252602082015281526020019060019003908161097b5790505b5090506109d2604051806060016040528060006001600160a01b0316815260200160008152602001606081525090565b6001600160a01b03881681526040810182905260005b8451811015610bae576040805180820190915260008082526020820152858281518110610a1757610a17613a2a565b602002602001015181600001906001600160a01b031690816001600160a01b031681525050670de0b6b3a7640000856001600160a01b031663fc57d4df888581518110610a6657610a66613a2a565b60200260200101516040518263ffffffff1660e01b8152600401610a9991906001600160a01b0391909116815260200190565b602060405180830381865afa158015610ab6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ada9190613a11565b878481518110610aec57610aec613a2a565b60200260200101516001600160a01b031663bbcac5576040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b559190613a11565b610b5f9190613b89565b610b699190613ba0565b60208201526040830151805182919084908110610b8857610b88613a2a565b6020026020010181905250806020015188610ba39190613bc2565b9750506001016109e8565b506020810195909552509295945050505050565b610bca612d07565b604051637aee632d60e01b81526001600160a01b0383811660048301528491610c4191839190821690637aee632d90602401600060405180830381865afa158015610c19573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526101139190810190613bd5565b949350505050565b60405163266e0a7f60e01b81526001600160a01b0383811660048301528281166024830152600091859182169063266e0a7f90604401602060405180830381865afa158015610c9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc091906139f4565b95945050505050565b60606000826001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610d0b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d33919081019061386d565b90506000836001600160a01b03166361252fd16040518163ffffffff1660e01b8152600401600060405180830381865afa158015610d75573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d9d9190810190613c09565b9050600081516001600160401b03811115610dba57610dba612e89565b604051908082528060200260200182016040528015610e0b57816020015b6040805160808101825260008082526020808301829052928201526060808201528252600019909201910181610dd85790505b50905060005b8251811015610846576040805160808101825260008082526020820181905291810191909152606080820152838281518110610e4f57610e4f613a2a565b60209081029190910101516001600160a01b031681528351849083908110610e7957610e79613a2a565b60200260200101516001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ebe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee291906139f4565b6001600160a01b031660208201528351849083908110610f0457610f04613a2a565b6020908102919091010151604051631627ee8960e01b81526001600160a01b038a8116600483015290911690631627ee8990602401602060405180830381865afa158015610f56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7a9190613a11565b816040018181525050610fa78886868581518110610f9a57610f9a613a2a565b6020026020010151611e03565b816060018190525080838381518110610fc257610fc2613a2a565b602090810291909101015250600101610e11565b6060826000816001600160401b03811115610ff357610ff3612e89565b60405190808252806020026020018201604052801561102c57816020015b611019612d8a565b8152602001906001900390816110115790505b50905060005b828110156108465761106a87878381811061104f5761104f613a2a565b905060200201602081019061106491906133ac565b866119b9565b82828151811061107c5761107c613a2a565b6020908102919091010152600101611032565b60408051808201909152600080825260208201526000826001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110e3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110791906139f4565b90506000816001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611149573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116d91906139f4565b6040805180820182526001600160a01b03808816808352925163fc57d4df60e01b815260048101939093529293509160208301919084169063fc57d4df90602401602060405180830381865afa1580156111cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ef9190613a11565b9052949350505050565b611201612dc9565b6000826001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611241573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112659190613a11565b90506000836001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cb91906139f4565b604051638e8f294b60e01b81526001600160a01b03868116600483015291925082916000918291841690638e8f294b906024016040805180830381865afa15801561131a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133e9190613ca7565b915091506000876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a691906139f4565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061140c9190613cd3565b60ff1690506000805b600860ff8216116114d2576000886001600160a01b031663e85a29608d8460ff16600881111561144757611447613cf6565b6040518363ffffffff1660e01b8152600401611464929190613d0c565b602060405180830381865afa158015611481573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a59190613d47565b6114b05760006114b3565b60015b60ff9081169083161b9290921791506114cb81613d62565b9050611415565b506000808b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611514573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115389190613a11565b11156115a3578a6001600160a01b031663ae9d70b06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561157c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a09190613a11565b90505b6040518061022001604052808c6001600160a01b031681526020018a81526020018281526020018c6001600160a01b031663f8f9da286040518163ffffffff1660e01b8152600401602060405180830381865afa158015611608573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061162c9190613a11565b81526020018c6001600160a01b031663173b99046040518163ffffffff1660e01b8152600401602060405180830381865afa15801561166f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116939190613a11565b81526040516302c3bcbb60e01b81526001600160a01b038e811660048301526020909201918a16906302c3bcbb90602401602060405180830381865afa1580156116e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117059190613a11565b815260405163252c221960e11b81526001600160a01b038e811660048301526020909201918a1690634a58443290602401602060405180830381865afa158015611753573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117779190613a11565b81526020018c6001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117de9190613a11565b81526020018c6001600160a01b0316638f840ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611821573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118459190613a11565b81526020018c6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611888573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ac9190613a11565b81526020018c6001600160a01b0316633b1d21a26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119139190613a11565b81526020018715158152602001868152602001856001600160a01b031681526020018c6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611973573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119979190613cd3565b60ff168152602001848152602001838152509950505050505050505050919050565b6119c1612d8a565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908516906370a0823190602401602060405180830381865afa158015611a0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a2f9190613a11565b6040516305eff7ef60e21b81526001600160a01b0385811660048301529192506000918616906317bfdfbc906024016020604051808303816000875af1158015611a7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa19190613a11565b604051633af9e66960e01b81526001600160a01b038681166004830152919250600091871690633af9e669906024016020604051808303816000875af1158015611aef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b139190613a11565b90506000806000886001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b7c91906139f4565b6040516370a0823160e01b81526001600160a01b038a81166004830152919250908216906370a0823190602401602060405180830381865afa158015611bc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bea9190613a11565b604051636eb1769f60e11b81526001600160a01b038a811660048301528b811660248301529194509082169063dd62ed3e90604401602060405180830381865afa158015611c3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c609190613a11565b6040805160c0810182526001600160a01b038c168152602081019890985287019590955250506060840191909152608083015260a0820152905092915050565b604051631e6db74760e31b81526001600160a01b038281166004830152606091849182169063f36dba3890602401600060405180830381865afa158015611ceb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c419190810190613d81565b80516060906000816001600160401b03811115611d3257611d32612e89565b604051908082528060200260200182016040528015611d6b57816020015b611d58612dc9565b815260200190600190039081611d505790505b50905060005b82811015611dc057611d9b858281518110611d8e57611d8e613a2a565b60200260200101516111f9565b828281518110611dad57611dad613a2a565b6020908102919091010152600101611d71565b509392505050565b6000611df67f000000000000000000000000000000000000000000000000000000000000000063ffffffff16565b905090565b4390565b4290565b6060600083516001600160401b03811115611e2057611e20612e89565b604051908082528060200260200182016040528015611e6557816020015b6040805180820190915260008082526020820152815260200190600190039081611e3e5790505b50905060005b845181101561071457611ea1604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b611ece604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b7f00000000000000000000000000000000000000000000000000000000000000001561205157856001600160a01b0316638f693ec7888581518110611f1557611f15613a2a565b60200260200101516040518263ffffffff1660e01b8152600401611f4891906001600160a01b0391909116815260200190565b606060405180830381865afa158015611f65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f899190613e26565b604085015260208401526001600160e01b0316825286516001600160a01b03871690638181494590899086908110611fc357611fc3613a2a565b60200260200101516040518263ffffffff1660e01b8152600401611ff691906001600160a01b0391909116815260200190565b606060405180830381865afa158015612013573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120379190613e26565b604084015260208301526001600160e01b031681526121bc565b856001600160a01b0316632c427b5788858151811061207257612072613a2a565b60200260200101516040518263ffffffff1660e01b81526004016120a591906001600160a01b0391909116815260200190565b606060405180830381865afa1580156120c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e69190613e6f565b63ffffffff90811660408601521660208401526001600160e01b0316825286516001600160a01b038716906392a182359089908690811061212957612129613a2a565b60200260200101516040518263ffffffff1660e01b815260040161215c91906001600160a01b0391909116815260200190565b606060405180830381865afa158015612179573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061219d9190613e6f565b63ffffffff90811660408501521660208301526001600160e01b031681525b600060405180602001604052808986815181106121db576121db613a2a565b60200260200101516001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612220573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122449190613a11565b815250905061226e88858151811061225e5761225e613a2a565b6020026020010151888584612363565b61229288858151811061228357612283613a2a565b60200260200101518884612564565b60006122ba8986815181106122a9576122a9613a2a565b6020026020010151898c878661275b565b905060006122e38a87815181106122d3576122d3613a2a565b60200260200101518a8d8761298b565b60408051808201909152600080825260208201529091508a878151811061230c5761230c613a2a565b60209081029190910101516001600160a01b0316815261232c8284613bc2565b60208201528751819089908990811061234757612347613a2a565b6020026020010181905250505050505050806001019050611e6b565b604051637c05a7c560e01b81526001600160a01b03858116600483015260009190851690637c05a7c590602401602060405180830381865afa1580156123ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123d19190613a11565b905060006123dd611dc8565b9050600084604001511180156123f65750836040015181115b15612402575060408301515b6000612412828660200151612baf565b90506000811180156124245750600083115b1561254d576000612496886001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561246c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124909190613a11565b86612bc2565b905060006124a48386612be0565b905060008083116124c457604051806020016040528060008152506124ce565b6124ce8284612bec565b905060006124f760405180602001604052808b600001516001600160e01b031681525083612c31565b90506125328160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612c5d565b6001600160e01b03168952505050506020850182905261255b565b801561255b57602085018290525b50505050505050565b604051631d31307360e21b81526001600160a01b038481166004830152600091908416906374c4c1cc90602401602060405180830381865afa1580156125ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125d29190613a11565b905060006125de611dc8565b9050600083604001511180156125f75750826040015181115b15612603575060408201515b6000612613828560200151612baf565b90506000811180156126255750600083115b15612745576000866001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561266a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061268e9190613a11565b9050600061269c8386612be0565b905060008083116126bc57604051806020016040528060008152506126c6565b6126c68284612bec565b905060006126ef60405180602001604052808a600001516001600160e01b031681525083612c31565b905061272a8160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612c5d565b6001600160e01b031688525050505060208401829052612753565b801561275357602084018290525b505050505050565b604080516020808201835284516001600160e01b031682528251908101928390526336fe846560e11b9092526001600160a01b0387811660248401528581166044840152600092839181908916636dfd08ca60648301602060405180830381865afa1580156127ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f29190613a11565b905280519091501580156128745750866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa15801561283f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128639190613eb2565b6001600160e01b0316826000015110155b156128e757866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128db9190613eb2565b6001600160e01b031681525b60006128f38383612c99565b6040516395dd919360e01b81526001600160a01b03898116600483015291925060009161296e91908c16906395dd919390602401602060405180830381865afa158015612944573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129689190613a11565b87612bc2565b9050600061297c8284612cc5565b9b9a5050505050505050505050565b604080516020808201835283516001600160e01b0316825282519081019283905263552c097160e01b9092526001600160a01b038681166024840152848116604484015260009283918190881663552c097160648301602060405180830381865afa1580156129fe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a229190613a11565b90528051909150158015612aa45750856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a939190613eb2565b6001600160e01b0316826000015110155b15612b1757856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ae7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b0b9190613eb2565b6001600160e01b031681525b6000612b238383612c99565b6040516370a0823160e01b81526001600160a01b0388811660048301529192506000918a16906370a0823190602401602060405180830381865afa158015612b6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b939190613a11565b90506000612ba18284612cc5565b9a9950505050505050505050565b6000612bbb8284613ecd565b9392505050565b6000612bbb612bd984670de0b6b3a7640000612be0565b8351612cef565b6000612bbb8284613b89565b6040805160208101909152600081526040518060200160405280612c28612c22866ec097ce7bc90715b34b9f1000000000612be0565b85612cef565b90529392505050565b6040805160208101909152600081526040518060200160405280612c2885600001518560000151612cfb565b6000816001600160e01b03841115612c915760405162461bcd60e51b8152600401612c889190613ee0565b60405180910390fd5b509192915050565b6040805160208101909152600081526040518060200160405280612c2885600001518560000151612baf565b60006ec097ce7bc90715b34b9f1000000000612ce5848460000151612be0565b612bbb9190613ba0565b6000612bbb8284613ba0565b6000612bbb8284613bc2565b604051806101a001604052806060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160608152602001606081526020016060815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001606081525090565b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180610220016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b6001600160a01b0381168114612e7657600080fd5b50565b8035612e8481612e61565b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715612ec157612ec1612e89565b60405290565b604051606081016001600160401b0381118282101715612ec157612ec1612e89565b604051601f8201601f191681016001600160401b0381118282101715612f1157612f11612e89565b604052919050565b60006001600160401b03821115612f3257612f32612e89565b50601f01601f191660200190565b60008060408385031215612f5357600080fd5b8235612f5e81612e61565b91506020838101356001600160401b0380821115612f7b57600080fd5b9085019060a08288031215612f8f57600080fd5b612f97612e9f565b823582811115612fa657600080fd5b83019150601f82018813612fb957600080fd5b8135612fcc612fc782612f19565b612ee9565b8181528986838601011115612fe057600080fd5b818685018783013760008683830101528083525050613000848401612e79565b8482015261301060408401612e79565b60408201526060830135606082015260808301356080820152809450505050509250929050565b60005b8381101561305257818101518382015260200161303a565b50506000910152565b60008151808452613073816020860160208601613037565b601f01601f19169290920160200192915050565b80516001600160a01b031682526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e0830152610100808201518184015250610120808201518184015250610140808201518184015250610160808201516131128285018215159052565b505061018081810151908301526101a0808201516001600160a01b0316908301526101c080820151908301526101e0808201519083015261020090810151910152565b60008151808452602080850194506020840160005b838110156131915761317d878351613087565b61022096909601959082019060010161316a565b509495945050505050565b60006101a082518185526131b28286018261305b565b91505060208301516131cf60208601826001600160a01b03169052565b5060408301516131ea60408601826001600160a01b03169052565b50606083015160608501526080830151608085015260a083015184820360a0860152613216828261305b565b91505060c083015184820360c0860152613230828261305b565b91505060e083015184820360e086015261324a828261305b565b91505061010080840151613268828701826001600160a01b03169052565b505061012083810151908501526101408084015190850152610160808401519085015261018080840151858303828701526132a38382613155565b9695505050505050565b602081526000612bbb602083018461319c565b60008083601f8401126132d257600080fd5b5081356001600160401b038111156132e957600080fd5b6020830191508360208260051b850101111561330457600080fd5b9250929050565b6000806020838503121561331e57600080fd5b82356001600160401b0381111561333457600080fd5b613340858286016132c0565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b8281101561339f5761338f84835180516001600160a01b03168252602090810151910152565b9284019290850190600101613369565b5091979650505050505050565b6000602082840312156133be57600080fd5b8135612bbb81612e61565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561342057603f1988860301845261340e85835161319c565b945092850192908501906001016133f2565b5092979650505050505050565b602080825282516001600160a01b03168282015282810151604080840191909152808401516060808501528051608085018190526000939291830191849160a08701905b808410156134ab5761349782865180516001600160a01b03168252602090810151910152565b938501936001939093019290820190613471565b50979650505050505050565b600080604083850312156134ca57600080fd5b82356134d581612e61565b915060208301356134e581612e61565b809150509250929050565b60008060006060848603121561350557600080fd5b833561351081612e61565b9250602084013561352081612e61565b9150604084013561353081612e61565b809150509250925092565b600060208083018184528085518083526040925060408601915060408160051b8701018488016000805b8481101561360857898403603f19018652825180516001600160a01b03908116865289820151168986015287810151888601526060908101516080918601829052805191860182905289019060a086019084905b808210156135f3576135df83855180516001600160a01b03168252602090810151910152565b928b0192918a0191600191909101906135b9565b50509689019694505091870191600101613565565b50919998505050505050505050565b60008060006040848603121561362c57600080fd5b83356001600160401b0381111561364257600080fd5b61364e868287016132c0565b909450925050602084013561353081612e61565b80516001600160a01b031682526020808201519083015260408082015190830152606080820151908301526080808201519083015260a090810151910152565b6020808252825182820181905260009190848201906040850190845b818110156136e4576136d1838551613662565b9284019260c092909201916001016136be565b50909695505050505050565b81516001600160a01b03168152602080830151908201526040810161064f565b610220810161064f8284613087565b60c0810161064f8284613662565b6020808252825182820181905260009190848201906040850190845b818110156136e45783516001600160a01b031683529284019291840191600101613749565b60006001600160401b0382111561378757613787612e89565b5060051b60200190565b600060208083850312156137a457600080fd5b82356001600160401b038111156137ba57600080fd5b8301601f810185136137cb57600080fd5b80356137d9612fc78261376e565b81815260059190911b820183019083810190878311156137f857600080fd5b928401925b8284101561381f57833561381081612e61565b825292840192908401906137fd565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156136e457613859838551613087565b928401926102209290920191600101613846565b6000602080838503121561388057600080fd5b82516001600160401b0381111561389657600080fd5b8301601f810185136138a757600080fd5b80516138b5612fc78261376e565b81815260059190911b820183019083810190878311156138d457600080fd5b928401925b8284101561381f5783516138ec81612e61565b825292840192908401906138d9565b600082601f83011261390c57600080fd5b815161391a612fc782612f19565b81815284602083860101111561392f57600080fd5b610c41826020830160208701613037565b60006020828403121561395257600080fd5b81516001600160401b038082111561396957600080fd5b908301906060828603121561397d57600080fd5b613985612ec7565b82518281111561399457600080fd5b6139a0878286016138fb565b8252506020830151828111156139b557600080fd5b6139c1878286016138fb565b6020830152506040830151828111156139d957600080fd5b6139e5878286016138fb565b60408301525095945050505050565b600060208284031215613a0657600080fd5b8151612bbb81612e61565b600060208284031215613a2357600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600060a08284031215613a5257600080fd5b613a5a612e9f565b905081516001600160401b03811115613a7257600080fd5b613a7e848285016138fb565b8252506020820151613a8f81612e61565b60208201526040820151613aa281612e61565b80604083015250606082015160608201526080820151608082015292915050565b60006020808385031215613ad657600080fd5b82516001600160401b0380821115613aed57600080fd5b818501915085601f830112613b0157600080fd5b8151613b0f612fc78261376e565b81815260059190911b83018401908481019088831115613b2e57600080fd5b8585015b83811015613b6657805185811115613b4a5760008081fd5b613b588b89838a0101613a40565b845250918601918601613b32565b5098975050505050505050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761064f5761064f613b73565b600082613bbd57634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561064f5761064f613b73565b600060208284031215613be757600080fd5b81516001600160401b03811115613bfd57600080fd5b610c4184828501613a40565b60006020808385031215613c1c57600080fd5b82516001600160401b03811115613c3257600080fd5b8301601f81018513613c4357600080fd5b8051613c51612fc78261376e565b81815260059190911b82018301908381019087831115613c7057600080fd5b928401925b8284101561381f578351613c8881612e61565b82529284019290840190613c75565b80518015158114612e8457600080fd5b60008060408385031215613cba57600080fd5b613cc383613c97565b9150602083015190509250929050565b600060208284031215613ce557600080fd5b815160ff81168114612bbb57600080fd5b634e487b7160e01b600052602160045260246000fd5b6001600160a01b03831681526040810160098310613d3a57634e487b7160e01b600052602160045260246000fd5b8260208301529392505050565b600060208284031215613d5957600080fd5b612bbb82613c97565b600060ff821660ff8103613d7857613d78613b73565b60010192915050565b60006020808385031215613d9457600080fd5b82516001600160401b03811115613daa57600080fd5b8301601f81018513613dbb57600080fd5b8051613dc9612fc78261376e565b81815260059190911b82018301908381019087831115613de857600080fd5b928401925b8284101561381f578351613e0081612e61565b82529284019290840190613ded565b80516001600160e01b0381168114612e8457600080fd5b600080600060608486031215613e3b57600080fd5b613e4484613e0f565b925060208401519150604084015190509250925092565b805163ffffffff81168114612e8457600080fd5b600080600060608486031215613e8457600080fd5b613e8d84613e0f565b9250613e9b60208501613e5b565b9150613ea960408501613e5b565b90509250925092565b600060208284031215613ec457600080fd5b612bbb82613e0f565b8181038181111561064f5761064f613b73565b602081526000612bbb602083018461305b56fea26469706673582212200676c45ecb3b8ffe0af9232b12bc003136dfae8bdb9833c728b4a7246afcb3d664736f6c63430008190033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101005760003560e01c80637c51b64211610097578063c7ad089511610066578063c7ad0895146102a1578063d77ebf96146102d8578063e0a67f11146102f8578063e1d146fb1461031857600080fd5b80637c51b642146102215780637c84e3b314610241578063aa5dbd2314610261578063b31242391461028157600080fd5b806347d86a81116100d357806347d86a811461018e57806355dd9515146101a15780636857249c146101cc5780637a27db571461020157600080fd5b80630d3ae318146101055780631f884fdf1461012e578063345954dc1461014e5780633e3e399c1461016e575b600080fd5b610118610113366004612f40565b610320565b60405161012591906132ad565b60405180910390f35b61014161013c36600461330b565b610655565b604051610125919061334c565b61016161015c3660046133ac565b61071d565b60405161012591906133c9565b61018161017c3660046133ac565b610850565b604051610125919061342d565b61011861019c3660046134b7565b610bc2565b6101b46101af3660046134f0565b610c49565b6040516001600160a01b039091168152602001610125565b6101f37f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610125565b61021461020f3660046134b7565b610cc9565b604051610125919061353b565b61023461022f366004613617565b610fd6565b60405161012591906136a2565b61025461024f3660046133ac565b61108f565b60405161012591906136f0565b61027461026f3660046133ac565b6111f9565b6040516101259190613710565b61029461028f3660046134b7565b6119b9565b604051610125919061371f565b6102c87f000000000000000000000000000000000000000000000000000000000000000081565b6040519015158152602001610125565b6102eb6102e63660046134b7565b611ca0565b604051610125919061372d565b61030b610306366004613791565b611d13565b604051610125919061382a565b6101f3611dc8565b610328612d07565b6000826040015190506000816001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610371573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610399919081019061386d565b905060006103a682611d13565b60408681015190516328ebbe8b60e21b81526001600160a01b039182166004820152919250879160009183169063a3aefa2c90602401600060405180830381865afa1580156103f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526104219190810190613940565b90506000876040015190506000604051806101a001604052808a6000015181526020018a602001516001600160a01b031681526020018a604001516001600160a01b031681526020018a6060015181526020018a608001518152602001846000015181526020018460200151815260200184604001518152602001836001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104fe91906139f4565b6001600160a01b03168152602001836001600160a01b031663e87554466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561054a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061056e9190613a11565b8152602001836001600160a01b0316634ada90af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d59190613a11565b8152602001836001600160a01b031663db5c65de6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610618573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063c9190613a11565b8152602001959095525092955050505050505b92915050565b6060816000816001600160401b0381111561067257610672612e89565b6040519080825280602002602001820160405280156106b757816020015b60408051808201909152600080825260208201528152602001906001900390816106905790505b50905060005b82811015610714576106ef8686838181106106da576106da613a2a565b905060200201602081019061024f91906133ac565b82828151811061070157610701613a2a565b60209081029190910101526001016106bd565b50949350505050565b606060008290506000816001600160a01b031663d88ff1f46040518163ffffffff1660e01b8152600401600060405180830381865afa158015610764573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261078c9190810190613ac3565b80519091506000816001600160401b038111156107ab576107ab612e89565b6040519080825280602002602001820160405280156107e457816020015b6107d1612d07565b8152602001906001900390816107c95790505b50905060005b8281101561084657600084828151811061080657610806613a2a565b60200260200101519050600061081c8983610320565b90508084848151811061083157610831613a2a565b602090810291909101015250506001016107ea565b5095945050505050565b604080516060808201835260008083526020830152918101919091526000808390506000816001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156108b2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108da919081019061386d565b90506000826001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561091c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094091906139f4565b9050600082516001600160401b0381111561095d5761095d612e89565b6040519080825280602002602001820160405280156109a257816020015b604080518082019091526000808252602082015281526020019060019003908161097b5790505b5090506109d2604051806060016040528060006001600160a01b0316815260200160008152602001606081525090565b6001600160a01b03881681526040810182905260005b8451811015610bae576040805180820190915260008082526020820152858281518110610a1757610a17613a2a565b602002602001015181600001906001600160a01b031690816001600160a01b031681525050670de0b6b3a7640000856001600160a01b031663fc57d4df888581518110610a6657610a66613a2a565b60200260200101516040518263ffffffff1660e01b8152600401610a9991906001600160a01b0391909116815260200190565b602060405180830381865afa158015610ab6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ada9190613a11565b878481518110610aec57610aec613a2a565b60200260200101516001600160a01b031663bbcac5576040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b559190613a11565b610b5f9190613b89565b610b699190613ba0565b60208201526040830151805182919084908110610b8857610b88613a2a565b6020026020010181905250806020015188610ba39190613bc2565b9750506001016109e8565b506020810195909552509295945050505050565b610bca612d07565b604051637aee632d60e01b81526001600160a01b0383811660048301528491610c4191839190821690637aee632d90602401600060405180830381865afa158015610c19573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526101139190810190613bd5565b949350505050565b60405163266e0a7f60e01b81526001600160a01b0383811660048301528281166024830152600091859182169063266e0a7f90604401602060405180830381865afa158015610c9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc091906139f4565b95945050505050565b60606000826001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610d0b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d33919081019061386d565b90506000836001600160a01b03166361252fd16040518163ffffffff1660e01b8152600401600060405180830381865afa158015610d75573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d9d9190810190613c09565b9050600081516001600160401b03811115610dba57610dba612e89565b604051908082528060200260200182016040528015610e0b57816020015b6040805160808101825260008082526020808301829052928201526060808201528252600019909201910181610dd85790505b50905060005b8251811015610846576040805160808101825260008082526020820181905291810191909152606080820152838281518110610e4f57610e4f613a2a565b60209081029190910101516001600160a01b031681528351849083908110610e7957610e79613a2a565b60200260200101516001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ebe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee291906139f4565b6001600160a01b031660208201528351849083908110610f0457610f04613a2a565b6020908102919091010151604051631627ee8960e01b81526001600160a01b038a8116600483015290911690631627ee8990602401602060405180830381865afa158015610f56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7a9190613a11565b816040018181525050610fa78886868581518110610f9a57610f9a613a2a565b6020026020010151611e03565b816060018190525080838381518110610fc257610fc2613a2a565b602090810291909101015250600101610e11565b6060826000816001600160401b03811115610ff357610ff3612e89565b60405190808252806020026020018201604052801561102c57816020015b611019612d8a565b8152602001906001900390816110115790505b50905060005b828110156108465761106a87878381811061104f5761104f613a2a565b905060200201602081019061106491906133ac565b866119b9565b82828151811061107c5761107c613a2a565b6020908102919091010152600101611032565b60408051808201909152600080825260208201526000826001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110e3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110791906139f4565b90506000816001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611149573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116d91906139f4565b6040805180820182526001600160a01b03808816808352925163fc57d4df60e01b815260048101939093529293509160208301919084169063fc57d4df90602401602060405180830381865afa1580156111cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ef9190613a11565b9052949350505050565b611201612dc9565b6000826001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611241573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112659190613a11565b90506000836001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cb91906139f4565b604051638e8f294b60e01b81526001600160a01b03868116600483015291925082916000918291841690638e8f294b906024016040805180830381865afa15801561131a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133e9190613ca7565b915091506000876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a691906139f4565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061140c9190613cd3565b60ff1690506000805b600860ff8216116114d2576000886001600160a01b031663e85a29608d8460ff16600881111561144757611447613cf6565b6040518363ffffffff1660e01b8152600401611464929190613d0c565b602060405180830381865afa158015611481573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a59190613d47565b6114b05760006114b3565b60015b60ff9081169083161b9290921791506114cb81613d62565b9050611415565b506000808b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611514573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115389190613a11565b11156115a3578a6001600160a01b031663ae9d70b06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561157c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a09190613a11565b90505b6040518061022001604052808c6001600160a01b031681526020018a81526020018281526020018c6001600160a01b031663f8f9da286040518163ffffffff1660e01b8152600401602060405180830381865afa158015611608573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061162c9190613a11565b81526020018c6001600160a01b031663173b99046040518163ffffffff1660e01b8152600401602060405180830381865afa15801561166f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116939190613a11565b81526040516302c3bcbb60e01b81526001600160a01b038e811660048301526020909201918a16906302c3bcbb90602401602060405180830381865afa1580156116e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117059190613a11565b815260405163252c221960e11b81526001600160a01b038e811660048301526020909201918a1690634a58443290602401602060405180830381865afa158015611753573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117779190613a11565b81526020018c6001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117de9190613a11565b81526020018c6001600160a01b0316638f840ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611821573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118459190613a11565b81526020018c6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611888573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ac9190613a11565b81526020018c6001600160a01b0316633b1d21a26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119139190613a11565b81526020018715158152602001868152602001856001600160a01b031681526020018c6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611973573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119979190613cd3565b60ff168152602001848152602001838152509950505050505050505050919050565b6119c1612d8a565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908516906370a0823190602401602060405180830381865afa158015611a0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a2f9190613a11565b6040516305eff7ef60e21b81526001600160a01b0385811660048301529192506000918616906317bfdfbc906024016020604051808303816000875af1158015611a7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa19190613a11565b604051633af9e66960e01b81526001600160a01b038681166004830152919250600091871690633af9e669906024016020604051808303816000875af1158015611aef573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b139190613a11565b90506000806000886001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b58573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b7c91906139f4565b6040516370a0823160e01b81526001600160a01b038a81166004830152919250908216906370a0823190602401602060405180830381865afa158015611bc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bea9190613a11565b604051636eb1769f60e11b81526001600160a01b038a811660048301528b811660248301529194509082169063dd62ed3e90604401602060405180830381865afa158015611c3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c609190613a11565b6040805160c0810182526001600160a01b038c168152602081019890985287019590955250506060840191909152608083015260a0820152905092915050565b604051631e6db74760e31b81526001600160a01b038281166004830152606091849182169063f36dba3890602401600060405180830381865afa158015611ceb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c419190810190613d81565b80516060906000816001600160401b03811115611d3257611d32612e89565b604051908082528060200260200182016040528015611d6b57816020015b611d58612dc9565b815260200190600190039081611d505790505b50905060005b82811015611dc057611d9b858281518110611d8e57611d8e613a2a565b60200260200101516111f9565b828281518110611dad57611dad613a2a565b6020908102919091010152600101611d71565b509392505050565b6000611df67f000000000000000000000000000000000000000000000000000000000000000063ffffffff16565b905090565b4390565b4290565b6060600083516001600160401b03811115611e2057611e20612e89565b604051908082528060200260200182016040528015611e6557816020015b6040805180820190915260008082526020820152815260200190600190039081611e3e5790505b50905060005b845181101561071457611ea1604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b611ece604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b7f00000000000000000000000000000000000000000000000000000000000000001561205157856001600160a01b0316638f693ec7888581518110611f1557611f15613a2a565b60200260200101516040518263ffffffff1660e01b8152600401611f4891906001600160a01b0391909116815260200190565b606060405180830381865afa158015611f65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f899190613e26565b604085015260208401526001600160e01b0316825286516001600160a01b03871690638181494590899086908110611fc357611fc3613a2a565b60200260200101516040518263ffffffff1660e01b8152600401611ff691906001600160a01b0391909116815260200190565b606060405180830381865afa158015612013573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120379190613e26565b604084015260208301526001600160e01b031681526121bc565b856001600160a01b0316632c427b5788858151811061207257612072613a2a565b60200260200101516040518263ffffffff1660e01b81526004016120a591906001600160a01b0391909116815260200190565b606060405180830381865afa1580156120c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e69190613e6f565b63ffffffff90811660408601521660208401526001600160e01b0316825286516001600160a01b038716906392a182359089908690811061212957612129613a2a565b60200260200101516040518263ffffffff1660e01b815260040161215c91906001600160a01b0391909116815260200190565b606060405180830381865afa158015612179573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061219d9190613e6f565b63ffffffff90811660408501521660208301526001600160e01b031681525b600060405180602001604052808986815181106121db576121db613a2a565b60200260200101516001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612220573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122449190613a11565b815250905061226e88858151811061225e5761225e613a2a565b6020026020010151888584612363565b61229288858151811061228357612283613a2a565b60200260200101518884612564565b60006122ba8986815181106122a9576122a9613a2a565b6020026020010151898c878661275b565b905060006122e38a87815181106122d3576122d3613a2a565b60200260200101518a8d8761298b565b60408051808201909152600080825260208201529091508a878151811061230c5761230c613a2a565b60209081029190910101516001600160a01b0316815261232c8284613bc2565b60208201528751819089908990811061234757612347613a2a565b6020026020010181905250505050505050806001019050611e6b565b604051637c05a7c560e01b81526001600160a01b03858116600483015260009190851690637c05a7c590602401602060405180830381865afa1580156123ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123d19190613a11565b905060006123dd611dc8565b9050600084604001511180156123f65750836040015181115b15612402575060408301515b6000612412828660200151612baf565b90506000811180156124245750600083115b1561254d576000612496886001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561246c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124909190613a11565b86612bc2565b905060006124a48386612be0565b905060008083116124c457604051806020016040528060008152506124ce565b6124ce8284612bec565b905060006124f760405180602001604052808b600001516001600160e01b031681525083612c31565b90506125328160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612c5d565b6001600160e01b03168952505050506020850182905261255b565b801561255b57602085018290525b50505050505050565b604051631d31307360e21b81526001600160a01b038481166004830152600091908416906374c4c1cc90602401602060405180830381865afa1580156125ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125d29190613a11565b905060006125de611dc8565b9050600083604001511180156125f75750826040015181115b15612603575060408201515b6000612613828560200151612baf565b90506000811180156126255750600083115b15612745576000866001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561266a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061268e9190613a11565b9050600061269c8386612be0565b905060008083116126bc57604051806020016040528060008152506126c6565b6126c68284612bec565b905060006126ef60405180602001604052808a600001516001600160e01b031681525083612c31565b905061272a8160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612c5d565b6001600160e01b031688525050505060208401829052612753565b801561275357602084018290525b505050505050565b604080516020808201835284516001600160e01b031682528251908101928390526336fe846560e11b9092526001600160a01b0387811660248401528581166044840152600092839181908916636dfd08ca60648301602060405180830381865afa1580156127ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f29190613a11565b905280519091501580156128745750866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa15801561283f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128639190613eb2565b6001600160e01b0316826000015110155b156128e757866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128b7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128db9190613eb2565b6001600160e01b031681525b60006128f38383612c99565b6040516395dd919360e01b81526001600160a01b03898116600483015291925060009161296e91908c16906395dd919390602401602060405180830381865afa158015612944573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129689190613a11565b87612bc2565b9050600061297c8284612cc5565b9b9a5050505050505050505050565b604080516020808201835283516001600160e01b0316825282519081019283905263552c097160e01b9092526001600160a01b038681166024840152848116604484015260009283918190881663552c097160648301602060405180830381865afa1580156129fe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a229190613a11565b90528051909150158015612aa45750856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a939190613eb2565b6001600160e01b0316826000015110155b15612b1757856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ae7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b0b9190613eb2565b6001600160e01b031681525b6000612b238383612c99565b6040516370a0823160e01b81526001600160a01b0388811660048301529192506000918a16906370a0823190602401602060405180830381865afa158015612b6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b939190613a11565b90506000612ba18284612cc5565b9a9950505050505050505050565b6000612bbb8284613ecd565b9392505050565b6000612bbb612bd984670de0b6b3a7640000612be0565b8351612cef565b6000612bbb8284613b89565b6040805160208101909152600081526040518060200160405280612c28612c22866ec097ce7bc90715b34b9f1000000000612be0565b85612cef565b90529392505050565b6040805160208101909152600081526040518060200160405280612c2885600001518560000151612cfb565b6000816001600160e01b03841115612c915760405162461bcd60e51b8152600401612c889190613ee0565b60405180910390fd5b509192915050565b6040805160208101909152600081526040518060200160405280612c2885600001518560000151612baf565b60006ec097ce7bc90715b34b9f1000000000612ce5848460000151612be0565b612bbb9190613ba0565b6000612bbb8284613ba0565b6000612bbb8284613bc2565b604051806101a001604052806060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160608152602001606081526020016060815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001606081525090565b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180610220016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b6001600160a01b0381168114612e7657600080fd5b50565b8035612e8481612e61565b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715612ec157612ec1612e89565b60405290565b604051606081016001600160401b0381118282101715612ec157612ec1612e89565b604051601f8201601f191681016001600160401b0381118282101715612f1157612f11612e89565b604052919050565b60006001600160401b03821115612f3257612f32612e89565b50601f01601f191660200190565b60008060408385031215612f5357600080fd5b8235612f5e81612e61565b91506020838101356001600160401b0380821115612f7b57600080fd5b9085019060a08288031215612f8f57600080fd5b612f97612e9f565b823582811115612fa657600080fd5b83019150601f82018813612fb957600080fd5b8135612fcc612fc782612f19565b612ee9565b8181528986838601011115612fe057600080fd5b818685018783013760008683830101528083525050613000848401612e79565b8482015261301060408401612e79565b60408201526060830135606082015260808301356080820152809450505050509250929050565b60005b8381101561305257818101518382015260200161303a565b50506000910152565b60008151808452613073816020860160208601613037565b601f01601f19169290920160200192915050565b80516001600160a01b031682526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e0830152610100808201518184015250610120808201518184015250610140808201518184015250610160808201516131128285018215159052565b505061018081810151908301526101a0808201516001600160a01b0316908301526101c080820151908301526101e0808201519083015261020090810151910152565b60008151808452602080850194506020840160005b838110156131915761317d878351613087565b61022096909601959082019060010161316a565b509495945050505050565b60006101a082518185526131b28286018261305b565b91505060208301516131cf60208601826001600160a01b03169052565b5060408301516131ea60408601826001600160a01b03169052565b50606083015160608501526080830151608085015260a083015184820360a0860152613216828261305b565b91505060c083015184820360c0860152613230828261305b565b91505060e083015184820360e086015261324a828261305b565b91505061010080840151613268828701826001600160a01b03169052565b505061012083810151908501526101408084015190850152610160808401519085015261018080840151858303828701526132a38382613155565b9695505050505050565b602081526000612bbb602083018461319c565b60008083601f8401126132d257600080fd5b5081356001600160401b038111156132e957600080fd5b6020830191508360208260051b850101111561330457600080fd5b9250929050565b6000806020838503121561331e57600080fd5b82356001600160401b0381111561333457600080fd5b613340858286016132c0565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b8281101561339f5761338f84835180516001600160a01b03168252602090810151910152565b9284019290850190600101613369565b5091979650505050505050565b6000602082840312156133be57600080fd5b8135612bbb81612e61565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561342057603f1988860301845261340e85835161319c565b945092850192908501906001016133f2565b5092979650505050505050565b602080825282516001600160a01b03168282015282810151604080840191909152808401516060808501528051608085018190526000939291830191849160a08701905b808410156134ab5761349782865180516001600160a01b03168252602090810151910152565b938501936001939093019290820190613471565b50979650505050505050565b600080604083850312156134ca57600080fd5b82356134d581612e61565b915060208301356134e581612e61565b809150509250929050565b60008060006060848603121561350557600080fd5b833561351081612e61565b9250602084013561352081612e61565b9150604084013561353081612e61565b809150509250925092565b600060208083018184528085518083526040925060408601915060408160051b8701018488016000805b8481101561360857898403603f19018652825180516001600160a01b03908116865289820151168986015287810151888601526060908101516080918601829052805191860182905289019060a086019084905b808210156135f3576135df83855180516001600160a01b03168252602090810151910152565b928b0192918a0191600191909101906135b9565b50509689019694505091870191600101613565565b50919998505050505050505050565b60008060006040848603121561362c57600080fd5b83356001600160401b0381111561364257600080fd5b61364e868287016132c0565b909450925050602084013561353081612e61565b80516001600160a01b031682526020808201519083015260408082015190830152606080820151908301526080808201519083015260a090810151910152565b6020808252825182820181905260009190848201906040850190845b818110156136e4576136d1838551613662565b9284019260c092909201916001016136be565b50909695505050505050565b81516001600160a01b03168152602080830151908201526040810161064f565b610220810161064f8284613087565b60c0810161064f8284613662565b6020808252825182820181905260009190848201906040850190845b818110156136e45783516001600160a01b031683529284019291840191600101613749565b60006001600160401b0382111561378757613787612e89565b5060051b60200190565b600060208083850312156137a457600080fd5b82356001600160401b038111156137ba57600080fd5b8301601f810185136137cb57600080fd5b80356137d9612fc78261376e565b81815260059190911b820183019083810190878311156137f857600080fd5b928401925b8284101561381f57833561381081612e61565b825292840192908401906137fd565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156136e457613859838551613087565b928401926102209290920191600101613846565b6000602080838503121561388057600080fd5b82516001600160401b0381111561389657600080fd5b8301601f810185136138a757600080fd5b80516138b5612fc78261376e565b81815260059190911b820183019083810190878311156138d457600080fd5b928401925b8284101561381f5783516138ec81612e61565b825292840192908401906138d9565b600082601f83011261390c57600080fd5b815161391a612fc782612f19565b81815284602083860101111561392f57600080fd5b610c41826020830160208701613037565b60006020828403121561395257600080fd5b81516001600160401b038082111561396957600080fd5b908301906060828603121561397d57600080fd5b613985612ec7565b82518281111561399457600080fd5b6139a0878286016138fb565b8252506020830151828111156139b557600080fd5b6139c1878286016138fb565b6020830152506040830151828111156139d957600080fd5b6139e5878286016138fb565b60408301525095945050505050565b600060208284031215613a0657600080fd5b8151612bbb81612e61565b600060208284031215613a2357600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600060a08284031215613a5257600080fd5b613a5a612e9f565b905081516001600160401b03811115613a7257600080fd5b613a7e848285016138fb565b8252506020820151613a8f81612e61565b60208201526040820151613aa281612e61565b80604083015250606082015160608201526080820151608082015292915050565b60006020808385031215613ad657600080fd5b82516001600160401b0380821115613aed57600080fd5b818501915085601f830112613b0157600080fd5b8151613b0f612fc78261376e565b81815260059190911b83018401908481019088831115613b2e57600080fd5b8585015b83811015613b6657805185811115613b4a5760008081fd5b613b588b89838a0101613a40565b845250918601918601613b32565b5098975050505050505050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761064f5761064f613b73565b600082613bbd57634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561064f5761064f613b73565b600060208284031215613be757600080fd5b81516001600160401b03811115613bfd57600080fd5b610c4184828501613a40565b60006020808385031215613c1c57600080fd5b82516001600160401b03811115613c3257600080fd5b8301601f81018513613c4357600080fd5b8051613c51612fc78261376e565b81815260059190911b82018301908381019087831115613c7057600080fd5b928401925b8284101561381f578351613c8881612e61565b82529284019290840190613c75565b80518015158114612e8457600080fd5b60008060408385031215613cba57600080fd5b613cc383613c97565b9150602083015190509250929050565b600060208284031215613ce557600080fd5b815160ff81168114612bbb57600080fd5b634e487b7160e01b600052602160045260246000fd5b6001600160a01b03831681526040810160098310613d3a57634e487b7160e01b600052602160045260246000fd5b8260208301529392505050565b600060208284031215613d5957600080fd5b612bbb82613c97565b600060ff821660ff8103613d7857613d78613b73565b60010192915050565b60006020808385031215613d9457600080fd5b82516001600160401b03811115613daa57600080fd5b8301601f81018513613dbb57600080fd5b8051613dc9612fc78261376e565b81815260059190911b82018301908381019087831115613de857600080fd5b928401925b8284101561381f578351613e0081612e61565b82529284019290840190613ded565b80516001600160e01b0381168114612e8457600080fd5b600080600060608486031215613e3b57600080fd5b613e4484613e0f565b925060208401519150604084015190509250925092565b805163ffffffff81168114612e8457600080fd5b600080600060608486031215613e8457600080fd5b613e8d84613e0f565b9250613e9b60208501613e5b565b9150613ea960408501613e5b565b90509250925092565b600060208284031215613ec457600080fd5b612bbb82613e0f565b8181038181111561064f5761064f613b73565b602081526000612bbb602083018461305b56fea26469706673582212200676c45ecb3b8ffe0af9232b12bc003136dfae8bdb9833c728b4a7246afcb3d664736f6c63430008190033", + "args": [false, 126144000, "0xD6e3E2A1d8d95caE355D15b3b9f8E5c2511874dd"], + "numDeployments": 2, + "solcInputHash": "09f8b2889a382752688c03578bc27f8d", + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"timeBased_\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"blocksPerYear_\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"corePoolComptroller_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidBlocksPerYear\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTimeBasedConfiguration\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"blocksOrSecondsPerYear\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"corePoolComptroller\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"}],\"name\":\"getAllPools\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockNumberOrTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getPendingRewards\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"distributorAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"rewardTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalRewards\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.PendingReward[]\",\"name\":\"pendingRewards\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.RewardSummary[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getPoolBadDebt\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalBadDebtUsd\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"badDebtUsd\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.BadDebt[]\",\"name\":\"badDebts\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.BadDebtSummary\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolByComptroller\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolRegistryInterface.VenusPool\",\"name\":\"venusPool\",\"type\":\"tuple\"}],\"name\":\"getPoolDataFromVenusPool\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getPoolsSupportedByAsset\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getVTokenForAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isTimeBased\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"vTokenBalances\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalanceCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balanceOfUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenAllowance\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenBalances\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"vTokenBalancesAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalanceCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balanceOfUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenAllowance\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenBalances[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"vTokenMetadata\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"vTokenMetadataAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"vTokenUnderlyingPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"underlyingPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenUnderlyingPrice\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"vTokenUnderlyingPriceAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"underlyingPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenUnderlyingPrice[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"params\":{\"blocksPerYear_\":\"The number of blocks per year\",\"corePoolComptroller_\":\"The address of the core pool comptroller\",\"timeBased_\":\"A boolean indicating whether the contract is based on time or block.\"}},\"getAllPools(address)\":{\"details\":\"This function is not designed to be called in a transaction: it is too gas-intensive\",\"params\":{\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"Arrays of all Venus pools' data\"}},\"getBlockNumberOrTimestamp()\":{\"details\":\"Function to simply retrieve block number or block timestamp\",\"returns\":{\"_0\":\"Current block number or block timestamp\"}},\"getPendingRewards(address,address)\":{\"params\":{\"account\":\"The user account.\",\"comptrollerAddress\":\"address\"},\"returns\":{\"_0\":\"Pending rewards array\"}},\"getPoolBadDebt(address)\":{\"params\":{\"comptrollerAddress\":\"Address of the comptroller\"},\"returns\":{\"_0\":\"badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and a break down of bad debt by market\"}},\"getPoolByComptroller(address,address)\":{\"params\":{\"comptroller\":\"The Comptroller implementation address\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"PoolData structure containing the details of the pool\"}},\"getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))\":{\"params\":{\"poolRegistryAddress\":\"Address of the PoolRegistry\",\"venusPool\":\"The VenusPool Object from PoolRegistry\"},\"returns\":{\"_0\":\"Enriched PoolData\"}},\"getPoolsSupportedByAsset(address,address)\":{\"params\":{\"asset\":\"The underlying asset of vToken\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"A list of Comptroller contracts\"}},\"getVTokenForAsset(address,address,address)\":{\"params\":{\"asset\":\"The underlyingAsset of VToken\",\"comptroller\":\"The pool comptroller\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"Address of the vToken\"}},\"vTokenBalances(address,address)\":{\"params\":{\"account\":\"The user Account\",\"vToken\":\"vToken address\"},\"returns\":{\"_0\":\"A struct containing the balances data\"}},\"vTokenBalancesAll(address[],address)\":{\"params\":{\"account\":\"The user Account\",\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"A list of structs containing balances data\"}},\"vTokenMetadata(address)\":{\"params\":{\"vToken\":\"The address of vToken\"},\"returns\":{\"_0\":\"VTokenMetadata struct\"}},\"vTokenMetadataAll(address[])\":{\"params\":{\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"An array of VTokenMetadata structs\"}},\"vTokenUnderlyingPrice(address)\":{\"params\":{\"vToken\":\"vToken address\"},\"returns\":{\"_0\":\"The price data for each asset\"}},\"vTokenUnderlyingPriceAll(address[])\":{\"params\":{\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"An array containing the price data for each asset\"}}},\"title\":\"PoolLens\",\"version\":1},\"userdoc\":{\"errors\":{\"InvalidBlocksPerYear()\":[{\"notice\":\"Thrown when blocks per year is invalid\"}],\"InvalidTimeBasedConfiguration()\":[{\"notice\":\"Thrown when time based but blocks per year is provided\"}]},\"kind\":\"user\",\"methods\":{\"blocksOrSecondsPerYear()\":{\"notice\":\"Stores blocksPerYear if isTimeBased is true else secondsPerYear is stored\"},\"corePoolComptroller()\":{\"notice\":\"Address of the core pool comptroller (all markets are returned for this pool, including paused ones)\"},\"getAllPools(address)\":{\"notice\":\"Queries all pools with addtional details for each of them\"},\"getPendingRewards(address,address)\":{\"notice\":\"Returns the pending rewards for a user for a given pool.\"},\"getPoolBadDebt(address)\":{\"notice\":\"Returns a summary of a pool's bad debt broken down by market\"},\"getPoolByComptroller(address,address)\":{\"notice\":\"Queries the details of a pool identified by Comptroller address\"},\"getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))\":{\"notice\":\"Queries additional information for the pool\"},\"getPoolsSupportedByAsset(address,address)\":{\"notice\":\"Returns all pools that support the specified underlying asset\"},\"getVTokenForAsset(address,address,address)\":{\"notice\":\"Returns vToken holding the specified underlying asset in the specified pool\"},\"isTimeBased()\":{\"notice\":\"Acknowledges if a contract is time based or not\"},\"vTokenBalances(address,address)\":{\"notice\":\"Queries the user's supply/borrow balances in the specified vToken\"},\"vTokenBalancesAll(address[],address)\":{\"notice\":\"Queries the user's supply/borrow balances in vTokens\"},\"vTokenMetadata(address)\":{\"notice\":\"Returns the metadata of VToken\"},\"vTokenMetadataAll(address[])\":{\"notice\":\"Returns the metadata of all VTokens\"},\"vTokenUnderlyingPrice(address)\":{\"notice\":\"Returns the price data for the underlying asset of the specified vToken\"},\"vTokenUnderlyingPriceAll(address[])\":{\"notice\":\"Returns the price data for the underlying assets of the specified vTokens\"}},\"notice\":\"The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be looked up for specific pools and markets: - the vToken balance of a given user; - the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address; - the vToken address in a pool for a given asset; - a list of all pools that support an asset; - the underlying asset price of a vToken; - the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Lens/PoolLens.sol\":\"PoolLens\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"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\",\"keccak256\":\"0x9140dabc466abab21b48b72dbda26736b1183a310d0e677d3719d201df026510\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x359a1ab89b46b9aba7bcad3fb651924baf4893d15153049b9976b0fc9be1358e\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x07e881de3b9f6d2c07909f193f24b96c7fe4ea60013260f3f25aecd8bab3c2f8\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x75097e35253e7fb282ee4d7f27a80eaacfa759923185bf17302a89cbc059c5ef\",\"license\":\"MIT\"},\"@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\"},\"@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\",\"keccak256\":\"0xfe0fd441c84ac907cabc88db69ef04f6d7532d770c7e6a1dfe6e7d6305debb49\",\"license\":\"BSD-3-Clause\"},\"@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 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/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface IProtocolShareReserve {\\n /// @notice it represents the type of vToken income\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(\\n address comptroller,\\n address asset,\\n IncomeType incomeType\\n ) external;\\n}\\n\",\"keccak256\":\"0x0f341bbef8f12885d79b7acaad7aaf11b84809e8f6b059ef4efc011c8f6c39a5\",\"license\":\"BSD-3-Clause\"},\"@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\",\"keccak256\":\"0x57a2bbb9b8e02b1c0a5c0e305fef1328a22db56c3d4b148c362010a6e767243c\",\"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\"},\"@venusprotocol/venus-protocol/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\",\"keccak256\":\"0xd112f60183416ad796093b4a83a80ddc1b8b655965f02ae55ca82e2a0c68f97d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/venus-protocol/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\",\"keccak256\":\"0x5285c875114db2ea2be0b81b65722d5761806217022db733323c4e03365a95e7\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IPrime } from \\\"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\\\";\\n\\nimport { ComptrollerInterface, Action } from \\\"./ComptrollerInterface.sol\\\";\\nimport { ComptrollerStorage } from \\\"./ComptrollerStorage.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"./MaxLoopsLimitHelper.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title Comptroller\\n * @author Venus\\n * @notice The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating,\\n * and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts\\n * with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows\\n * or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing\\n * liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow,\\n * as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the\\n * markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market\\u2019s corresponding liquidation threshold,\\n * the borrow is eligible for liquidation.\\n *\\n * The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed\\n * the `minLiquidatableCollateral` for the `Comptroller`:\\n *\\n * - `healAccount()`: This function is called to seize all of a given user\\u2019s collateral, requiring the `msg.sender` repay a certain percentage\\n * of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed\\n * 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt\\n * and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool.\\n * - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation\\n * incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic\\n * verifying that the repay amount does not exceed the close factor.\\n */\\ncontract Comptroller is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n ComptrollerStorage,\\n ComptrollerInterface,\\n ExponentialNoError,\\n MaxLoopsLimitHelper\\n{\\n // PoolRegistry, immutable to save on gas\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable poolRegistry;\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(VToken indexed vToken, address indexed account);\\n\\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(VToken vToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa);\\n\\n /// @notice Emitted when liquidation threshold is changed by admin\\n event NewLiquidationThreshold(\\n VToken vToken,\\n uint256 oldLiquidationThresholdMantissa,\\n uint256 newLiquidationThresholdMantissa\\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 an action is paused on a market\\n event ActionPausedMarket(VToken vToken, Action action, bool pauseState);\\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 the collateral threshold (in USD) for non-batch liquidations is changed\\n event NewMinLiquidatableCollateral(uint256 oldMinLiquidatableCollateral, uint256 newMinLiquidatableCollateral);\\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 a rewards distributor is added\\n event NewRewardsDistributor(address indexed rewardsDistributor, address indexed rewardToken);\\n\\n /// @notice Emitted when a market is supported\\n event MarketSupported(VToken vToken);\\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 a market\\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\\n\\n /// @notice Emitted when a market is unlisted\\n event MarketUnlisted(address indexed vToken);\\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 Thrown when collateral factor exceeds the upper bound\\n error InvalidCollateralFactor();\\n\\n /// @notice Thrown when liquidation threshold exceeds the collateral factor\\n error InvalidLiquidationThreshold();\\n\\n /// @notice Thrown when the action is only available to specific sender, but the real sender was different\\n error UnexpectedSender(address expectedSender, address actualSender);\\n\\n /// @notice Thrown when the oracle returns an invalid price for some asset\\n error PriceError(address vToken);\\n\\n /// @notice Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\\n error SnapshotError(address vToken, address user);\\n\\n /// @notice Thrown when the market is not listed\\n error MarketNotListed(address market);\\n\\n /// @notice Thrown when a market has an unexpected comptroller\\n error ComptrollerMismatch();\\n\\n /// @notice Thrown when user is not member of market\\n error MarketNotCollateral(address vToken, address user);\\n\\n /// @notice Thrown when borrow action is not paused\\n error BorrowActionNotPaused();\\n\\n /// @notice Thrown when mint action is not paused\\n error MintActionNotPaused();\\n\\n /// @notice Thrown when redeem action is not paused\\n error RedeemActionNotPaused();\\n\\n /// @notice Thrown when repay action is not paused\\n error RepayActionNotPaused();\\n\\n /// @notice Thrown when seize action is not paused\\n error SeizeActionNotPaused();\\n\\n /// @notice Thrown when exit market action is not paused\\n error ExitMarketActionNotPaused();\\n\\n /// @notice Thrown when transfer action is not paused\\n error TransferActionNotPaused();\\n\\n /// @notice Thrown when enter market action is not paused\\n error EnterMarketActionNotPaused();\\n\\n /// @notice Thrown when liquidate action is not paused\\n error LiquidateActionNotPaused();\\n\\n /// @notice Thrown when borrow cap is not zero\\n error BorrowCapIsNotZero();\\n\\n /// @notice Thrown when supply cap is not zero\\n error SupplyCapIsNotZero();\\n\\n /// @notice Thrown when collateral factor is not zero\\n error CollateralFactorIsNotZero();\\n\\n /**\\n * @notice Thrown during the liquidation if user's total collateral amount is lower than\\n * a predefined threshold. In this case only batch liquidations (either liquidateAccount\\n * or healAccount) are available.\\n */\\n error MinimalCollateralViolated(uint256 expectedGreaterThan, uint256 actual);\\n error CollateralExceedsThreshold(uint256 expectedLessThanOrEqualTo, uint256 actual);\\n error InsufficientCollateral(uint256 collateralToSeize, uint256 availableCollateral);\\n\\n /// @notice Thrown when the account doesn't have enough liquidity to redeem or borrow\\n error InsufficientLiquidity();\\n\\n /// @notice Thrown when trying to liquidate a healthy account\\n error InsufficientShortfall();\\n\\n /// @notice Thrown when trying to repay more than allowed by close factor\\n error TooMuchRepay();\\n\\n /// @notice Thrown if the user is trying to exit a market in which they have an outstanding debt\\n error NonzeroBorrowBalance();\\n\\n /// @notice Thrown when trying to perform an action that is paused\\n error ActionPaused(address market, Action action);\\n\\n /// @notice Thrown when trying to add a market that is already listed\\n error MarketAlreadyListed(address market);\\n\\n /// @notice Thrown if the supply cap is exceeded\\n error SupplyCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if the borrow cap is exceeded\\n error BorrowCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if delegate approval status is already set to the requested value\\n error DelegationStatusUnchanged();\\n\\n /// @param poolRegistry_ Pool registry address\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n constructor(address poolRegistry_) {\\n ensureNonzeroAddress(poolRegistry_);\\n\\n poolRegistry = poolRegistry_;\\n _disableInitializers();\\n }\\n\\n /**\\n * @param loopLimit Limit for the loops can iterate to avoid the DOS\\n * @param accessControlManager Access control manager contract address\\n */\\n function initialize(uint256 loopLimit, address accessControlManager) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager);\\n\\n _setMaxLoopsLimit(loopLimit);\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation; enabling them to be used as collateral\\n * @param vTokens The list of addresses of the vToken markets to be enabled\\n * @return errors An array of NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketEntered is emitted for each market on success\\n * @custom:error ActionPaused error is thrown if entering any of the markets is paused\\n * @custom:error MarketNotListed error is thrown if any of the markets is not listed\\n * @custom:access Not restricted\\n */\\n function enterMarkets(address[] memory vTokens) external override returns (uint256[] memory) {\\n uint256 len = vTokens.length;\\n\\n uint256[] memory results = new uint256[](len);\\n for (uint256 i; i < len; ++i) {\\n VToken vToken = VToken(vTokens[i]);\\n\\n _addToMarket(vToken, msg.sender);\\n results[i] = NO_ERROR;\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Unlist a market by setting isListed to false\\n * @dev Checks if all actions are paused, borrow/supply caps is set to 0 and collateral factor is to 0.\\n * @param market The address of the market (token) to unlist\\n * @return uint256 Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketUnlisted is emitted on success\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error BorrowActionNotPaused error is thrown if borrow action is not paused\\n * @custom:error MintActionNotPaused error is thrown if mint action is not paused\\n * @custom:error RedeemActionNotPaused error is thrown if redeem action is not paused\\n * @custom:error RepayActionNotPaused error is thrown if repay action is not paused\\n * @custom:error EnterMarketActionNotPaused error is thrown if enter market action is not paused\\n * @custom:error LiquidateActionNotPaused error is thrown if liquidate action is not paused\\n * @custom:error BorrowCapIsNotZero error is thrown if borrow cap is not zero\\n * @custom:error SupplyCapIsNotZero error is thrown if supply cap is not zero\\n * @custom:error CollateralFactorIsNotZero error is thrown if collateral factor is not zero\\n */\\n function unlistMarket(address market) external returns (uint256) {\\n _checkAccessAllowed(\\\"unlistMarket(address)\\\");\\n\\n Market storage _market = markets[market];\\n\\n if (!_market.isListed) {\\n revert MarketNotListed(market);\\n }\\n\\n if (!actionPaused(market, Action.BORROW)) {\\n revert BorrowActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.MINT)) {\\n revert MintActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.REDEEM)) {\\n revert RedeemActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.REPAY)) {\\n revert RepayActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.SEIZE)) {\\n revert SeizeActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.ENTER_MARKET)) {\\n revert EnterMarketActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.LIQUIDATE)) {\\n revert LiquidateActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.TRANSFER)) {\\n revert TransferActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.EXIT_MARKET)) {\\n revert ExitMarketActionNotPaused();\\n }\\n\\n if (borrowCaps[market] != 0) {\\n revert BorrowCapIsNotZero();\\n }\\n\\n if (supplyCaps[market] != 0) {\\n revert SupplyCapIsNotZero();\\n }\\n\\n if (_market.collateralFactorMantissa != 0) {\\n revert CollateralFactorIsNotZero();\\n }\\n\\n _market.isListed = false;\\n emit MarketUnlisted(market);\\n\\n return NO_ERROR;\\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 * @custom:event DelegateUpdated emits on success\\n * @custom:error ZeroAddressNotAllowed is thrown when delegate address is zero\\n * @custom:error DelegationStatusUnchanged is thrown if approval status is already set to the requested value\\n * @custom:access Not restricted\\n */\\n function updateDelegate(address delegate, bool approved) external {\\n ensureNonzeroAddress(delegate);\\n if (approvedDelegates[msg.sender][delegate] == approved) {\\n revert DelegationStatusUnchanged();\\n }\\n\\n approvedDelegates[msg.sender][delegate] = approved;\\n emit DelegateUpdated(msg.sender, delegate, approved);\\n }\\n\\n /**\\n * @notice Removes asset from sender's account liquidity calculation; disabling them as collateral\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketExited is emitted on success\\n * @custom:error ActionPaused error is thrown if exiting the market is paused\\n * @custom:error NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function exitMarket(address vTokenAddress) external override returns (uint256) {\\n _checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\\n VToken vToken = VToken(vTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\\n (uint256 tokensHeld, uint256 amountOwed, ) = _safeGetAccountSnapshot(vToken, msg.sender);\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n revert NonzeroBorrowBalance();\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n _checkRedeemAllowed(vTokenAddress, msg.sender, tokensHeld);\\n\\n Market storage marketToExit = markets[address(vToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return 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 // load into memory for faster iteration\\n VToken[] memory userAssetList = accountAssets[msg.sender];\\n uint256 len = userAssetList.length;\\n\\n uint256 assetIndex = len;\\n for (uint256 i; i < len; ++i) {\\n if (userAssetList[i] == vToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n VToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.pop();\\n\\n emit MarketExited(vToken, msg.sender);\\n\\n return NO_ERROR;\\n }\\n\\n /*** Policy Hooks ***/\\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 * @custom:error ActionPaused error is thrown if supplying to this market is paused\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\\n * @custom:access Not restricted\\n */\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external override {\\n _checkActionPauseState(vToken, Action.MINT);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n uint256 supplyCap = supplyCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (supplyCap != type(uint256).max) {\\n uint256 vTokenSupply = VToken(vToken).totalSupply();\\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\\n if (nextTotalSupply > supplyCap) {\\n revert SupplyCapExceeded(vToken, supplyCap);\\n }\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, minter);\\n }\\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external override {\\n _checkActionPauseState(vToken, Action.REDEEM);\\n\\n _checkRedeemAllowed(vToken, redeemer, redeemTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, redeemer);\\n }\\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 if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(redeemer, vToken);\\n }\\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 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 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 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 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 * @custom:error ActionPaused error is thrown if borrowing is paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if there is not enough collateral to borrow\\n * @custom:error BorrowCapExceeded is thrown if the borrow cap will be exceeded should this borrow succeed\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted if vToken is enabled as collateral, otherwise only vToken\\n */\\n /// disable-eslint\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external override {\\n _checkActionPauseState(vToken, Action.BORROW);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (!markets[vToken].accountMembership[borrower]) {\\n // only vTokens may call borrowAllowed if borrower not in market\\n _checkSenderIs(vToken);\\n\\n // attempt to add borrower to the market or revert\\n _addToMarket(VToken(msg.sender), borrower);\\n }\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (oracle.getUnderlyingPrice(vToken) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 borrowCap = borrowCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (borrowCap != type(uint256).max) {\\n uint256 totalBorrows = VToken(vToken).totalBorrows();\\n uint256 badDebt = VToken(vToken).badDebt();\\n uint256 nextTotalBorrows = totalBorrows + borrowAmount + badDebt;\\n if (nextTotalBorrows > borrowCap) {\\n revert BorrowCapExceeded(vToken, borrowCap);\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n borrower,\\n VToken(vToken),\\n 0,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\n }\\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 borrower The account which would borrowed the asset\\n * @custom:error ActionPaused error is thrown if repayments are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:access Not restricted\\n */\\n function preRepayHook(address vToken, address borrower) external override {\\n _checkActionPauseState(vToken, Action.REPAY);\\n\\n oracle.updatePrice(vToken);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\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 borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n * @param skipLiquidityCheck Allows the borrow to be liquidated regardless of the account liquidity\\n * @custom:error ActionPaused error is thrown if liquidations are paused in this market\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor\\n * @custom:error MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations\\n * @custom:error InsufficientShortfall is thrown when trying to liquidate a healthy account\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n */\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external override {\\n // Pause Action.LIQUIDATE on BORROWED TOKEN to prevent liquidating it.\\n // If we want to pause liquidating to vTokenCollateral, we should pause\\n // Action.SEIZE on it\\n _checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(address(vTokenBorrowed));\\n }\\n if (!markets[vTokenCollateral].isListed) {\\n revert MarketNotListed(address(vTokenCollateral));\\n }\\n\\n uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\\n\\n /* Allow accounts to be liquidated if it is a forced liquidation */\\n if (skipLiquidityCheck || isForcedLiquidationEnabled[vTokenBorrowed]) {\\n if (repayAmount > borrowBalance) {\\n revert TooMuchRepay();\\n }\\n return;\\n }\\n\\n /* The borrower must have shortfall and collateral > threshold in order to be liquidatable */\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral <= minLiquidatableCollateral) {\\n /* The liquidator should use either liquidateAccount or healAccount */\\n revert MinimalCollateralViolated(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint256 maxClose = mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance);\\n if (repayAmount > maxClose) {\\n revert TooMuchRepay();\\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 seizerContract Contract that tries to seize the asset (either borrowed vToken or Comptroller)\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @custom:error ActionPaused error is thrown if seizing this type of collateral is paused\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error ComptrollerMismatch error is when seizer contract or seized asset belong to different pools\\n * @custom:access Not restricted\\n */\\n function preSeizeHook(\\n address vTokenCollateral,\\n address seizerContract,\\n address liquidator,\\n address borrower\\n ) external override {\\n // Pause Action.SEIZE on COLLATERAL to prevent seizing it.\\n // If we want to pause liquidating vTokenBorrowed, we should pause\\n // Action.LIQUIDATE on it\\n _checkActionPauseState(vTokenCollateral, Action.SEIZE);\\n\\n Market storage market = markets[vTokenCollateral];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(vTokenCollateral);\\n }\\n\\n if (seizerContract == address(this)) {\\n // If Comptroller is the seizer, just check if collateral's comptroller\\n // is equal to the current address\\n if (address(VToken(vTokenCollateral).comptroller()) != address(this)) {\\n revert ComptrollerMismatch();\\n }\\n } else {\\n // If the seizer is not the Comptroller, check that the seizer is a\\n // listed market, and that the markets' comptrollers match\\n if (!markets[seizerContract].isListed) {\\n revert MarketNotListed(seizerContract);\\n }\\n if (VToken(vTokenCollateral).comptroller() != VToken(seizerContract).comptroller()) {\\n revert ComptrollerMismatch();\\n }\\n }\\n\\n if (!market.accountMembership[borrower]) {\\n revert MarketNotCollateral(vTokenCollateral, borrower);\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vTokenCollateral);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, borrower);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, liquidator);\\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external override {\\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 _checkRedeemAllowed(vToken, src, transferTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, src);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, dst);\\n }\\n }\\n\\n /*** Pool-level operations ***/\\n\\n /**\\n * @notice Seizes all the remaining collateral, makes msg.sender repay the existing\\n * borrows, and treats the rest of the debt as bad debt (for each market).\\n * The sender has to repay a certain percentage of the debt, computed as\\n * collateral / (borrows * liquidationIncentive).\\n * @param user account to heal\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for healing\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function healAccount(address user) external {\\n VToken[] memory userAssets = getAssetsIn(user);\\n uint256 userAssetsCount = userAssets.length;\\n\\n address liquidator = msg.sender;\\n {\\n ResilientOracleInterface oracle_ = oracle;\\n // We need all user's markets to be fresh for the computations to be correct\\n for (uint256 i; i < userAssetsCount; ++i) {\\n userAssets[i].accrueInterest();\\n oracle_.updatePrice(address(userAssets[i]));\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(user, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n // percentage = collateral / (borrows * liquidation incentive)\\n Exp memory collateral = Exp({ mantissa: snapshot.totalCollateral });\\n Exp memory scaledBorrows = mul_(\\n Exp({ mantissa: snapshot.borrows }),\\n Exp({ mantissa: liquidationIncentiveMantissa })\\n );\\n\\n Exp memory percentage = div_(collateral, scaledBorrows);\\n if (lessThanExp(Exp({ mantissa: MANTISSA_ONE }), percentage)) {\\n revert CollateralExceedsThreshold(scaledBorrows.mantissa, collateral.mantissa);\\n }\\n\\n for (uint256 i; i < userAssetsCount; ++i) {\\n VToken market = userAssets[i];\\n\\n (uint256 tokens, uint256 borrowBalance, ) = _safeGetAccountSnapshot(market, user);\\n uint256 repaymentAmount = mul_ScalarTruncate(percentage, borrowBalance);\\n\\n // Seize the entire collateral\\n if (tokens != 0) {\\n market.seize(liquidator, user, tokens);\\n }\\n // Repay a certain percentage of the borrow, forgive the rest\\n if (borrowBalance != 0) {\\n market.healBorrow(liquidator, user, repaymentAmount);\\n }\\n }\\n }\\n\\n /**\\n * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than\\n * a predefined threshold, and the account collateral can be seized to cover all borrows. If\\n * the collateral is higher than the threshold, use regular liquidations. If the collateral is\\n * below the threshold, and the account is insolvent, use healAccount.\\n * @param borrower the borrower address\\n * @param orders an array of liquidation orders\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation\\n * @custom:error InsufficientCollateral error is thrown when there is not enough collateral to cover the debt\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function liquidateAccount(address borrower, LiquidationOrder[] calldata orders) external {\\n // We will accrue interest and update the oracle prices later during the liquidation\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n // You should use the regular vToken.liquidateBorrow(...) call\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n uint256 collateralToSeize = mul_ScalarTruncate(\\n Exp({ mantissa: liquidationIncentiveMantissa }),\\n snapshot.borrows\\n );\\n if (collateralToSeize >= snapshot.totalCollateral) {\\n // There is not enough collateral to seize. Use healBorrow to repay some part of the borrow\\n // and record bad debt.\\n revert InsufficientCollateral(collateralToSeize, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n uint256 ordersCount = orders.length;\\n\\n _ensureMaxLoops(ordersCount / 2);\\n\\n for (uint256 i; i < ordersCount; ++i) {\\n if (!markets[address(orders[i].vTokenBorrowed)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenBorrowed));\\n }\\n if (!markets[address(orders[i].vTokenCollateral)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenCollateral));\\n }\\n\\n LiquidationOrder calldata order = orders[i];\\n order.vTokenBorrowed.forceLiquidateBorrow(\\n msg.sender,\\n borrower,\\n order.repayAmount,\\n order.vTokenCollateral,\\n true\\n );\\n }\\n\\n VToken[] memory borrowMarkets = getAssetsIn(borrower);\\n uint256 marketsCount = borrowMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower);\\n require(borrowBalance == 0, \\\"Nonzero borrow balance after liquidation\\\");\\n }\\n }\\n\\n /**\\n * @notice Sets the closeFactor to use when liquidating borrows\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @custom:event Emits NewCloseFactor on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCloseFactor(uint256 newCloseFactorMantissa) external {\\n _checkAccessAllowed(\\\"setCloseFactor(uint256)\\\");\\n require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, \\\"Close factor greater than maximum close factor\\\");\\n require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, \\\"Close factor smaller than minimum close factor\\\");\\n\\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev This function is restricted by the AccessControlManager\\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 * @custom:event Emits NewCollateralFactor when collateral factor is updated\\n * and NewLiquidationThreshold when liquidation threshold is updated\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InvalidCollateralFactor error is thrown when collateral factor is too high\\n * @custom:error InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor\\n * @custom:error PriceError is thrown when the oracle returns an invalid price for the asset\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCollateralFactor(\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external {\\n _checkAccessAllowed(\\\"setCollateralFactor(address,uint256,uint256)\\\");\\n\\n // Verify market is listed\\n Market storage market = markets[address(vToken)];\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Check collateral factor <= 0.9\\n if (newCollateralFactorMantissa > MAX_COLLATERAL_FACTOR_MANTISSA) {\\n revert InvalidCollateralFactor();\\n }\\n\\n // Ensure that liquidation threshold <= 1\\n if (newLiquidationThresholdMantissa > MANTISSA_ONE) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // Ensure that liquidation threshold >= CF\\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n }\\n\\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\\n emit NewLiquidationThreshold(vToken, oldLiquidationThresholdMantissa, newLiquidationThresholdMantissa);\\n }\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev This function is restricted by the AccessControlManager\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @custom:event Emits NewLiquidationIncentive on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external {\\n require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, \\\"liquidation incentive should be greater than 1e18\\\");\\n\\n _checkAccessAllowed(\\\"setLiquidationIncentive(uint256)\\\");\\n\\n // Save current value for use in log\\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\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\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Only callable by the PoolRegistry\\n * @param vToken The address of the market (token) to list\\n * @custom:error MarketAlreadyListed is thrown if the market is already listed in this pool\\n * @custom:access Only PoolRegistry\\n */\\n function supportMarket(VToken vToken) external {\\n _checkSenderIs(poolRegistry);\\n\\n if (markets[address(vToken)].isListed) {\\n revert MarketAlreadyListed(address(vToken));\\n }\\n\\n require(vToken.isVToken(), \\\"Comptroller: Invalid vToken\\\"); // Sanity check to make sure its really a VToken\\n\\n Market storage newMarket = markets[address(vToken)];\\n newMarket.isListed = true;\\n newMarket.collateralFactorMantissa = 0;\\n newMarket.liquidationThresholdMantissa = 0;\\n\\n _addMarket(address(vToken));\\n\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n rewardsDistributors[i].initializeMarket(address(vToken));\\n }\\n\\n emit MarketSupported(vToken);\\n }\\n\\n /**\\n * @notice Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A borrow cap of type(uint256).max corresponds to unlimited borrowing.\\n * @dev Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed\\n until the total borrows amount goes below the new borrow cap\\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 type(uint256).max corresponds to unlimited borrowing.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\\n _checkAccessAllowed(\\\"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 _ensureMaxLoops(numMarkets);\\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 * @notice Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A supply cap of type(uint256).max corresponds to unlimited supply.\\n * @dev Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed\\n until the total supplies amount goes below the new supply cap\\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 type(uint256).max corresponds to unlimited supply.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\\n _checkAccessAllowed(\\\"setMarketSupplyCaps(address[],uint256[])\\\");\\n uint256 vTokensCount = vTokens.length;\\n\\n require(vTokensCount != 0, \\\"invalid number of markets\\\");\\n require(vTokensCount == newSupplyCaps.length, \\\"invalid number of markets\\\");\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Pause/unpause specified actions\\n * @dev This function is restricted by the AccessControlManager\\n * @param marketsList Markets to pause/unpause the actions on\\n * @param actionsList List of action ids to pause/unpause\\n * @param paused The new paused state (true=paused, false=unpaused)\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setActionsPaused(VToken[] calldata marketsList, Action[] calldata actionsList, bool paused) external {\\n _checkAccessAllowed(\\\"setActionsPaused(address[],uint256[],bool)\\\");\\n\\n uint256 marketsCount = marketsList.length;\\n uint256 actionsCount = actionsList.length;\\n\\n _ensureMaxLoops(marketsCount * actionsCount);\\n\\n for (uint256 marketIdx; marketIdx < marketsCount; ++marketIdx) {\\n for (uint256 actionIdx; actionIdx < actionsCount; ++actionIdx) {\\n _setActionPaused(address(marketsList[marketIdx]), actionsList[actionIdx], paused);\\n }\\n }\\n }\\n\\n /**\\n * @notice Set the given collateral threshold for non-batch liquidations. Regular liquidations\\n * will fail if the collateral amount is less than this threshold. Liquidators should use batch\\n * operations like liquidateAccount or healAccount.\\n * @dev This function is restricted by the AccessControlManager\\n * @param newMinLiquidatableCollateral The new min liquidatable collateral (in USD).\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external {\\n _checkAccessAllowed(\\\"setMinLiquidatableCollateral(uint256)\\\");\\n\\n uint256 oldMinLiquidatableCollateral = minLiquidatableCollateral;\\n minLiquidatableCollateral = newMinLiquidatableCollateral;\\n emit NewMinLiquidatableCollateral(oldMinLiquidatableCollateral, newMinLiquidatableCollateral);\\n }\\n\\n /**\\n * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor\\n * contracts with the same rewardToken, and there could be overlaping among them considering the last reward slot (block or second)\\n * @dev Only callable by the admin\\n * @param _rewardsDistributor Address of the RewardDistributor contract to add\\n * @custom:access Only Governance\\n * @custom:event Emits NewRewardsDistributor with distributor address\\n */\\n function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner {\\n require(!rewardsDistributorExists[address(_rewardsDistributor)], \\\"already exists\\\");\\n\\n uint256 rewardsDistributorsLen = rewardsDistributors.length;\\n _ensureMaxLoops(rewardsDistributorsLen + 1);\\n\\n rewardsDistributors.push(_rewardsDistributor);\\n rewardsDistributorExists[address(_rewardsDistributor)] = true;\\n\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n _rewardsDistributor.initializeMarket(address(allMarkets[i]));\\n }\\n\\n emit NewRewardsDistributor(address(_rewardsDistributor), address(_rewardsDistributor.rewardToken()));\\n }\\n\\n /**\\n * @notice Sets a new price oracle for the Comptroller\\n * @dev Only callable by the admin\\n * @param newOracle Address of the new price oracle to set\\n * @custom:event Emits NewPriceOracle on success\\n * @custom:error ZeroAddressNotAllowed is thrown when the new oracle address is zero\\n */\\n function setPriceOracle(ResilientOracleInterface newOracle) external onlyOwner {\\n ensureNonzeroAddress(address(newOracle));\\n\\n ResilientOracleInterface oldOracle = oracle;\\n oracle = newOracle;\\n emit NewPriceOracle(oldOracle, newOracle);\\n }\\n\\n /**\\n * @notice Set the for loop iteration limit to avoid DOS\\n * @param limit Limit for the max loops can execute at a time\\n */\\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Sets the prime token contract for the comptroller\\n * @param _prime Address of the Prime contract\\n */\\n function setPrimeToken(IPrime _prime) external onlyOwner {\\n ensureNonzeroAddress(address(_prime));\\n\\n emit NewPrimeToken(prime, _prime);\\n prime = _prime;\\n }\\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 * @param vTokenBorrowed Borrowed vToken\\n * @param enable Whether to enable forced liquidations\\n */\\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\\n _checkAccessAllowed(\\\"setForcedLiquidation(address,bool)\\\");\\n ensureNonzeroAddress(vTokenBorrowed);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(vTokenBorrowed);\\n }\\n\\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to liquidation threshold requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of liquidation threshold requirements,\\n * @return shortfall Account shortfall below liquidation threshold requirements\\n */\\n function getAccountLiquidity(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getLiquidationThreshold);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to collateral requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of collateral requirements,\\n * @return shortfall Account shortfall below collateral requirements\\n */\\n function getBorrowingPower(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getCollateralFactor);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Hypothetical account liquidity in excess of collateral requirements,\\n * @return shortfall 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 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n account,\\n VToken(vTokenModify),\\n redeemTokens,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\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 markets The list of market addresses\\n */\\n function getAllMarkets() external view override returns (VToken[] memory) {\\n return allMarkets;\\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 /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns whether the given account is entered in a given market\\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 market specified, 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 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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return tokensToSeize Number of vTokenCollateral tokens to be seized in a liquidation\\n * @custom:error PriceError if the oracle returns an invalid price\\n */\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view override returns (uint256 error, uint256 tokensToSeize) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint256 priceBorrowedMantissa = _safeGetUnderlyingPrice(VToken(vTokenBorrowed));\\n uint256 priceCollateralMantissa = _safeGetUnderlyingPrice(VToken(vTokenCollateral));\\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 uint256 exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint256 seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n\\n numerator = mul_(Exp({ mantissa: liquidationIncentiveMantissa }), Exp({ mantissa: priceBorrowedMantissa }));\\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\\n ratio = div_(numerator, denominator);\\n\\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\\n\\n return (NO_ERROR, seizeTokens);\\n }\\n\\n /**\\n * @notice Returns reward speed given a vToken\\n * @param vToken The vToken to get the reward speeds for\\n * @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors\\n */\\n function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {\\n uint256 rewardsDistributorsLength = rewardsDistributors.length;\\n rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);\\n for (uint256 i; i < rewardsDistributorsLength; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n address rewardToken = address(rewardsDistributor.rewardToken());\\n rewardSpeeds[i] = RewardSpeeds({\\n rewardToken: rewardToken,\\n supplySpeed: rewardsDistributor.rewardTokenSupplySpeeds(vToken),\\n borrowSpeed: rewardsDistributor.rewardTokenBorrowSpeeds(vToken)\\n });\\n }\\n return rewardSpeeds;\\n }\\n\\n /**\\n * @notice Return all reward distributors for this pool\\n * @return Array of RewardDistributor addresses\\n */\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory) {\\n return rewardsDistributors;\\n }\\n\\n /**\\n * @notice A marker method that returns true for a valid Comptroller contract\\n * @return Always true\\n */\\n function isComptroller() external pure override returns (bool) {\\n return true;\\n }\\n\\n /**\\n * @notice Update the prices of all the tokens associated with the provided account\\n * @param account Address of the account to get associated tokens with\\n */\\n function updatePrices(address account) public {\\n VToken[] memory vTokens = getAssetsIn(account);\\n uint256 vTokensCount = vTokens.length;\\n\\n ResilientOracleInterface oracle_ = oracle;\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n oracle_.updatePrice(address(vTokens[i]));\\n }\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param market vToken address\\n * @param action Action to check\\n * @return paused True if the action is paused otherwise false\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][action];\\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 list with the assets the account has entered\\n */\\n function getAssetsIn(address account) public 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 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 */\\n function _addToMarket(VToken vToken, address borrower) internal {\\n _checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = markets[address(vToken)];\\n\\n if (!marketToJoin.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return;\\n }\\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\\n /**\\n * @notice Internal function to validate that a market hasn't already been added\\n * and if it hasn't adds it\\n * @param vToken The market to support\\n */\\n function _addMarket(address vToken) internal {\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n if (allMarkets[i] == VToken(vToken)) {\\n revert MarketAlreadyListed(vToken);\\n }\\n }\\n allMarkets.push(VToken(vToken));\\n marketsCount = allMarkets.length;\\n _ensureMaxLoops(marketsCount);\\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 _setActionPaused(address market, Action action, bool paused) internal {\\n require(markets[market].isListed, \\\"cannot pause a market that is not listed\\\");\\n _actionPaused[market][action] = paused;\\n emit ActionPausedMarket(VToken(market), action, paused);\\n }\\n\\n /**\\n * @dev Internal function to check that vTokens can be safely redeemed for the underlying asset.\\n * @param vToken Address of the vTokens to redeem\\n * @param redeemer Account redeeming the tokens\\n * @param redeemTokens The number of tokens to redeem\\n */\\n function _checkRedeemAllowed(address vToken, address redeemer, uint256 redeemTokens) internal {\\n Market storage market = markets[vToken];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!market.accountMembership[redeemer]) {\\n return;\\n }\\n\\n // Update the prices of tokens\\n updatePrices(redeemer);\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n _getCollateralFactor\\n );\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n }\\n\\n /**\\n * @notice Get the total collateral, weighted collateral, borrow balance, liquidity, shortfall\\n * @param account The account to get the snapshot for\\n * @param weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n * liquidation threshold. Accepts the address of the vToken and returns the weight as Exp.\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getCurrentLiquiditySnapshot(\\n address account,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n return _getHypotheticalLiquiditySnapshot(account, VToken(address(0)), 0, 0, weight);\\n }\\n\\n /**\\n * @notice Determine what the supply/borrow balances 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 weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n liquidation threshold. Accepts the address of the VToken and returns the weight\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getHypotheticalLiquiditySnapshot(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n // For each asset the account is in\\n VToken[] memory assets = getAssetsIn(account);\\n uint256 assetsCount = assets.length;\\n\\n for (uint256 i; i < assetsCount; ++i) {\\n VToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the vToken\\n (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) = _safeGetAccountSnapshot(\\n asset,\\n account\\n );\\n\\n // Get the normalized price of the asset\\n Exp memory oraclePrice = Exp({ mantissa: _safeGetUnderlyingPrice(asset) });\\n\\n // Pre-compute conversion factors from vTokens -> usd\\n Exp memory vTokenPrice = mul_(Exp({ mantissa: exchangeRateMantissa }), oraclePrice);\\n Exp memory weightedVTokenPrice = mul_(weight(asset), vTokenPrice);\\n\\n // weightedCollateral += weightedVTokenPrice * vTokenBalance\\n snapshot.weightedCollateral = mul_ScalarTruncateAddUInt(\\n weightedVTokenPrice,\\n vTokenBalance,\\n snapshot.weightedCollateral\\n );\\n\\n // totalCollateral += vTokenPrice * vTokenBalance\\n snapshot.totalCollateral = mul_ScalarTruncateAddUInt(vTokenPrice, vTokenBalance, snapshot.totalCollateral);\\n\\n // borrows += oraclePrice * borrowBalance\\n snapshot.borrows = mul_ScalarTruncateAddUInt(oraclePrice, borrowBalance, snapshot.borrows);\\n\\n // Calculate effects of interacting with vTokenModify\\n if (asset == vTokenModify) {\\n // redeem effect\\n // effects += tokensToDenom * redeemTokens\\n snapshot.effects = mul_ScalarTruncateAddUInt(weightedVTokenPrice, redeemTokens, snapshot.effects);\\n\\n // borrow effect\\n // effects += oraclePrice * borrowAmount\\n snapshot.effects = mul_ScalarTruncateAddUInt(oraclePrice, borrowAmount, snapshot.effects);\\n }\\n }\\n\\n uint256 borrowPlusEffects = snapshot.borrows + snapshot.effects;\\n // These are safe, as the underflow condition is checked first\\n unchecked {\\n if (snapshot.weightedCollateral > borrowPlusEffects) {\\n snapshot.liquidity = snapshot.weightedCollateral - borrowPlusEffects;\\n snapshot.shortfall = 0;\\n } else {\\n snapshot.liquidity = 0;\\n snapshot.shortfall = borrowPlusEffects - snapshot.weightedCollateral;\\n }\\n }\\n\\n return snapshot;\\n }\\n\\n /**\\n * @dev Retrieves price from oracle for an asset and checks it is nonzero\\n * @param asset Address for asset to query price\\n * @return Underlying price\\n */\\n function _safeGetUnderlyingPrice(VToken asset) internal view returns (uint256) {\\n uint256 oraclePriceMantissa = oracle.getUnderlyingPrice(address(asset));\\n if (oraclePriceMantissa == 0) {\\n revert PriceError(address(asset));\\n }\\n return oraclePriceMantissa;\\n }\\n\\n /**\\n * @dev Return collateral factor for a market\\n * @param asset Address for asset\\n * @return Collateral factor as exponential\\n */\\n function _getCollateralFactor(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].collateralFactorMantissa });\\n }\\n\\n /**\\n * @dev Retrieves liquidation threshold for a market as an exponential\\n * @param asset Address for asset to liquidation threshold\\n * @return Liquidation threshold as exponential\\n */\\n function _getLiquidationThreshold(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].liquidationThresholdMantissa });\\n }\\n\\n /**\\n * @dev Returns supply and borrow balances of user in vToken, reverts on failure\\n * @param vToken Market to query\\n * @param user Account address\\n * @return vTokenBalance Balance of vTokens, the same as vToken.balanceOf(user)\\n * @return borrowBalance Borrowed amount, including the interest\\n * @return exchangeRateMantissa Stored exchange rate\\n */\\n function _safeGetAccountSnapshot(\\n VToken vToken,\\n address user\\n ) internal view returns (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) {\\n uint256 err;\\n (err, vTokenBalance, borrowBalance, exchangeRateMantissa) = vToken.getAccountSnapshot(user);\\n if (err != 0) {\\n revert SnapshotError(address(vToken), user);\\n }\\n return (vTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /// @notice Reverts if the call is not from expectedSender\\n /// @param expectedSender Expected transaction sender\\n function _checkSenderIs(address expectedSender) internal view {\\n if (msg.sender != expectedSender) {\\n revert UnexpectedSender(expectedSender, msg.sender);\\n }\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n /// @param market Market to check\\n /// @param action Action to check\\n function _checkActionPauseState(address market, Action action) private view {\\n if (actionPaused(market, action)) {\\n revert ActionPaused(market, action);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7c6e1c6264e4681f82a9ac1bcd9155197a930033291ee5561ad97a56006f5e9c\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.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\\n/**\\n * @title ComptrollerInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract.\\n */\\ninterface ComptrollerInterface {\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\\n\\n function exitMarket(address vToken) external returns (uint256);\\n\\n /*** Policy Hooks ***/\\n\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external;\\n\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external;\\n\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external;\\n\\n function preRepayHook(address vToken, address borrower) external;\\n\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external;\\n\\n function preSeizeHook(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower\\n ) external;\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\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 seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external;\\n\\n function isComptroller() external view returns (bool);\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 repayAmount\\n ) external view returns (uint256, uint256);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n}\\n\\n/**\\n * @title ComptrollerViewInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract, including only some util view functions.\\n */\\ninterface ComptrollerViewInterface {\\n function markets(address) external view returns (bool, uint256);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function closeFactorMantissa() external view returns (uint256);\\n\\n function liquidationIncentiveMantissa() external view returns (uint256);\\n\\n function minLiquidatableCollateral() external view returns (uint256);\\n\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function borrowCaps(address) external view returns (uint256);\\n\\n function supplyCaps(address) external view returns (uint256);\\n\\n function approvedDelegates(address user, address delegate) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xcbf7f9977472650c61345b7cbde23e81f626e1f8863bab4c6ce3dacfc7604919\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { IPrime } from \\\"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\\\";\\nimport { Action } from \\\"./ComptrollerInterface.sol\\\";\\n\\n/**\\n * @title ComptrollerStorage\\n * @author Venus\\n * @notice Storage layout for the `Comptroller` contract.\\n */\\ncontract ComptrollerStorage {\\n struct LiquidationOrder {\\n VToken vTokenCollateral;\\n VToken vTokenBorrowed;\\n uint256 repayAmount;\\n }\\n\\n struct AccountLiquiditySnapshot {\\n uint256 totalCollateral;\\n uint256 weightedCollateral;\\n uint256 borrows;\\n uint256 effects;\\n uint256 liquidity;\\n uint256 shortfall;\\n }\\n\\n struct RewardSpeeds {\\n address rewardToken;\\n uint256 supplySpeed;\\n uint256 borrowSpeed;\\n }\\n\\n struct Market {\\n // Whether or not this market is listed\\n bool isListed;\\n // 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 uint256 collateralFactorMantissa;\\n // 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 uint256 liquidationThresholdMantissa;\\n // Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n }\\n\\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 Per-account mapping of \\\"assets you are in\\\"\\n */\\n mapping(address => VToken[]) public accountAssets;\\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 /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\\n mapping(address => uint256) public borrowCaps;\\n\\n /// @notice Minimal collateral required for regular (non-batch) liquidations\\n uint256 public minLiquidatableCollateral;\\n\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\\n mapping(address => uint256) public supplyCaps;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(Action => bool)) internal _actionPaused;\\n\\n // List of Reward Distributors added\\n RewardsDistributor[] internal rewardsDistributors;\\n\\n // Used to check if rewards distributor is added\\n mapping(address => bool) internal rewardsDistributorExists;\\n\\n /// @notice Flag indicating whether forced liquidation enabled for a market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n\\n uint256 internal constant NO_ERROR = 0;\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant MIN_CLOSE_FACTOR_MANTISSA = 0.05e18; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant MAX_CLOSE_FACTOR_MANTISSA = 0.9e18; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.95e18; // 0.95\\n\\n /// Prime token address\\n IPrime public prime;\\n\\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 /**\\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[47] private __gap;\\n}\\n\",\"keccak256\":\"0x4df44cb65ac152bac2be4b4545430e703005a74a55b72e144100b16421bd8bfd\",\"license\":\"BSD-3-Clause\"},\"contracts/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title TokenErrorReporter\\n * @author Venus\\n * @notice Errors that can be thrown by the `VToken` contract.\\n */\\ncontract TokenErrorReporter {\\n uint256 public constant NO_ERROR = 0; // support legacy return codes\\n\\n error TransferNotAllowed();\\n\\n error MintFreshnessCheck();\\n\\n error RedeemFreshnessCheck();\\n error RedeemTransferOutNotPossible();\\n\\n error BorrowFreshnessCheck();\\n error BorrowCashNotAvailable();\\n error DelegateNotApproved();\\n\\n error RepayBorrowFreshnessCheck();\\n\\n error HealBorrowUnauthorized();\\n error ForceLiquidateBorrowUnauthorized();\\n\\n error LiquidateFreshnessCheck();\\n error LiquidateCollateralFreshnessCheck();\\n error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\\n error LiquidateLiquidatorIsBorrower();\\n error LiquidateCloseAmountIsZero();\\n error LiquidateCloseAmountIsUintMax();\\n\\n error LiquidateSeizeLiquidatorIsBorrower();\\n\\n error ProtocolSeizeShareTooBig();\\n\\n error SetReserveFactorFreshCheck();\\n error SetReserveFactorBoundsCheck();\\n\\n error AddReservesFactorFreshCheck(uint256 actualAddAmount);\\n\\n error ReduceReservesFreshCheck();\\n error ReduceReservesCashNotAvailable();\\n error ReduceReservesCashValidation();\\n\\n error SetInterestRateModelFreshCheck();\\n}\\n\",\"keccak256\":\"0x7a7ced1caaac2d9242659ebd50b99f308c725ce958ac9e11f7ada404b1d97a7b\",\"license\":\"BSD-3-Clause\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from \\\"./lib/constants.sol\\\";\\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 struct Exp {\\n uint256 mantissa;\\n }\\n\\n struct Double {\\n uint256 mantissa;\\n }\\n\\n uint256 internal constant EXP_SCALE = EXP_SCALE_;\\n uint256 internal constant DOUBLE_SCALE = 1e36;\\n uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;\\n uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint256) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / EXP_SCALE;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\\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 // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint256 scalar, uint256 addend) internal pure returns (uint256) {\\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 function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\\n require(n <= type(uint224).max, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\\n require(n <= type(uint32).max, 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_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a + b;\\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_(uint256 a, uint256 b) internal pure returns (uint256) {\\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) / EXP_SCALE });\\n }\\n\\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / EXP_SCALE;\\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) / DOUBLE_SCALE });\\n }\\n\\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / DOUBLE_SCALE;\\n }\\n\\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a * b;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return div_(mul_(a, EXP_SCALE), 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, DOUBLE_SCALE), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return div_(mul_(a, DOUBLE_SCALE), b.mantissa);\\n }\\n\\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a / b;\\n }\\n\\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });\\n }\\n}\\n\",\"keccak256\":\"0x8afbe8a24fe3539c124e718681ed3dcebd24c40dd53095786c0155998213b9b0\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModel.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\nabstract contract InterestRateModel {\\n /**\\n * @notice Calculates the current borrow interest rate per slot (block or second)\\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 amount of reserves the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per slot (block or second)\\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 amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\\n * @return Always true\\n */\\n function isInterestRateModel() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xc4fda1ab75ebe4b187b707c4f10c58780f343cf343c537f641dc75d3cd28ab51\",\"license\":\"BSD-3-Clause\"},\"contracts/Lens/PoolLens.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { IERC20Metadata } from \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Action, ComptrollerInterface, ComptrollerViewInterface } from \\\"../ComptrollerInterface.sol\\\";\\nimport { PoolRegistryInterface } from \\\"../Pool/PoolRegistryInterface.sol\\\";\\nimport { PoolRegistry } from \\\"../Pool/PoolRegistry.sol\\\";\\nimport { RewardsDistributor } from \\\"../Rewards/RewardsDistributor.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\n\\n/**\\n * @title PoolLens\\n * @author Venus\\n * @notice The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information\\n * for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be\\n * looked up for specific pools and markets:\\n- the vToken balance of a given user;\\n- the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address;\\n- the vToken address in a pool for a given asset;\\n- a list of all pools that support an asset;\\n- the underlying asset price of a vToken;\\n- the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\\n */\\ncontract PoolLens is ExponentialNoError, TimeManagerV8 {\\n /**\\n * @dev Struct for PoolDetails.\\n */\\n struct PoolData {\\n string name;\\n address creator;\\n address comptroller;\\n uint256 blockPosted;\\n uint256 timestampPosted;\\n string category;\\n string logoURL;\\n string description;\\n address priceOracle;\\n uint256 closeFactor;\\n uint256 liquidationIncentive;\\n uint256 minLiquidatableCollateral;\\n VTokenMetadata[] vTokens;\\n }\\n\\n /**\\n * @dev Struct for VToken.\\n */\\n struct VTokenMetadata {\\n address vToken;\\n uint256 exchangeRateCurrent;\\n uint256 supplyRatePerBlockOrTimestamp;\\n uint256 borrowRatePerBlockOrTimestamp;\\n uint256 reserveFactorMantissa;\\n uint256 supplyCaps;\\n uint256 borrowCaps;\\n uint256 totalBorrows;\\n uint256 totalReserves;\\n uint256 totalSupply;\\n uint256 totalCash;\\n bool isListed;\\n uint256 collateralFactorMantissa;\\n address underlyingAssetAddress;\\n uint256 vTokenDecimals;\\n uint256 underlyingDecimals;\\n uint256 pausedActions;\\n }\\n\\n /**\\n * @dev Struct for VTokenBalance.\\n */\\n struct VTokenBalances {\\n address vToken;\\n uint256 balanceOf;\\n uint256 borrowBalanceCurrent;\\n uint256 balanceOfUnderlying;\\n uint256 tokenBalance;\\n uint256 tokenAllowance;\\n }\\n\\n /**\\n * @dev Struct for underlyingPrice of VToken.\\n */\\n struct VTokenUnderlyingPrice {\\n address vToken;\\n uint256 underlyingPrice;\\n }\\n\\n /**\\n * @dev Struct with pending reward info for a market.\\n */\\n struct PendingReward {\\n address vTokenAddress;\\n uint256 amount;\\n }\\n\\n /**\\n * @dev Struct with reward distribution totals for a single reward token and distributor.\\n */\\n struct RewardSummary {\\n address distributorAddress;\\n address rewardTokenAddress;\\n uint256 totalRewards;\\n PendingReward[] pendingRewards;\\n }\\n\\n /**\\n * @dev Struct used in RewardDistributor to save last updated market state.\\n */\\n struct RewardTokenState {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number or timestamp the index was last updated at\\n uint256 blockOrTimestamp;\\n // The block number or timestamp at which to stop rewards\\n uint256 lastRewardingBlockOrTimestamp;\\n }\\n\\n /**\\n * @dev Struct with bad debt of a market denominated\\n */\\n struct BadDebt {\\n address vTokenAddress;\\n uint256 badDebtUsd;\\n }\\n\\n /**\\n * @dev Struct with bad debt total denominated in usd for a pool and an array of BadDebt structs for each market\\n */\\n struct BadDebtSummary {\\n address comptroller;\\n uint256 totalBadDebtUsd;\\n BadDebt[] badDebts;\\n }\\n\\n /// @notice Address of the core pool comptroller (all markets are returned for this pool, including paused ones)\\n address public immutable corePoolComptroller;\\n\\n /**\\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @param corePoolComptroller_ The address of the core pool comptroller\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(\\n bool timeBased_,\\n uint256 blocksPerYear_,\\n address corePoolComptroller_\\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\\n corePoolComptroller = corePoolComptroller_;\\n }\\n\\n /**\\n * @notice Queries the user's supply/borrow balances in vTokens\\n * @param vTokens The list of vToken addresses\\n * @param account The user Account\\n * @return A list of structs containing balances data\\n */\\n function vTokenBalancesAll(VToken[] calldata vTokens, address account) external returns (VTokenBalances[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenBalances[] memory res = new VTokenBalances[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenBalances(vTokens[i], account);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Queries all pools with addtional details for each of them\\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @return Arrays of all Venus pools' data\\n */\\n function getAllPools(address poolRegistryAddress) external view returns (PoolData[] memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n PoolRegistry.VenusPool[] memory venusPools = poolRegistryInterface.getAllPools();\\n uint256 poolLength = venusPools.length;\\n\\n PoolData[] memory poolDataItems = new PoolData[](poolLength);\\n\\n for (uint256 i; i < poolLength; ++i) {\\n PoolRegistry.VenusPool memory venusPool = venusPools[i];\\n PoolData memory poolData = getPoolDataFromVenusPool(poolRegistryAddress, venusPool);\\n poolDataItems[i] = poolData;\\n }\\n\\n return poolDataItems;\\n }\\n\\n /**\\n * @notice Queries the details of a pool identified by Comptroller address\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param comptroller The Comptroller implementation address\\n * @return PoolData structure containing the details of the pool\\n */\\n function getPoolByComptroller(\\n address poolRegistryAddress,\\n address comptroller\\n ) external view returns (PoolData memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return getPoolDataFromVenusPool(poolRegistryAddress, poolRegistryInterface.getPoolByComptroller(comptroller));\\n }\\n\\n /**\\n * @notice Returns vToken holding the specified underlying asset in the specified pool\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param comptroller The pool comptroller\\n * @param asset The underlyingAsset of VToken\\n * @return Address of the vToken\\n */\\n function getVTokenForAsset(\\n address poolRegistryAddress,\\n address comptroller,\\n address asset\\n ) external view returns (address) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return poolRegistryInterface.getVTokenForAsset(comptroller, asset);\\n }\\n\\n /**\\n * @notice Returns all pools that support the specified underlying asset\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param asset The underlying asset of vToken\\n * @return A list of Comptroller contracts\\n */\\n function getPoolsSupportedByAsset(\\n address poolRegistryAddress,\\n address asset\\n ) external view returns (address[] memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return poolRegistryInterface.getPoolsSupportedByAsset(asset);\\n }\\n\\n /**\\n * @notice Returns the price data for the underlying assets of the specified vTokens\\n * @param vTokens The list of vToken addresses\\n * @return An array containing the price data for each asset\\n */\\n function vTokenUnderlyingPriceAll(\\n VToken[] calldata vTokens\\n ) external view returns (VTokenUnderlyingPrice[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenUnderlyingPrice[] memory res = new VTokenUnderlyingPrice[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenUnderlyingPrice(vTokens[i]);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Returns the pending rewards for a user for a given pool.\\n * @param account The user account.\\n * @param comptrollerAddress address\\n * @return Pending rewards array\\n */\\n function getPendingRewards(\\n address account,\\n address comptrollerAddress\\n ) external view returns (RewardSummary[] memory) {\\n VToken[] memory markets = _getMarkets(ComptrollerInterface(comptrollerAddress));\\n RewardsDistributor[] memory rewardsDistributors = ComptrollerViewInterface(comptrollerAddress)\\n .getRewardDistributors();\\n RewardSummary[] memory rewardSummary = new RewardSummary[](rewardsDistributors.length);\\n for (uint256 i; i < rewardsDistributors.length; ++i) {\\n RewardSummary memory reward;\\n reward.distributorAddress = address(rewardsDistributors[i]);\\n reward.rewardTokenAddress = address(rewardsDistributors[i].rewardToken());\\n reward.totalRewards = rewardsDistributors[i].rewardTokenAccrued(account);\\n reward.pendingRewards = _calculateNotDistributedAwards(account, markets, rewardsDistributors[i]);\\n rewardSummary[i] = reward;\\n }\\n return rewardSummary;\\n }\\n\\n /**\\n * @notice Returns a summary of a pool's bad debt broken down by market\\n *\\n * @param comptrollerAddress Address of the comptroller\\n *\\n * @return badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and\\n * a break down of bad debt by market\\n */\\n function getPoolBadDebt(address comptrollerAddress) external view returns (BadDebtSummary memory) {\\n uint256 totalBadDebtUsd;\\n\\n // Get every listed market in the pool\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\\n VToken[] memory markets = _getMarkets(ComptrollerInterface(comptrollerAddress));\\n ResilientOracleInterface priceOracle = comptroller.oracle();\\n\\n BadDebt[] memory badDebts = new BadDebt[](markets.length);\\n\\n BadDebtSummary memory badDebtSummary;\\n badDebtSummary.comptroller = comptrollerAddress;\\n badDebtSummary.badDebts = badDebts;\\n\\n // // Calculate the bad debt is USD per market\\n for (uint256 i; i < markets.length; ++i) {\\n BadDebt memory badDebt;\\n badDebt.vTokenAddress = address(markets[i]);\\n badDebt.badDebtUsd =\\n (VToken(address(markets[i])).badDebt() * priceOracle.getUnderlyingPrice(address(markets[i]))) /\\n EXP_SCALE;\\n badDebtSummary.badDebts[i] = badDebt;\\n totalBadDebtUsd = totalBadDebtUsd + badDebt.badDebtUsd;\\n }\\n\\n badDebtSummary.totalBadDebtUsd = totalBadDebtUsd;\\n\\n return badDebtSummary;\\n }\\n\\n /**\\n * @notice Queries the user's supply/borrow balances in the specified vToken\\n * @param vToken vToken address\\n * @param account The user Account\\n * @return A struct containing the balances data\\n */\\n function vTokenBalances(VToken vToken, address account) public returns (VTokenBalances memory) {\\n uint256 balanceOf = vToken.balanceOf(account);\\n uint256 borrowBalanceCurrent = vToken.borrowBalanceCurrent(account);\\n uint256 balanceOfUnderlying = vToken.balanceOfUnderlying(account);\\n uint256 tokenBalance;\\n uint256 tokenAllowance;\\n\\n IERC20 underlying = IERC20(vToken.underlying());\\n tokenBalance = underlying.balanceOf(account);\\n tokenAllowance = underlying.allowance(account, address(vToken));\\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 Queries additional information for the pool\\n * @param poolRegistryAddress Address of the PoolRegistry\\n * @param venusPool The VenusPool Object from PoolRegistry\\n * @return Enriched PoolData\\n */\\n function getPoolDataFromVenusPool(\\n address poolRegistryAddress,\\n PoolRegistry.VenusPool memory venusPool\\n ) public view returns (PoolData memory) {\\n // Get tokens in the Pool\\n ComptrollerInterface comptrollerInstance = ComptrollerInterface(venusPool.comptroller);\\n\\n VToken[] memory vTokens = _getMarkets(comptrollerInstance);\\n\\n VTokenMetadata[] memory vTokenMetadataItems = vTokenMetadataAll(vTokens);\\n\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n\\n PoolRegistry.VenusPoolMetaData memory venusPoolMetaData = poolRegistryInterface.getVenusPoolMetadata(\\n venusPool.comptroller\\n );\\n\\n ComptrollerViewInterface comptrollerViewInstance = ComptrollerViewInterface(venusPool.comptroller);\\n\\n PoolData memory poolData = PoolData({\\n name: venusPool.name,\\n creator: venusPool.creator,\\n comptroller: venusPool.comptroller,\\n blockPosted: venusPool.blockPosted,\\n timestampPosted: venusPool.timestampPosted,\\n category: venusPoolMetaData.category,\\n logoURL: venusPoolMetaData.logoURL,\\n description: venusPoolMetaData.description,\\n vTokens: vTokenMetadataItems,\\n priceOracle: address(comptrollerViewInstance.oracle()),\\n closeFactor: comptrollerViewInstance.closeFactorMantissa(),\\n liquidationIncentive: comptrollerViewInstance.liquidationIncentiveMantissa(),\\n minLiquidatableCollateral: comptrollerViewInstance.minLiquidatableCollateral()\\n });\\n\\n return poolData;\\n }\\n\\n /**\\n * @notice Returns the metadata of VToken\\n * @param vToken The address of vToken\\n * @return VTokenMetadata struct\\n */\\n function vTokenMetadata(VToken vToken) public view returns (VTokenMetadata memory) {\\n uint256 exchangeRateCurrent = vToken.exchangeRateStored();\\n address comptrollerAddress = address(vToken.comptroller());\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\\n (bool isListed, uint256 collateralFactorMantissa) = comptroller.markets(address(vToken));\\n\\n address underlyingAssetAddress = vToken.underlying();\\n uint256 underlyingDecimals = IERC20Metadata(underlyingAssetAddress).decimals();\\n\\n uint256 pausedActions;\\n for (uint8 i; i <= uint8(type(Action).max); ++i) {\\n uint256 paused = ComptrollerInterface(comptrollerAddress).actionPaused(address(vToken), Action(i)) ? 1 : 0;\\n pausedActions |= paused << i;\\n }\\n\\n uint256 supplyRatePerBlock;\\n\\n if (vToken.totalSupply() > 0) {\\n supplyRatePerBlock = vToken.supplyRatePerBlock();\\n }\\n\\n return\\n VTokenMetadata({\\n vToken: address(vToken),\\n exchangeRateCurrent: exchangeRateCurrent,\\n supplyRatePerBlockOrTimestamp: supplyRatePerBlock,\\n borrowRatePerBlockOrTimestamp: vToken.borrowRatePerBlock(),\\n reserveFactorMantissa: vToken.reserveFactorMantissa(),\\n supplyCaps: comptroller.supplyCaps(address(vToken)),\\n borrowCaps: comptroller.borrowCaps(address(vToken)),\\n totalBorrows: vToken.totalBorrows(),\\n totalReserves: vToken.totalReserves(),\\n totalSupply: vToken.totalSupply(),\\n totalCash: vToken.getCash(),\\n isListed: isListed,\\n collateralFactorMantissa: collateralFactorMantissa,\\n underlyingAssetAddress: underlyingAssetAddress,\\n vTokenDecimals: vToken.decimals(),\\n underlyingDecimals: underlyingDecimals,\\n pausedActions: pausedActions\\n });\\n }\\n\\n /**\\n * @notice Returns the metadata of all VTokens\\n * @param vTokens The list of vToken addresses\\n * @return An array of VTokenMetadata structs\\n */\\n function vTokenMetadataAll(VToken[] memory vTokens) public view returns (VTokenMetadata[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenMetadata[] memory res = new VTokenMetadata[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenMetadata(vTokens[i]);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Returns the price data for the underlying asset of the specified vToken\\n * @param vToken vToken address\\n * @return The price data for each asset\\n */\\n function vTokenUnderlyingPrice(VToken vToken) public view returns (VTokenUnderlyingPrice memory) {\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(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 Returns markets from a comptroller. For the core pool, all markets are returned.\\n * For other pools, markets with zero internalCash are filtered.\\n * @param comptroller The comptroller to query\\n * @return An array of VToken addresses\\n */\\n function _getMarkets(ComptrollerInterface comptroller) internal view returns (VToken[] memory) {\\n VToken[] memory allMarkets = comptroller.getAllMarkets();\\n\\n if (address(comptroller) == corePoolComptroller) {\\n return allMarkets;\\n }\\n\\n // Single-loop filter: pack active markets to the front of allMarkets\\n uint256 count;\\n uint256 len = allMarkets.length;\\n for (uint256 i; i < len; ++i) {\\n if (allMarkets[i].internalCash() > 0) {\\n allMarkets[count] = allMarkets[i];\\n ++count;\\n }\\n }\\n\\n // Trim the array to the active count\\n assembly {\\n mstore(allMarkets, count)\\n }\\n\\n return allMarkets;\\n }\\n\\n function _calculateNotDistributedAwards(\\n address account,\\n VToken[] memory markets,\\n RewardsDistributor rewardsDistributor\\n ) internal view returns (PendingReward[] memory) {\\n PendingReward[] memory pendingRewards = new PendingReward[](markets.length);\\n\\n for (uint256 i; i < markets.length; ++i) {\\n // Market borrow and supply state we will modify update in-memory, in order to not modify storage\\n RewardTokenState memory borrowState;\\n RewardTokenState memory supplyState;\\n\\n if (isTimeBased) {\\n (\\n borrowState.index,\\n borrowState.blockOrTimestamp,\\n borrowState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenBorrowStateTimeBased(address(markets[i]));\\n (\\n supplyState.index,\\n supplyState.blockOrTimestamp,\\n supplyState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenSupplyStateTimeBased(address(markets[i]));\\n } else {\\n (\\n borrowState.index,\\n borrowState.blockOrTimestamp,\\n borrowState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenBorrowState(address(markets[i]));\\n (\\n supplyState.index,\\n supplyState.blockOrTimestamp,\\n supplyState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenSupplyState(address(markets[i]));\\n }\\n\\n Exp memory marketBorrowIndex = Exp({ mantissa: markets[i].borrowIndex() });\\n\\n // Update market supply and borrow index in-memory\\n updateMarketBorrowIndex(address(markets[i]), rewardsDistributor, borrowState, marketBorrowIndex);\\n updateMarketSupplyIndex(address(markets[i]), rewardsDistributor, supplyState);\\n\\n // Calculate pending rewards\\n uint256 borrowReward = calculateBorrowerReward(\\n address(markets[i]),\\n rewardsDistributor,\\n account,\\n borrowState,\\n marketBorrowIndex\\n );\\n uint256 supplyReward = calculateSupplierReward(\\n address(markets[i]),\\n rewardsDistributor,\\n account,\\n supplyState\\n );\\n\\n PendingReward memory pendingReward;\\n pendingReward.vTokenAddress = address(markets[i]);\\n pendingReward.amount = borrowReward + supplyReward;\\n pendingRewards[i] = pendingReward;\\n }\\n return pendingRewards;\\n }\\n\\n function updateMarketBorrowIndex(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n RewardTokenState memory borrowState,\\n Exp memory marketBorrowIndex\\n ) internal view {\\n uint256 borrowSpeed = rewardsDistributor.rewardTokenBorrowSpeeds(vToken);\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (\\n borrowState.lastRewardingBlockOrTimestamp > 0 &&\\n blockNumberOrTimestamp > borrowState.lastRewardingBlockOrTimestamp\\n ) {\\n blockNumberOrTimestamp = borrowState.lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, borrowState.blockOrTimestamp);\\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\\n // Remove the total earned interest rate since the opening of the market from total borrows\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, borrowSpeed);\\n Double memory ratio = borrowAmount > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\\n } else if (deltaBlocksOrTimestamp > 0) {\\n borrowState.blockOrTimestamp = blockNumberOrTimestamp;\\n }\\n }\\n\\n function updateMarketSupplyIndex(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n RewardTokenState memory supplyState\\n ) internal view {\\n uint256 supplySpeed = rewardsDistributor.rewardTokenSupplySpeeds(vToken);\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (\\n supplyState.lastRewardingBlockOrTimestamp > 0 &&\\n blockNumberOrTimestamp > supplyState.lastRewardingBlockOrTimestamp\\n ) {\\n blockNumberOrTimestamp = supplyState.lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, supplyState.blockOrTimestamp);\\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, supplySpeed);\\n Double memory ratio = supplyTokens > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\\n } else if (deltaBlocksOrTimestamp > 0) {\\n supplyState.blockOrTimestamp = blockNumberOrTimestamp;\\n }\\n }\\n\\n function calculateBorrowerReward(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n address borrower,\\n RewardTokenState memory borrowState,\\n Exp memory marketBorrowIndex\\n ) internal view returns (uint256) {\\n Double memory borrowIndex = Double({ mantissa: borrowState.index });\\n Double memory borrowerIndex = Double({\\n mantissa: rewardsDistributor.rewardTokenBorrowerIndex(vToken, borrower)\\n });\\n if (borrowerIndex.mantissa == 0 && borrowIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set\\n borrowerIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\\n }\\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n return borrowerDelta;\\n }\\n\\n function calculateSupplierReward(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n address supplier,\\n RewardTokenState memory supplyState\\n ) internal view returns (uint256) {\\n Double memory supplyIndex = Double({ mantissa: supplyState.index });\\n Double memory supplierIndex = Double({\\n mantissa: rewardsDistributor.rewardTokenSupplierIndex(vToken, supplier)\\n });\\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\\n // Covers the case where users supplied tokens before the market's supply state index was set\\n supplierIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\\n }\\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n return supplierDelta;\\n }\\n}\\n\",\"keccak256\":\"0xfe3f00ebb7f0b5c98ee03cf1cfa1a013a56984cf6879373c70a74b3d9d0db399\",\"license\":\"BSD-3-Clause\"},\"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\",\"keccak256\":\"0x4c25e30635485d162177effa384eee51768b0141a567a0da16ff6ad673274166\",\"license\":\"BSD-3-Clause\"},\"contracts/Pool/PoolRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\nimport { PoolRegistryInterface } from \\\"./PoolRegistryInterface.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"../lib/validators.sol\\\";\\n\\n/**\\n * @title PoolRegistry\\n * @author Venus\\n * @notice The Isolated Pools architecture centers around the `PoolRegistry` contract. The `PoolRegistry` maintains a directory of isolated lending\\n * pools and can perform actions like creating and registering new pools, adding new markets to existing pools, setting and updating the pool's required\\n * metadata, and providing the getter methods to get information on the pools.\\n *\\n * Isolated lending has three main components: PoolRegistry, pools, and markets. The PoolRegistry is responsible for managing pools.\\n * It can create new pools, update pool metadata and manage markets within pools. PoolRegistry contains getter methods to get the details of\\n * any existing pool like `getVTokenForAsset` and `getPoolsSupportedByAsset`. It also contains methods for updating pool metadata (`updatePoolMetadata`)\\n * and setting pool name (`setPoolName`).\\n *\\n * The directory of pools is managed through two mappings: `_poolByComptroller` which is a hashmap with the comptroller address as the key and `VenusPool` as\\n * the value and `_poolsByID` which is an array of comptroller addresses. Individual pools can be accessed by calling `getPoolByComptroller` with the pool's\\n * comptroller address. `_poolsByID` is used to iterate through all of the pools.\\n *\\n * PoolRegistry also contains a map of asset addresses called `_supportedPools` that maps to an array of assets suppored by each pool. This array of pools by\\n * asset is retrieved by calling `getPoolsSupportedByAsset`.\\n *\\n * PoolRegistry registers new isolated pools in the directory with the `createRegistryPool` method. Isolated pools are composed of independent markets with\\n * specific assets and custom risk management configurations according to their markets.\\n */\\ncontract PoolRegistry is Ownable2StepUpgradeable, AccessControlledV8, PoolRegistryInterface {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n struct AddMarketInput {\\n VToken vToken;\\n uint256 collateralFactor;\\n uint256 liquidationThreshold;\\n uint256 initialSupply;\\n address vTokenReceiver;\\n uint256 supplyCap;\\n uint256 borrowCap;\\n }\\n\\n uint256 internal constant MAX_POOL_NAME_LENGTH = 100;\\n\\n /**\\n * @notice Maps pool's comptroller address to metadata.\\n */\\n mapping(address => VenusPoolMetaData) public metadata;\\n\\n /**\\n * @dev Maps pool ID to pool's comptroller address\\n */\\n mapping(uint256 => address) private _poolsByID;\\n\\n /**\\n * @dev Total number of pools created.\\n */\\n uint256 private _numberOfPools;\\n\\n /**\\n * @dev Maps comptroller address to Venus pool Index.\\n */\\n mapping(address => VenusPool) private _poolByComptroller;\\n\\n /**\\n * @dev Maps pool's comptroller address to asset to vToken.\\n */\\n mapping(address => mapping(address => address)) private _vTokens;\\n\\n /**\\n * @dev Maps asset to list of supported pools.\\n */\\n mapping(address => address[]) private _supportedPools;\\n\\n /**\\n * @notice Emitted when a new Venus pool is added to the directory.\\n */\\n event PoolRegistered(address indexed comptroller, VenusPool pool);\\n\\n /**\\n * @notice Emitted when a pool name is set.\\n */\\n event PoolNameSet(address indexed comptroller, string oldName, string newName);\\n\\n /**\\n * @notice Emitted when a pool metadata is updated.\\n */\\n event PoolMetadataUpdated(\\n address indexed comptroller,\\n VenusPoolMetaData oldMetadata,\\n VenusPoolMetaData newMetadata\\n );\\n\\n /**\\n * @notice Emitted when a Market is added to the pool.\\n */\\n event MarketAdded(address indexed comptroller, address indexed vTokenAddress);\\n\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor() {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializes the deployer to owner\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(address accessControlManager_) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n /**\\n * @notice Adds a new Venus pool to the directory\\n * @dev Price oracle must be configured before adding a pool\\n * @param name The name of the pool\\n * @param comptroller Pool's Comptroller contract\\n * @param closeFactor The pool's close factor (scaled by 1e18)\\n * @param liquidationIncentive The pool's liquidation incentive (scaled by 1e18)\\n * @param minLiquidatableCollateral Minimal collateral for regular (non-batch) liquidations flow\\n * @return index The index of the registered Venus pool\\n * @custom:error ZeroAddressNotAllowed is thrown when Comptroller address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\\n */\\n function addPool(\\n string calldata name,\\n Comptroller comptroller,\\n uint256 closeFactor,\\n uint256 liquidationIncentive,\\n uint256 minLiquidatableCollateral\\n ) external virtual returns (uint256 index) {\\n _checkAccessAllowed(\\\"addPool(string,address,uint256,uint256,uint256)\\\");\\n // Input validation\\n ensureNonzeroAddress(address(comptroller));\\n ensureNonzeroAddress(address(comptroller.oracle()));\\n\\n uint256 poolId = _registerPool(name, address(comptroller));\\n\\n // Set Venus pool parameters\\n comptroller.setCloseFactor(closeFactor);\\n comptroller.setLiquidationIncentive(liquidationIncentive);\\n comptroller.setMinLiquidatableCollateral(minLiquidatableCollateral);\\n\\n return poolId;\\n }\\n\\n /**\\n * @notice Add a market to an existing pool and then mint to provide initial supply\\n * @param input The structure describing the parameters for adding a market to a pool\\n * @custom:error ZeroAddressNotAllowed is thrown when vToken address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when vTokenReceiver address is zero\\n */\\n function addMarket(AddMarketInput memory input) external {\\n _checkAccessAllowed(\\\"addMarket(AddMarketInput)\\\");\\n ensureNonzeroAddress(address(input.vToken));\\n ensureNonzeroAddress(input.vTokenReceiver);\\n require(input.initialSupply > 0, \\\"PoolRegistry: initialSupply is zero\\\");\\n\\n VToken vToken = input.vToken;\\n address vTokenAddress = address(vToken);\\n address comptrollerAddress = address(vToken.comptroller());\\n Comptroller comptroller = Comptroller(comptrollerAddress);\\n address underlyingAddress = vToken.underlying();\\n IERC20Upgradeable underlying = IERC20Upgradeable(underlyingAddress);\\n\\n require(_poolByComptroller[comptrollerAddress].creator != address(0), \\\"PoolRegistry: Pool not registered\\\");\\n // solhint-disable-next-line reason-string\\n require(\\n _vTokens[comptrollerAddress][underlyingAddress] == address(0),\\n \\\"PoolRegistry: Market already added for asset comptroller combination\\\"\\n );\\n\\n comptroller.supportMarket(vToken);\\n comptroller.setCollateralFactor(vToken, input.collateralFactor, input.liquidationThreshold);\\n\\n uint256[] memory newSupplyCaps = new uint256[](1);\\n uint256[] memory newBorrowCaps = new uint256[](1);\\n VToken[] memory vTokens = new VToken[](1);\\n\\n newSupplyCaps[0] = input.supplyCap;\\n newBorrowCaps[0] = input.borrowCap;\\n vTokens[0] = vToken;\\n\\n comptroller.setMarketSupplyCaps(vTokens, newSupplyCaps);\\n comptroller.setMarketBorrowCaps(vTokens, newBorrowCaps);\\n\\n _vTokens[comptrollerAddress][underlyingAddress] = vTokenAddress;\\n _supportedPools[underlyingAddress].push(comptrollerAddress);\\n\\n uint256 amountToSupply = _transferIn(underlying, msg.sender, input.initialSupply);\\n underlying.forceApprove(vTokenAddress, 0);\\n underlying.forceApprove(vTokenAddress, amountToSupply);\\n vToken.mintBehalf(input.vTokenReceiver, amountToSupply);\\n\\n emit MarketAdded(comptrollerAddress, vTokenAddress);\\n }\\n\\n /**\\n * @notice Modify existing Venus pool name\\n * @param comptroller Pool's Comptroller\\n * @param name New pool name\\n */\\n function setPoolName(address comptroller, string calldata name) external {\\n _checkAccessAllowed(\\\"setPoolName(address,string)\\\");\\n _ensureValidName(name);\\n VenusPool storage pool = _poolByComptroller[comptroller];\\n string memory oldName = pool.name;\\n pool.name = name;\\n emit PoolNameSet(comptroller, oldName, name);\\n }\\n\\n /**\\n * @notice Update metadata of an existing pool\\n * @param comptroller Pool's Comptroller\\n * @param metadata_ New pool metadata\\n */\\n function updatePoolMetadata(address comptroller, VenusPoolMetaData calldata metadata_) external {\\n _checkAccessAllowed(\\\"updatePoolMetadata(address,VenusPoolMetaData)\\\");\\n VenusPoolMetaData memory oldMetadata = metadata[comptroller];\\n metadata[comptroller] = metadata_;\\n emit PoolMetadataUpdated(comptroller, oldMetadata, metadata_);\\n }\\n\\n /**\\n * @notice Returns arrays of all Venus pools' data\\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\\n * @return A list of all pools within PoolRegistry, with details for each pool\\n */\\n function getAllPools() external view override returns (VenusPool[] memory) {\\n uint256 numberOfPools_ = _numberOfPools; // storage load to save gas\\n VenusPool[] memory _pools = new VenusPool[](numberOfPools_);\\n for (uint256 i = 1; i <= numberOfPools_; ++i) {\\n address comptroller = _poolsByID[i];\\n _pools[i - 1] = (_poolByComptroller[comptroller]);\\n }\\n return _pools;\\n }\\n\\n /**\\n * @param comptroller The comptroller proxy address associated to the pool\\n * @return Returns Venus pool\\n */\\n function getPoolByComptroller(address comptroller) external view override returns (VenusPool memory) {\\n return _poolByComptroller[comptroller];\\n }\\n\\n /**\\n * @param comptroller comptroller of Venus pool\\n * @return Returns Metadata of Venus pool\\n */\\n function getVenusPoolMetadata(address comptroller) external view override returns (VenusPoolMetaData memory) {\\n return metadata[comptroller];\\n }\\n\\n function getVTokenForAsset(address comptroller, address asset) external view override returns (address) {\\n return _vTokens[comptroller][asset];\\n }\\n\\n function getPoolsSupportedByAsset(address asset) external view override returns (address[] memory) {\\n return _supportedPools[asset];\\n }\\n\\n /**\\n * @dev Adds a new Venus pool to the directory (without checking msg.sender).\\n * @param name The name of the pool\\n * @param comptroller The pool's Comptroller proxy contract address\\n * @return The index of the registered Venus pool\\n */\\n function _registerPool(string calldata name, address comptroller) internal returns (uint256) {\\n VenusPool storage storedPool = _poolByComptroller[comptroller];\\n\\n require(storedPool.creator == address(0), \\\"PoolRegistry: Pool already exists in the directory.\\\");\\n _ensureValidName(name);\\n\\n ++_numberOfPools;\\n uint256 numberOfPools_ = _numberOfPools; // cache on stack to save storage read gas\\n\\n VenusPool memory pool = VenusPool(name, msg.sender, comptroller, block.number, block.timestamp);\\n\\n _poolsByID[numberOfPools_] = comptroller;\\n _poolByComptroller[comptroller] = pool;\\n\\n emit PoolRegistered(comptroller, pool);\\n return numberOfPools_;\\n }\\n\\n function _transferIn(IERC20Upgradeable token, address from, uint256 amount) internal returns (uint256) {\\n uint256 balanceBefore = token.balanceOf(address(this));\\n token.safeTransferFrom(from, address(this), amount);\\n uint256 balanceAfter = token.balanceOf(address(this));\\n return balanceAfter - balanceBefore;\\n }\\n\\n function _ensureValidName(string calldata name) internal pure {\\n require(bytes(name).length <= MAX_POOL_NAME_LENGTH, \\\"Pool's name is too large\\\");\\n }\\n}\\n\",\"keccak256\":\"0xafbb871f7b4db3ef439d846baa5f18a136192f9b43ea695c81262a77b06c4b25\",\"license\":\"BSD-3-Clause\"},\"contracts/Pool/PoolRegistryInterface.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 /**\\n * @notice Struct for a Venus interest rate pool metadata.\\n */\\n struct VenusPoolMetaData {\\n string category;\\n string logoURL;\\n string description;\\n }\\n\\n /// @notice Get all pools in PoolRegistry\\n function getAllPools() external view returns (VenusPool[] memory);\\n\\n /// @notice Get a pool by comptroller address\\n function getPoolByComptroller(address comptroller) external view returns (VenusPool memory);\\n\\n /// @notice Get the address of the VToken contract in the Pool where the underlying token is the provided 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 /// @notice Get the metadata of a Pool by comptroller address\\n function getVenusPoolMetadata(address comptroller) external view returns (VenusPoolMetaData memory);\\n}\\n\",\"keccak256\":\"0x7b39cda3b372a686501ce3c2aad288c6af410148110318249d75d4516729c92c\",\"license\":\"BSD-3-Clause\"},\"contracts/Rewards/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\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 { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"../MaxLoopsLimitHelper.sol\\\";\\nimport { RewardsDistributorStorage } from \\\"./RewardsDistributorStorage.sol\\\";\\n\\n/**\\n * @title `RewardsDistributor`\\n * @author Venus\\n * @notice Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol.\\n * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward\\n * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool.\\n * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward\\n * token to be released each slot (block or second) for borrowers and suppliers, which is distributed based on a user\\u2019s percentage of the borrows or supplies\\n * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting\\n * their contributor reward token speed, which similarly allocates a fixed amount of reward token per slot (block or second).\\n *\\n * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed\\n * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized\\n * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\\n */\\ncontract RewardsDistributor is\\n ExponentialNoError,\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n MaxLoopsLimitHelper,\\n RewardsDistributorStorage,\\n TimeManagerV8\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice The initial REWARD TOKEN index for a market\\n uint224 public constant INITIAL_INDEX = 1e36;\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a supplier\\n event DistributedSupplierRewardToken(\\n VToken indexed vToken,\\n address indexed supplier,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenSupplyIndex\\n );\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a borrower\\n event DistributedBorrowerRewardToken(\\n VToken indexed vToken,\\n address indexed borrower,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenBorrowIndex\\n );\\n\\n /// @notice Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when REWARD TOKEN is granted by admin\\n event RewardTokenGranted(address indexed recipient, uint256 amount);\\n\\n /// @notice Emitted when a new REWARD TOKEN speed is set for a contributor\\n event ContributorRewardTokenSpeedUpdated(address indexed contributor, uint256 newSpeed);\\n\\n /// @notice Emitted when a market is initialized\\n event MarketInitialized(address indexed vToken);\\n\\n /// @notice Emitted when a reward token supply index is updated\\n event RewardTokenSupplyIndexUpdated(address indexed vToken);\\n\\n /// @notice Emitted when a reward token borrow index is updated\\n event RewardTokenBorrowIndexUpdated(address indexed vToken, Exp marketBorrowIndex);\\n\\n /// @notice Emitted when a reward for contributor is updated\\n event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued);\\n\\n /// @notice Emitted when a reward token last rewarding block for supply is updated\\n event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding block for borrow is updated\\n event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding timestamp for supply is updated\\n event SupplyLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\\n\\n /// @notice Emitted when a reward token last rewarding timestamp for borrow is updated\\n event BorrowLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\\n\\n modifier onlyComptroller() {\\n require(address(comptroller) == msg.sender, \\\"Only comptroller can call this function\\\");\\n _;\\n }\\n\\n /**\\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice RewardsDistributor initializer\\n * @dev Initializes the deployer to owner\\n * @param comptroller_ Comptroller to attach the reward distributor to\\n * @param rewardToken_ Reward token to distribute\\n * @param loopsLimit_ Maximum number of iterations for the loops in this contract\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(\\n Comptroller comptroller_,\\n IERC20Upgradeable rewardToken_,\\n uint256 loopsLimit_,\\n address accessControlManager_\\n ) external initializer {\\n comptroller = comptroller_;\\n rewardToken = rewardToken_;\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n\\n _setMaxLoopsLimit(loopsLimit_);\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken\\n * @param vToken The address of the vToken to be initialized\\n * @custom:event MarketInitialized emits on success\\n * @custom:access Only Comptroller\\n */\\n function initializeMarket(address vToken) external onlyComptroller {\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n isTimeBased\\n ? _initializeMarketTimestampBased(vToken, blockNumberOrTimestamp)\\n : _initializeMarketBlockBased(vToken, safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\"));\\n\\n emit MarketInitialized(vToken);\\n }\\n\\n /*** Reward Token Distribution ***/\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them\\n * Borrowers will begin to accrue after the first interaction with the protocol.\\n * @dev This function should only be called when the user has a borrow position in the market\\n * (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook)\\n * We avoid an external call to check if they are in the market to save gas because this function is called in many places\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function distributeBorrowerRewardToken(\\n address vToken,\\n address borrower,\\n Exp memory marketBorrowIndex\\n ) external onlyComptroller {\\n _distributeBorrowerRewardToken(vToken, borrower, marketBorrowIndex);\\n }\\n\\n function updateRewardTokenSupplyIndex(address vToken) external onlyComptroller {\\n _updateRewardTokenSupplyIndex(vToken);\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the recipient\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\\n * @param recipient The address of the recipient to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n */\\n function grantRewardToken(address recipient, uint256 amount) external onlyOwner {\\n uint256 amountLeft = _grantRewardToken(recipient, amount);\\n require(amountLeft == 0, \\\"insufficient rewardToken for grant\\\");\\n emit RewardTokenGranted(recipient, amount);\\n }\\n\\n function updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) external onlyComptroller {\\n _updateRewardTokenBorrowIndex(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN borrow and supply speeds for the specified markets\\n * @param vTokens The markets whose REWARD TOKEN speed to update\\n * @param supplySpeeds New supply-side REWARD TOKEN speed for the corresponding market\\n * @param borrowSpeeds New borrow-side REWARD TOKEN speed for the corresponding market\\n */\\n function setRewardTokenSpeeds(\\n VToken[] memory vTokens,\\n uint256[] memory supplySpeeds,\\n uint256[] memory borrowSpeeds\\n ) external {\\n _checkAccessAllowed(\\\"setRewardTokenSpeeds(address[],uint256[],uint256[])\\\");\\n uint256 numTokens = vTokens.length;\\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \\\"invalid setRewardTokenSpeeds\\\");\\n\\n for (uint256 i; i < numTokens; ++i) {\\n _setRewardTokenSpeed(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for the specified markets, used when contract is block based\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market\\n * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market\\n */\\n function setLastRewardingBlocks(\\n VToken[] calldata vTokens,\\n uint32[] calldata supplyLastRewardingBlocks,\\n uint32[] calldata borrowLastRewardingBlocks\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlocks(address[],uint32[],uint32[])\\\");\\n require(!isTimeBased, \\\"Block-based operation only\\\");\\n\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length,\\n \\\"RewardsDistributor::setLastRewardingBlocks invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlock(vTokens[i], supplyLastRewardingBlocks[i], borrowLastRewardingBlocks[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block timestamp for the specified markets, used when contract is time based\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlockTimestamps New supply-side REWARD TOKEN last rewarding block timestamp for the corresponding market\\n * @param borrowLastRewardingBlockTimestamps New borrow-side REWARD TOKEN last rewarding block timestamp for the corresponding market\\n */\\n function setLastRewardingBlockTimestamps(\\n VToken[] calldata vTokens,\\n uint256[] calldata supplyLastRewardingBlockTimestamps,\\n uint256[] calldata borrowLastRewardingBlockTimestamps\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlockTimestamps(address[],uint256[],uint256[])\\\");\\n require(isTimeBased, \\\"Time-based operation only\\\");\\n\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlockTimestamps.length &&\\n numTokens == borrowLastRewardingBlockTimestamps.length,\\n \\\"RewardsDistributor::setLastRewardingBlockTimestamps invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlockTimestamp(\\n vTokens[i],\\n supplyLastRewardingBlockTimestamps[i],\\n borrowLastRewardingBlockTimestamps[i]\\n );\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single contributor\\n * @param contributor The contributor whose REWARD TOKEN speed to update\\n * @param rewardTokenSpeed New REWARD TOKEN speed for contributor\\n */\\n function setContributorRewardTokenSpeed(address contributor, uint256 rewardTokenSpeed) external onlyOwner {\\n // note that REWARD TOKEN speed could be set to 0 to halt liquidity rewards for a contributor\\n updateContributorRewards(contributor);\\n if (rewardTokenSpeed == 0) {\\n // release storage\\n delete lastContributorBlock[contributor];\\n } else {\\n lastContributorBlock[contributor] = getBlockNumberOrTimestamp();\\n }\\n rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed;\\n\\n emit ContributorRewardTokenSpeedUpdated(contributor, rewardTokenSpeed);\\n }\\n\\n function distributeSupplierRewardToken(address vToken, address supplier) external onlyComptroller {\\n _distributeSupplierRewardToken(vToken, supplier);\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in all markets\\n * @param holder The address to claim REWARD TOKEN for\\n */\\n function claimRewardToken(address holder) external {\\n return claimRewardToken(holder, comptroller.getAllMarkets());\\n }\\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) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Calculate additional accrued REWARD TOKEN for a contributor since last accrual\\n * @param contributor The address to calculate contributor rewards for\\n */\\n function updateContributorRewards(address contributor) public {\\n uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, lastContributorBlock[contributor]);\\n if (deltaBlocksOrTimestamp > 0 && rewardTokenSpeed > 0) {\\n uint256 newAccrued = mul_(deltaBlocksOrTimestamp, rewardTokenSpeed);\\n uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued);\\n\\n rewardTokenAccrued[contributor] = contributorAccrued;\\n lastContributorBlock[contributor] = blockNumberOrTimestamp;\\n\\n emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]);\\n }\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in the specified markets\\n * @param holder The address to claim REWARD TOKEN for\\n * @param vTokens The list of markets to claim REWARD TOKEN in\\n */\\n function claimRewardToken(address holder, VToken[] memory vTokens) public {\\n uint256 vTokensCount = vTokens.length;\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n VToken vToken = vTokens[i];\\n require(comptroller.isMarketListed(vToken), \\\"market must be listed\\\");\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n _distributeBorrowerRewardToken(address(vToken), holder, borrowIndex);\\n _updateRewardTokenSupplyIndex(address(vToken));\\n _distributeSupplierRewardToken(address(vToken), holder);\\n }\\n rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for a single market.\\n * @param vToken market's whose reward token last rewarding block to be updated\\n * @param supplyLastRewardingBlock New supply-side REWARD TOKEN last rewarding block for market\\n * @param borrowLastRewardingBlock New borrow-side REWARD TOKEN last rewarding block for market\\n */\\n function _setLastRewardingBlock(\\n VToken vToken,\\n uint32 supplyLastRewardingBlock,\\n uint32 borrowLastRewardingBlock\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockNumber = getBlockNumberOrTimestamp();\\n\\n require(supplyLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n require(borrowLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n\\n uint32 currentSupplyLastRewardingBlock = rewardTokenSupplyState[address(vToken)].lastRewardingBlock;\\n uint32 currentBorrowLastRewardingBlock = rewardTokenBorrowState[address(vToken)].lastRewardingBlock;\\n\\n require(\\n currentSupplyLastRewardingBlock == 0 || currentSupplyLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlock == 0 || currentBorrowLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlock != supplyLastRewardingBlock) {\\n rewardTokenSupplyState[address(vToken)].lastRewardingBlock = supplyLastRewardingBlock;\\n emit SupplyLastRewardingBlockUpdated(address(vToken), supplyLastRewardingBlock);\\n }\\n\\n if (currentBorrowLastRewardingBlock != borrowLastRewardingBlock) {\\n rewardTokenBorrowState[address(vToken)].lastRewardingBlock = borrowLastRewardingBlock;\\n emit BorrowLastRewardingBlockUpdated(address(vToken), borrowLastRewardingBlock);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding timestamp for a single market.\\n * @param vToken market's whose reward token last rewarding timestamp to be updated\\n * @param supplyLastRewardingBlockTimestamp New supply-side REWARD TOKEN last rewarding timestamp for market\\n * @param borrowLastRewardingBlockTimestamp New borrow-side REWARD TOKEN last rewarding timestamp for market\\n */\\n function _setLastRewardingBlockTimestamp(\\n VToken vToken,\\n uint256 supplyLastRewardingBlockTimestamp,\\n uint256 borrowLastRewardingBlockTimestamp\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockTimestamp = getBlockNumberOrTimestamp();\\n\\n require(\\n supplyLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"setting last rewarding timestamp in the past is not allowed\\\"\\n );\\n require(\\n borrowLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"setting last rewarding timestamp in the past is not allowed\\\"\\n );\\n\\n uint256 currentSupplyLastRewardingBlockTimestamp = rewardTokenSupplyStateTimeBased[address(vToken)]\\n .lastRewardingTimestamp;\\n uint256 currentBorrowLastRewardingBlockTimestamp = rewardTokenBorrowStateTimeBased[address(vToken)]\\n .lastRewardingTimestamp;\\n\\n require(\\n currentSupplyLastRewardingBlockTimestamp == 0 || currentSupplyLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlockTimestamp == 0 || currentBorrowLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlockTimestamp != supplyLastRewardingBlockTimestamp) {\\n rewardTokenSupplyStateTimeBased[address(vToken)].lastRewardingTimestamp = supplyLastRewardingBlockTimestamp;\\n emit SupplyLastRewardingBlockTimestampUpdated(address(vToken), supplyLastRewardingBlockTimestamp);\\n }\\n\\n if (currentBorrowLastRewardingBlockTimestamp != borrowLastRewardingBlockTimestamp) {\\n rewardTokenBorrowStateTimeBased[address(vToken)].lastRewardingTimestamp = borrowLastRewardingBlockTimestamp;\\n emit BorrowLastRewardingBlockTimestampUpdated(address(vToken), borrowLastRewardingBlockTimestamp);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single market.\\n * @param vToken market's whose reward token rate to be updated\\n * @param supplySpeed New supply-side REWARD TOKEN speed for market\\n * @param borrowSpeed New borrow-side REWARD TOKEN speed for market\\n */\\n function _setRewardTokenSpeed(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n if (rewardTokenSupplySpeeds[address(vToken)] != supplySpeed) {\\n // Supply speed updated so let's update supply state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n _updateRewardTokenSupplyIndex(address(vToken));\\n\\n // Update speed and emit event\\n rewardTokenSupplySpeeds[address(vToken)] = supplySpeed;\\n emit RewardTokenSupplySpeedUpdated(vToken, supplySpeed);\\n }\\n\\n if (rewardTokenBorrowSpeeds[address(vToken)] != borrowSpeed) {\\n // Borrow speed updated so let's update borrow state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n\\n // Update speed and emit event\\n rewardTokenBorrowSpeeds[address(vToken)] = borrowSpeed;\\n emit RewardTokenBorrowSpeedUpdated(vToken, borrowSpeed);\\n }\\n }\\n\\n /**\\n * @notice Calculate REWARD TOKEN 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 REWARD TOKEN to\\n */\\n function _distributeSupplierRewardToken(address vToken, address supplier) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\\n\\n uint256 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\\n uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier];\\n\\n // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenSupplierIndex[vToken][supplier] = supplyIndex;\\n\\n if (supplierIndex == 0 && supplyIndex >= INITIAL_INDEX) {\\n // Covers the case where users supplied tokens before the market's supply state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when supplier rewards were first\\n // set for the market.\\n supplierIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per vToken accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\\n\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerVToken\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n\\n uint256 supplierAccrued = add_(rewardTokenAccrued[supplier], supplierDelta);\\n rewardTokenAccrued[supplier] = supplierAccrued;\\n\\n emit DistributedSupplierRewardToken(VToken(vToken), supplier, supplierDelta, supplierAccrued, supplyIndex);\\n }\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them.\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function _distributeBorrowerRewardToken(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\\n\\n uint256 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\\n uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower];\\n\\n // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenBorrowerIndex[vToken][borrower] = borrowIndex;\\n\\n if (borrowerIndex == 0 && borrowIndex >= INITIAL_INDEX) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when borrower rewards were first\\n // set for the market.\\n borrowerIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per borrowed unit accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\\n\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerBorrowedUnit\\n if (borrowerAmount != 0) {\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n\\n uint256 borrowerAccrued = add_(rewardTokenAccrued[borrower], borrowerDelta);\\n rewardTokenAccrued[borrower] = borrowerAccrued;\\n\\n emit DistributedBorrowerRewardToken(VToken(vToken), borrower, borrowerDelta, borrowerAccrued, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the user.\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all.\\n * @param user The address of the user to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n * @return The amount of REWARD TOKEN which was NOT transferred to the user\\n */\\n function _grantRewardToken(address user, uint256 amount) internal returns (uint256) {\\n uint256 rewardTokenRemaining = rewardToken.balanceOf(address(this));\\n if (amount > 0 && amount <= rewardTokenRemaining) {\\n rewardToken.safeTransfer(user, amount);\\n return 0;\\n }\\n return amount;\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the supply index\\n * @param vToken The market whose supply index to update\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenSupplyIndex(address vToken) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\\n\\n uint256 supplySpeed = rewardTokenSupplySpeeds[vToken];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (!isTimeBased) {\\n safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\");\\n }\\n\\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\\n ? supplyStateTimeBased.lastRewardingTimestamp\\n : uint256(supplyState.lastRewardingBlock);\\n\\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(\\n blockNumberOrTimestamp,\\n (isTimeBased ? supplyStateTimeBased.timestamp : uint256(supplyState.block))\\n );\\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, supplySpeed);\\n Double memory ratio = supplyTokens > 0\\n ? fraction(accruedSinceUpdate, supplyTokens)\\n : Double({ mantissa: 0 });\\n uint224 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\\n uint224 index = safe224(\\n add_(Double({ mantissa: supplyIndex }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n\\n if (isTimeBased) {\\n supplyStateTimeBased.index = index;\\n supplyStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n supplyState.index = index;\\n supplyState.block = uint32(blockNumberOrTimestamp);\\n }\\n } else if (deltaBlocksOrTimestamp > 0) {\\n isTimeBased ? supplyStateTimeBased.timestamp = blockNumberOrTimestamp : supplyState.block = uint32(\\n blockNumberOrTimestamp\\n );\\n }\\n\\n emit RewardTokenSupplyIndexUpdated(vToken);\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the borrow index\\n * @param vToken The market whose borrow index to update\\n * @param marketBorrowIndex The current global borrow index of vToken\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\\n\\n uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (!isTimeBased) {\\n safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\");\\n }\\n\\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\\n ? borrowStateTimeBased.lastRewardingTimestamp\\n : uint256(borrowState.lastRewardingBlock);\\n\\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(\\n blockNumberOrTimestamp,\\n (isTimeBased ? borrowStateTimeBased.timestamp : uint256(borrowState.block))\\n );\\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, borrowSpeed);\\n Double memory ratio = borrowAmount > 0\\n ? fraction(accruedSinceUpdate, borrowAmount)\\n : Double({ mantissa: 0 });\\n uint224 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\\n uint224 index = safe224(\\n add_(Double({ mantissa: borrowIndex }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n\\n if (isTimeBased) {\\n borrowStateTimeBased.index = index;\\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n borrowState.index = index;\\n borrowState.block = uint32(blockNumberOrTimestamp);\\n }\\n } else if (deltaBlocksOrTimestamp > 0) {\\n if (isTimeBased) {\\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n borrowState.block = uint32(blockNumberOrTimestamp);\\n }\\n }\\n\\n emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken called when contract is block-based\\n * @param vToken The address of the vToken to be initialized\\n * @param blockNumber current block number\\n */\\n function _initializeMarketBlockBased(address vToken, uint32 blockNumber) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n RewardToken storage borrowState = rewardTokenBorrowState[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 = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block numbers\\n */\\n supplyState.block = borrowState.block = blockNumber;\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken called when contract is time-based\\n * @param vToken The address of the vToken to be initialized\\n * @param blockTimestamp current block timestamp\\n */\\n function _initializeMarketTimestampBased(address vToken, uint256 blockTimestamp) internal {\\n TimeBasedRewardToken storage supplyState = rewardTokenSupplyStateTimeBased[vToken];\\n TimeBasedRewardToken storage borrowState = rewardTokenBorrowStateTimeBased[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 = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block timestamp\\n */\\n supplyState.timestamp = borrowState.timestamp = blockTimestamp;\\n }\\n}\\n\",\"keccak256\":\"0x3cc824e59c923cfe25c4f1a875959b7e9410cde8e73cd405de13f301298c697f\",\"license\":\"BSD-3-Clause\"},\"contracts/Rewards/RewardsDistributorStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\n\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\n\\n/**\\n * @title RewardsDistributorStorage\\n * @author Venus\\n * @dev Storage for RewardsDistributor\\n */\\ncontract RewardsDistributorStorage {\\n struct RewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number the index was last updated at\\n uint32 block;\\n // The block number at which to stop rewards\\n uint32 lastRewardingBlock;\\n }\\n\\n struct TimeBasedRewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block timestamp the index was last updated at\\n uint256 timestamp;\\n // The block timestamp at which to stop rewards\\n uint256 lastRewardingTimestamp;\\n }\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => RewardToken) public rewardTokenSupplyState;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex;\\n\\n /// @notice The REWARD TOKEN accrued but not yet transferred to each user\\n mapping(address => uint256) public rewardTokenAccrued;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding borrow market per slot (block or second)\\n mapping(address => uint256) public rewardTokenBorrowSpeeds;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding supply market per slot (block or second)\\n mapping(address => uint256) public rewardTokenSupplySpeeds;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => RewardToken) public rewardTokenBorrowState;\\n\\n /// @notice The portion of REWARD TOKEN that each contributor receives per slot (block or second)\\n mapping(address => uint256) public rewardTokenContributorSpeeds;\\n\\n /// @notice Last slot (block or second) at which a contributor's REWARD TOKEN rewards have been allocated\\n mapping(address => uint256) public lastContributorBlock;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex;\\n\\n Comptroller internal comptroller;\\n\\n IERC20Upgradeable public rewardToken;\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => TimeBasedRewardToken) public rewardTokenSupplyStateTimeBased;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => TimeBasedRewardToken) public rewardTokenBorrowStateTimeBased;\\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[37] private __gap;\\n}\\n\",\"keccak256\":\"0x70e5015a78a2acf95277949c8b4796e10b9ac194130be006d5e5217e158070c0\",\"license\":\"BSD-3-Clause\"},\"contracts/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\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 { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"@venusprotocol/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\\\";\\n\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { ComptrollerInterface, ComptrollerViewInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"./ErrorReporter.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title VToken\\n * @author Venus\\n * @notice Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview,\\n * each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of\\n * the pool. The main actions a user regularly interacts with in a market are:\\n\\n- mint/redeem of vTokens;\\n- transfer of vTokens;\\n- borrow/repay a loan on an underlying asset;\\n- liquidate a borrow or liquidate/heal an account.\\n\\n * A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`.\\n * The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted\\n * `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken`\\n * as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that\\n * a user may borrow up to a portion of their collateral determined by the market\\u2019s collateral factor. However, if their borrowed amount exceeds an amount\\n * calculated using the market\\u2019s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also\\n * pay off interest accrued on the borrow.\\n * \\n * The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller`\\n * and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a\\n * total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`.\\n * Both functions settle all of an account\\u2019s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of\\n * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\\n */\\ncontract VToken is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n VTokenInterface,\\n ExponentialNoError,\\n TokenErrorReporter,\\n TimeManagerV8\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5%\\n\\n // Maximum fraction of interest that can be set aside for reserves\\n uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18;\\n\\n // Maximum borrow rate that can ever be applied per slot(block or second)\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n uint256 internal immutable MAX_BORROW_RATE_MANTISSA;\\n\\n /**\\n * Reentrancy Guard **\\n */\\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 * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @param maxBorrowRateMantissa_ The maximum value of borrowing rate mantissa\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(\\n bool timeBased_,\\n uint256 blocksPerYear_,\\n uint256 maxBorrowRateMantissa_\\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n require(maxBorrowRateMantissa_ <= 1e18, \\\"Max borrow rate must be <= 1e18\\\");\\n\\n MAX_BORROW_RATE_MANTISSA = maxBorrowRateMantissa_;\\n _disableInitializers();\\n }\\n\\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_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n */\\n function initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) external initializer {\\n ensureNonzeroAddress(admin_);\\n\\n // Initialize the market\\n _initialize(\\n underlying_,\\n comptroller_,\\n interestRateModel_,\\n initialExchangeRateMantissa_,\\n name_,\\n symbol_,\\n decimals_,\\n admin_,\\n accessControlManager_,\\n riskManagement,\\n reserveFactorMantissa_\\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 * @return success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, msg.sender, dst, amount);\\n return true;\\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 success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, src, dst, amount);\\n return true;\\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 (uint256.max means infinite)\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Increase approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param addedValue The number of additional tokens spender can transfer\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function increaseAllowance(address spender, uint256 addedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 newAllowance = transferAllowances[src][spender];\\n newAllowance += addedValue;\\n transferAllowances[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n return true;\\n }\\n\\n /**\\n * @notice Decreases approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param subtractedValue The number of tokens to remove from total approval\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 currentAllowance = transferAllowances[src][spender];\\n require(currentAllowance >= subtractedValue, \\\"decreased allowance below zero\\\");\\n unchecked {\\n currentAllowance -= subtractedValue;\\n }\\n\\n transferAllowances[src][spender] = currentAllowance;\\n\\n emit Approval(src, spender, currentAllowance);\\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 amount The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint256) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return totalBorrows The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\\n accrueInterest();\\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 borrowBalance The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n return _borrowBalanceStored(account);\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function mint(uint256 mintAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _mintFresh(msg.sender, msg.sender, mintAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param minter User whom the supply will be attributed to\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when minter address is zero\\n */\\n function mintBehalf(address minter, uint256 mintAmount) external override nonReentrant returns (uint256) {\\n ensureNonzeroAddress(minter);\\n\\n accrueInterest();\\n\\n _mintFresh(msg.sender, minter, mintAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function redeem(uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _redeemFresh(msg.sender, msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function redeemBehalf(address redeemer, uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n _ensureSenderIsDelegateOf(redeemer);\\n\\n accrueInterest();\\n\\n _redeemFresh(redeemer, msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\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 receive from redeeming vTokens\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n */\\n function redeemUnderlying(uint256 redeemAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _redeemFresh(msg.sender, msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function redeemUnderlyingBehalf(\\n address redeemer,\\n uint256 redeemAmount\\n ) external override nonReentrant returns (uint256) {\\n _ensureSenderIsDelegateOf(redeemer);\\n\\n accrueInterest();\\n\\n _redeemFresh(redeemer, msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function borrow(uint256 borrowAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _borrowFresh(msg.sender, msg.sender, borrowAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error DelegateNotApproved is thrown if caller is not approved delegate\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function borrowBehalf(address borrower, uint256 borrowAmount) external override returns (uint256) {\\n _ensureSenderIsDelegateOf(borrower);\\n accrueInterest();\\n\\n _borrowFresh(borrower, msg.sender, borrowAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrow(uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n return NO_ERROR;\\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, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _repayBorrowFresh(msg.sender, borrower, repayAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Not restricted\\n */\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external override returns (uint256) {\\n _liquidateBorrow(msg.sender, borrower, repayAmount, vTokenCollateral, false);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice sets protocol share accumulated from liquidations\\n * @dev must be equal or less than liquidation incentive - 1\\n * @param newProtocolSeizeShareMantissa_ new protocol share mantissa\\n * @custom:event Emits NewProtocolSeizeShare event on success\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error ProtocolSeizeShareTooBig is thrown when the new seize share is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa_) external {\\n _checkAccessAllowed(\\\"setProtocolSeizeShare(uint256)\\\");\\n uint256 liquidationIncentive = ComptrollerViewInterface(address(comptroller)).liquidationIncentiveMantissa();\\n if (newProtocolSeizeShareMantissa_ + MANTISSA_ONE > liquidationIncentive) {\\n revert ProtocolSeizeShareTooBig();\\n }\\n\\n uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\\n protocolSeizeShareMantissa = newProtocolSeizeShareMantissa_;\\n emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa_);\\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 * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n * @custom:event Emits NewReserveFactor event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant {\\n _checkAccessAllowed(\\\"setReserveFactor(uint256)\\\");\\n\\n accrueInterest();\\n _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to the protocol reserve contract\\n * @dev Gracefully return if reserves already reduced in accrueInterest\\n * @param reduceAmount Amount of reduction to reserves\\n * @custom:event Emits ReservesReduced event; may emit AccrueInterest\\n * @custom:error ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash\\n * @custom:error ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\\n * @custom:access Not restricted\\n */\\n function reduceReserves(uint256 reduceAmount) external override nonReentrant {\\n accrueInterest();\\n if (reduceReservesBlockNumber == getBlockNumberOrTimestamp()) return;\\n _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice The sender adds to reserves.\\n * @param addAmount The amount of underlying token to add as reserves\\n * @custom:event Emits ReservesAdded event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function addReserves(uint256 addAmount) external override nonReentrant {\\n accrueInterest();\\n _addReservesFresh(addAmount);\\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 * @custom:event Emits NewMarketInterestRateModel event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external override {\\n _checkAccessAllowed(\\\"setInterestRateModel(address)\\\");\\n\\n accrueInterest();\\n _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially\\n * \\\"forgiving\\\" the borrower. Healing is a situation that should rarely happen. However, some pools\\n * may list risky assets or be configured improperly \\u2013 we want to still handle such cases gracefully.\\n * We assume that Comptroller does the seizing, so this function is only available to Comptroller.\\n * @dev This function does not call any Comptroller hooks (like \\\"healAllowed\\\"), because we assume\\n * the Comptroller does all the necessary checks before calling this function.\\n * @param payer account who repays the debt\\n * @param borrower account to heal\\n * @param repayAmount amount to repay\\n * @custom:event Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\\n * @custom:error HealBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:access Only Comptroller\\n */\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external override nonReentrant {\\n if (repayAmount != 0) {\\n comptroller.preRepayHook(address(this), borrower);\\n }\\n\\n if (msg.sender != address(comptroller)) {\\n revert HealBorrowUnauthorized();\\n }\\n\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 totalBorrowsNew = totalBorrows;\\n\\n uint256 actualRepayAmount;\\n if (repayAmount != 0) {\\n // _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // We violate checks-effects-interactions here to account for tokens that take transfer fees\\n actualRepayAmount = _doTransferIn(payer, repayAmount);\\n totalBorrowsNew = totalBorrowsNew - actualRepayAmount;\\n emit RepayBorrow(\\n payer,\\n borrower,\\n actualRepayAmount,\\n accountBorrowsPrev - actualRepayAmount,\\n totalBorrowsNew\\n );\\n }\\n\\n // The transaction will fail if trying to repay too much\\n uint256 badDebtDelta = accountBorrowsPrev - actualRepayAmount;\\n if (badDebtDelta != 0) {\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld + badDebtDelta;\\n totalBorrowsNew = totalBorrowsNew - badDebtDelta;\\n badDebt = badDebtNew;\\n\\n // We treat healing as \\\"repayment\\\", where vToken is the payer\\n emit RepayBorrow(address(this), borrower, badDebtDelta, 0, totalBorrowsNew);\\n emit BadDebtIncreased(borrower, badDebtDelta, badDebtOld, badDebtNew);\\n }\\n\\n accountBorrows[borrower].principal = 0;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n emit HealBorrow(payer, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice The extended version of liquidations, callable only by Comptroller. May skip\\n * the close factor check. The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Only Comptroller\\n */\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) external override {\\n if (msg.sender != address(comptroller)) {\\n revert ForceLiquidateBorrowUnauthorized();\\n }\\n _liquidateBorrow(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\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 * @custom:event Emits Transfer, ReservesAdded events\\n * @custom:error LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:access Not restricted\\n */\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external override nonReentrant {\\n _seize(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Updates bad debt\\n * @dev Called only when bad debt is recovered from auction. Updates internal cash balance.\\n * @param recoveredAmount_ The amount of bad debt recovered\\n * @custom:event Emits BadDebtRecovered event\\n * @custom:access Only Shortfall contract\\n */\\n function badDebtRecovered(uint256 recoveredAmount_) external {\\n require(msg.sender == shortfall, \\\"only shortfall contract can update bad debt\\\");\\n require(recoveredAmount_ <= badDebt, \\\"more than bad debt recovered from auction\\\");\\n\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld - recoveredAmount_;\\n badDebt = badDebtNew;\\n internalCash += recoveredAmount_;\\n\\n emit BadDebtRecovered(badDebtOld, badDebtNew);\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protocolShareReserve_ The address of the protocol share reserve contract\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n * @custom:access Only Governance\\n */\\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\\n _setProtocolShareReserve(protocolShareReserve_);\\n }\\n\\n /**\\n * @notice Sets shortfall contract address\\n * @param shortfall_ The address of the shortfall contract\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:access Only Governance\\n */\\n function setShortfallContract(address shortfall_) external onlyOwner {\\n _setShortfallContract(shortfall_);\\n }\\n\\n /**\\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\\n * @param token The address of the ERC-20 token to sweep\\n * @custom:access Only Governance\\n */\\n function sweepToken(IERC20Upgradeable token) external override {\\n require(msg.sender == owner(), \\\"VToken::sweepToken: only admin can sweep tokens\\\");\\n require(address(token) != underlying, \\\"VToken::sweepToken: can not sweep underlying token\\\");\\n uint256 balance = token.balanceOf(address(this));\\n token.safeTransfer(owner(), balance);\\n\\n emit SweepToken(address(token));\\n }\\n\\n /**\\n * @notice Sync internalCash with the actual underlying token balance\\n * @dev Used for one-time migration after upgrade to initialize internalCash\\n * @custom:event Emits CashSynced\\n * @custom:access Controlled by AccessControlManager\\n */\\n function syncCash() external override nonReentrant {\\n _checkAccessAllowed(\\\"syncCash()\\\");\\n uint256 oldInternalCash = internalCash;\\n uint256 actualCash = IERC20Upgradeable(underlying).balanceOf(address(this));\\n internalCash = actualCash;\\n emit CashSynced(oldInternalCash, actualCash);\\n }\\n\\n /**\\n * @notice A public function to set new threshold of slot(block or second) difference after which funds will be sent to the protocol share reserve\\n * @param _newReduceReservesBlockOrTimestampDelta slot(block or second) difference value\\n * @custom:access Only Governance\\n */\\n function setReduceReservesBlockDelta(uint256 _newReduceReservesBlockOrTimestampDelta) external {\\n _checkAccessAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n require(_newReduceReservesBlockOrTimestampDelta > 0, \\\"Invalid Input\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, _newReduceReservesBlockOrTimestampDelta);\\n reduceReservesBlockDelta = _newReduceReservesBlockOrTimestampDelta;\\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 amount 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 amount 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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return vTokenBalance User's balance of vTokens\\n * @return borrowBalance Amount owed in terms of underlying\\n * @return exchangeRate Stored exchange rate\\n */\\n function getAccountSnapshot(\\n address account\\n )\\n external\\n view\\n override\\n returns (uint256 error, uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRate)\\n {\\n return (NO_ERROR, accountTokens[account], _borrowBalanceStored(account), _exchangeRateStored());\\n }\\n\\n /**\\n * @notice Get the internally tracked cash balance of this vToken in the underlying asset\\n * @return cash The quantity of underlying asset tracked internally by this contract\\n */\\n function getCash() external view override returns (uint256) {\\n return _getCashPrior();\\n }\\n\\n /**\\n * @notice Returns the current per slot(block or second) borrow interest rate for this vToken\\n * @return rate The borrow interest rate per slot(block or second), scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint256) {\\n return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt);\\n }\\n\\n /**\\n * @notice Returns the current per-slot(block or second) supply interest rate for this v\\n * @return rate The supply interest rate per slot(block or second), scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint256) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPrior(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa,\\n badDebt\\n );\\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 borrowBalance The calculated balance\\n */\\n function borrowBalanceStored(address account) external view override returns (uint256) {\\n return _borrowBalanceStored(account);\\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 exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() external view override returns (uint256) {\\n return _exchangeRateStored();\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\\n accrueInterest();\\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 slot(block or second)\\n * up to the current slot(block or second) and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentSlot - reduceReservesBlockNumber >= slotDelta\\n * @return Always NO_ERROR\\n * @custom:event Emits AccrueInterest event on success\\n * @custom:access Not restricted\\n */\\n function accrueInterest() public virtual override returns (uint256) {\\n /* Remember the initial block number or timestamp */\\n uint256 currentSlotNumber = getBlockNumberOrTimestamp();\\n uint256 accrualSlotNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualSlotNumberPrior == currentSlotNumber) {\\n return NO_ERROR;\\n }\\n\\n /* Read the previous values out of storage */\\n uint256 cashPrior = _getCashPrior();\\n uint256 borrowsPrior = totalBorrows;\\n uint256 reservesPrior = totalReserves;\\n uint256 borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt);\\n require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of slots elapsed since the last accrual */\\n uint256 slotDelta = currentSlotNumber - accrualSlotNumberPrior;\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * slotDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), slotDelta);\\n uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\\n uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;\\n uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentSlotNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n if (currentSlotNumber - reduceReservesBlockNumber >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentSlotNumber;\\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 NO_ERROR;\\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 or timestamp\\n * @param payer The address of the account which is sending the assets for supply\\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 */\\n function _mintFresh(address payer, address minter, uint256 mintAmount) internal {\\n /* Fail if mint not allowed */\\n comptroller.preMintHook(address(this), minter, mintAmount);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert MintFreshnessCheck();\\n }\\n\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\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 * `_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 uint256 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 uint256 mintTokens = div_(actualMintAmount, exchangeRate);\\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 * And write them into storage\\n */\\n totalSupply = totalSupply + mintTokens;\\n uint256 balanceAfter = accountTokens[minter] + mintTokens;\\n accountTokens[minter] = balanceAfter;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, actualMintAmount, mintTokens, balanceAfter);\\n emit Transfer(address(0), minter, mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, actualMintAmount, mintTokens);\\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 Comptroller.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current slot(block or second)\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the underlying 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 */\\n function _redeemFresh(address redeemer, address receiver, uint256 redeemTokensIn, uint256 redeemAmountIn) internal {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert RedeemFreshnessCheck();\\n }\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n\\n uint256 redeemTokens;\\n uint256 redeemAmount;\\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 */\\n redeemTokens = redeemTokensIn;\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n */\\n redeemTokens = div_(redeemAmountIn, exchangeRate);\\n\\n uint256 _redeemAmount = mul_(redeemTokens, exchangeRate);\\n if (_redeemAmount != 0 && _redeemAmount != redeemAmountIn) redeemTokens++; // round up\\n }\\n\\n // redeemAmount = exchangeRate * redeemTokens\\n redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokens);\\n\\n // Revert if amount is zero\\n if (redeemAmount == 0) {\\n revert(\\\"redeemAmount is zero\\\");\\n }\\n\\n /* Fail if redeem not allowed */\\n comptroller.preRedeemHook(address(this), redeemer, redeemTokens);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (_getCashPrior() - totalReserves < redeemAmount) {\\n revert RedeemTransferOutNotPossible();\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\\n */\\n totalSupply = totalSupply - redeemTokens;\\n uint256 balanceAfter = accountTokens[redeemer] - redeemTokens;\\n accountTokens[redeemer] = balanceAfter;\\n\\n /*\\n * We invoke _doTransferOut for the receiver and the redeemAmount.\\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 _doTransferOut(receiver, redeemAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), redeemTokens);\\n emit Redeem(redeemer, redeemAmount, redeemTokens, balanceAfter);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, redeemAmount, redeemTokens);\\n }\\n\\n /**\\n * @notice Users or their delegates borrow assets from the protocol\\n * @param borrower User who borrows the assets\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param borrowAmount The amount of the underlying asset to borrow\\n */\\n function _borrowFresh(address borrower, address receiver, uint256 borrowAmount) internal {\\n /* Fail if borrow not allowed */\\n comptroller.preBorrowHook(address(this), borrower, borrowAmount);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert BorrowFreshnessCheck();\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (_getCashPrior() - totalReserves < borrowAmount) {\\n revert BorrowCashNotAvailable();\\n }\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowNew = accountBorrow + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;\\n uint256 totalBorrowsNew = totalBorrows + borrowAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\\n `*/\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /*\\n * We invoke _doTransferOut for the receiver and the borrowAmount.\\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, accountBorrowsNew, totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\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 underlying tokens being returned, or type(uint256).max for the full outstanding amount\\n * @return (uint) the actual repayment amount.\\n */\\n function _repayBorrowFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256) {\\n /* Fail if repayBorrow not allowed */\\n comptroller.preRepayHook(address(this), borrower);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert RepayBorrowFreshnessCheck();\\n }\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n\\n uint256 repayAmountFinal = repayAmount >= accountBorrowsPrev ? accountBorrowsPrev : 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 * 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 uint256 actualRepayAmount = _doTransferIn(payer, repayAmountFinal);\\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 uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\\n uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, actualRepayAmount, borrowIndex);\\n\\n return actualRepayAmount;\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal nonReentrant {\\n accrueInterest();\\n\\n uint256 error = vTokenCollateral.accrueInterest();\\n if (error != NO_ERROR) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n revert LiquidateAccrueCollateralInterestFailed(error);\\n }\\n\\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal {\\n /* Fail if liquidate not allowed */\\n comptroller.preLiquidateHook(\\n address(this),\\n address(vTokenCollateral),\\n borrower,\\n repayAmount,\\n skipLiquidityCheck\\n );\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert LiquidateFreshnessCheck();\\n }\\n\\n /* Verify vTokenCollateral market's slot(block or second) number equals current slot(block or second) number */\\n if (vTokenCollateral.accrualBlockNumber() != getBlockNumberOrTimestamp()) {\\n revert LiquidateCollateralFreshnessCheck();\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateLiquidatorIsBorrower();\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n revert LiquidateCloseAmountIsZero();\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n revert LiquidateCloseAmountIsUintMax();\\n }\\n\\n /* Fail if repayBorrow fails */\\n uint256 actualRepayAmount = _repayBorrowFresh(liquidator, borrower, repayAmount);\\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.liquidateCalculateSeizeTokens(\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n require(amountSeizeError == 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, call _seize internally to avoid re-entrancy, otherwise make an external call\\n if (address(vTokenCollateral) == address(this)) {\\n _seize(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\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\\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 * It's absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerContract The contract seizing the collateral (either borrowed vToken or Comptroller)\\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 */\\n function _seize(address seizerContract, address liquidator, address borrower, uint256 seizeTokens) internal {\\n /* Fail if seize not allowed */\\n comptroller.preSeizeHook(address(this), seizerContract, liquidator, borrower);\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateSeizeLiquidatorIsBorrower();\\n }\\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 uint256 liquidationIncentiveMantissa = ComptrollerViewInterface(address(comptroller))\\n .liquidationIncentiveMantissa();\\n uint256 numerator = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));\\n uint256 protocolSeizeTokens = div_(numerator, Exp({ mantissa: liquidationIncentiveMantissa }));\\n uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n uint256 protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the calculated values into storage */\\n totalSupply = totalSupply - protocolSeizeTokens;\\n accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\\n accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\\n\\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, protocolSeizeAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.LIQUIDATION\\n );\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\\n emit ProtocolSeize(borrower, protocolShareReserve, protocolSeizeAmount);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerContract, liquidator, borrower, seizeTokens);\\n }\\n\\n function _setComptroller(ComptrollerInterface newComptroller) internal {\\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\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n */\\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal {\\n // Verify market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert SetReserveFactorFreshCheck();\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > MAX_RESERVE_FACTOR_MANTISSA) {\\n revert SetReserveFactorBoundsCheck();\\n }\\n\\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\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 actualAddAmount The actual amount added, excluding the potential token fees\\n */\\n function _addReservesFresh(uint256 addAmount) internal returns (uint256) {\\n // totalReserves + actualAddAmount\\n uint256 totalReservesNew;\\n uint256 actualAddAmount;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert AddReservesFactorFreshCheck(actualAddAmount);\\n }\\n\\n actualAddAmount = _doTransferIn(msg.sender, addAmount);\\n totalReservesNew = totalReserves + actualAddAmount;\\n totalReserves = totalReservesNew;\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n return actualAddAmount;\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to the protocol reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n */\\n function _reduceReservesFresh(uint256 reduceAmount) internal {\\n if (reduceAmount == 0) {\\n return;\\n }\\n // totalReserves - reduceAmount\\n uint256 totalReservesNew;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert ReduceReservesFreshCheck();\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (_getCashPrior() < reduceAmount) {\\n revert ReduceReservesCashNotAvailable();\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n revert ReduceReservesCashValidation();\\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 // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, reduceAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit SpreadReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal {\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert SetInterestRateModelFreshCheck();\\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\\n /**\\n * Safe Token **\\n */\\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 returns (uint256) {\\n IERC20Upgradeable token = IERC20Upgradeable(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 * @param to Receiver of the underlying tokens\\n * @param amount Amount of underlying to transfer\\n */\\n function _doTransferOut(address to, uint256 amount) internal virtual {\\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\\n internalCash -= amount;\\n token.safeTransfer(to, amount);\\n }\\n\\n /**\\n * @notice Transfer `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 */\\n function _transferTokens(address spender, address src, address dst, uint256 tokens) internal {\\n /* Fail if transfer not allowed */\\n comptroller.preTransferHook(address(this), src, dst, tokens);\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n revert TransferNotAllowed();\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint256 startingAllowance;\\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 uint256 allowanceNew = startingAllowance - tokens;\\n uint256 srcTokensNew = accountTokens[src] - tokens;\\n uint256 dstTokensNew = accountTokens[dst] + tokens;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n\\n accountTokens[src] = srcTokensNew;\\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\\n /**\\n * @notice Initialize the 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_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n */\\n function _initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\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 _setComptroller(comptroller_);\\n\\n // Initialize slot(block or second) number and borrow index (slot(block or second) number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumberOrTimestamp();\\n borrowIndex = MANTISSA_ONE;\\n\\n // Set the interest rate model (depends on slot(block or second) number / borrow index)\\n _setInterestRateModelFresh(interestRateModel_);\\n\\n _setReserveFactorFresh(reserveFactorMantissa_);\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n _setShortfallContract(riskManagement.shortfall);\\n _setProtocolShareReserve(riskManagement.protocolShareReserve);\\n protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA;\\n\\n // Set underlying and sanity check it\\n underlying = underlying_;\\n IERC20Upgradeable(underlying).totalSupply();\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n _transferOwnership(admin_);\\n }\\n\\n function _setShortfallContract(address shortfall_) internal {\\n ensureNonzeroAddress(shortfall_);\\n address oldShortfall = shortfall;\\n shortfall = shortfall_;\\n emit NewShortfallContract(oldShortfall, shortfall_);\\n }\\n\\n function _setProtocolShareReserve(address payable protocolShareReserve_) internal {\\n ensureNonzeroAddress(protocolShareReserve_);\\n address oldProtocolShareReserve = address(protocolShareReserve);\\n protocolShareReserve = protocolShareReserve_;\\n emit NewProtocolShareReserve(oldProtocolShareReserve, address(protocolShareReserve_));\\n }\\n\\n function _ensureSenderIsDelegateOf(address user) internal view {\\n if (!ComptrollerViewInterface(address(comptroller)).approvedDelegates(user, msg.sender)) {\\n revert DelegateNotApproved();\\n }\\n }\\n\\n /**\\n * @notice Gets the internally tracked cash balance of this market\\n * @dev Returns the internalCash state variable, which is updated on transfers in/out\\n * @return The quantity of underlying tokens tracked internally by this contract\\n */\\n function _getCashPrior() internal view virtual returns (uint256) {\\n return internalCash;\\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 borrowBalance the calculated balance\\n */\\n function _borrowBalanceStored(address account) internal view returns (uint256) {\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot memory 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 0;\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;\\n\\n return principalTimesIndex / borrowSnapshot.interestIndex;\\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 exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function _exchangeRateStored() internal view virtual returns (uint256) {\\n uint256 _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return initialExchangeRateMantissa;\\n }\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply\\n */\\n uint256 totalCash = _getCashPrior();\\n uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;\\n uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply;\\n\\n return exchangeRate;\\n }\\n}\\n\",\"keccak256\":\"0x7267f5337062ad01a5011f7725a86cc2ad0351cca0aaceadc167341f168cdef2\",\"license\":\"BSD-3-Clause\"},\"contracts/VTokenInterfaces.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\\nimport { ComptrollerInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title VTokenStorage\\n * @author Venus\\n * @notice Storage layout used by the `VToken` contract\\n */\\n// solhint-disable-next-line max-states-count\\ncontract VTokenStorage {\\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 uint256 principal;\\n uint256 interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\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 Protocol share Reserve contract address\\n */\\n address payable public protocolShareReserve;\\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 InterestRateModel public interestRateModel;\\n\\n // Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n uint256 internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint256 public reserveFactorMantissa;\\n\\n /**\\n * @notice Slot(block or second) number that interest was last accrued at\\n */\\n uint256 public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint256 public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint256 public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint256 public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint256 public totalSupply;\\n\\n /**\\n * @notice Total bad debt of the market\\n */\\n uint256 public badDebt;\\n\\n // Official record of token balances for each account\\n mapping(address => uint256) internal accountTokens;\\n\\n // Approved token transfer amounts on behalf of others\\n mapping(address => mapping(address => uint256)) internal transferAllowances;\\n\\n // Mapping of account addresses to outstanding borrow balances\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint256 public protocolSeizeShareMantissa;\\n\\n /**\\n * @notice Storage of Shortfall contract address\\n */\\n address public shortfall;\\n\\n /**\\n * @notice delta slot (block or second) after which reserves will be reduced\\n */\\n uint256 public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last slot (block or second) number at which reserves were reduced\\n */\\n uint256 public reduceReservesBlockNumber;\\n\\n /**\\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\\n * @dev Updated via _doTransferIn(), _doTransferOut(), syncCash(), and badDebtRecovered(). Must be initialized via syncCash() 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[47] private __gap;\\n}\\n\\n/**\\n * @title VTokenInterface\\n * @author Venus\\n * @notice Interface implemented by the `VToken` contract\\n */\\nabstract contract VTokenInterface is VTokenStorage {\\n struct RiskManagementInit {\\n address shortfall;\\n address payable protocolShareReserve;\\n }\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address indexed minter, uint256 mintAmount, uint256 mintTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address indexed borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(\\n address indexed payer,\\n address indexed borrower,\\n uint256 repayAmount,\\n uint256 accountBorrows,\\n uint256 totalBorrows\\n );\\n\\n /**\\n * @notice Event emitted when bad debt is accumulated on a market\\n * @param borrower borrower to \\\"forgive\\\"\\n * @param badDebtDelta amount of new bad debt recorded\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtIncreased(address indexed borrower, uint256 badDebtDelta, uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when bad debt is recovered via an auction\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtRecovered(uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address indexed liquidator,\\n address indexed borrower,\\n uint256 repayAmount,\\n address indexed vTokenCollateral,\\n uint256 seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface indexed oldComptroller, ComptrollerInterface indexed newComptroller);\\n\\n /**\\n * @notice Event emitted when shortfall contract address is changed\\n */\\n event NewShortfallContract(address indexed oldShortfall, address indexed newShortfall);\\n\\n /**\\n * @notice Event emitted when protocol share reserve contract address is changed\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModel indexed oldInterestRateModel,\\n InterestRateModel indexed newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when protocol seize share is changed\\n */\\n event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address indexed benefactor, uint256 addAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the spread reserves are reduced\\n */\\n event SpreadReservesReduced(address indexed protocolShareReserve, uint256 reduceAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /**\\n * @notice Event emitted when healing the borrow\\n */\\n event HealBorrow(address indexed payer, address indexed borrower, uint256 repayAmount);\\n\\n /**\\n * @notice Event emitted when tokens are swept\\n */\\n event SweepToken(address indexed token);\\n\\n /**\\n * @notice Event emitted when reduce reserves slot (block or second) delta is changed\\n */\\n event NewReduceReservesBlockDelta(\\n uint256 oldReduceReservesBlockOrTimestampDelta,\\n uint256 newReduceReservesBlockOrTimestampDelta\\n );\\n\\n /**\\n * @notice Event emitted when liquidation reserves are reduced\\n */\\n event ProtocolSeize(address indexed from, address indexed to, uint256 amount);\\n\\n /**\\n * @notice Event emitted when internalCash is synced with actual token balance\\n */\\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\\n\\n /*** User Interface ***/\\n\\n function mint(uint256 mintAmount) external virtual returns (uint256);\\n\\n function mintBehalf(address minter, uint256 mintAllowed) external virtual returns (uint256);\\n\\n function redeem(uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemBehalf(address redeemer, uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);\\n\\n function redeemUnderlyingBehalf(address redeemer, uint256 redeemAmount) external virtual returns (uint256);\\n\\n function borrow(uint256 borrowAmount) external virtual returns (uint256);\\n\\n function borrowBehalf(address borrwwer, uint256 borrowAmount) external virtual returns (uint256);\\n\\n function repayBorrow(uint256 repayAmount) external virtual returns (uint256);\\n\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external virtual returns (uint256);\\n\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external virtual;\\n\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipCloseFactorCheck\\n ) external virtual;\\n\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external virtual;\\n\\n function transfer(address dst, uint256 amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint256 amount) external virtual returns (bool);\\n\\n function accrueInterest() external virtual returns (uint256);\\n\\n function sweepToken(IERC20Upgradeable token) external virtual;\\n\\n /*** Admin Functions ***/\\n\\n function setReserveFactor(uint256 newReserveFactorMantissa) external virtual;\\n\\n function reduceReserves(uint256 reduceAmount) external virtual;\\n\\n function exchangeRateCurrent() external virtual returns (uint256);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint256);\\n\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external virtual;\\n\\n function addReserves(uint256 addAmount) external virtual;\\n\\n function syncCash() external virtual;\\n\\n function totalBorrowsCurrent() external virtual returns (uint256);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint256);\\n\\n function approve(address spender, uint256 amount) external virtual returns (bool);\\n\\n function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool);\\n\\n function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint256);\\n\\n function balanceOf(address owner) external view virtual returns (uint256);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint256, uint256, uint256, uint256);\\n\\n function borrowRatePerBlock() external view virtual returns (uint256);\\n\\n function supplyRatePerBlock() external view virtual returns (uint256);\\n\\n function borrowBalanceStored(address account) external view virtual returns (uint256);\\n\\n function exchangeRateStored() external view virtual returns (uint256);\\n\\n function getCash() external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is a VToken contract (for inspection)\\n * @return Always true\\n */\\n function isVToken() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x155684e9cb12cdd8be63d2314c9452b68ee44ff98a00e0d65cd1fd7d0bdd4391\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\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\",\"keccak256\":\"0x54ab3a6f3bc87569ed12370f3470a1ec84cea9796d4d0ccf3d07dd4280c044aa\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/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 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\",\"keccak256\":\"0x93bdd5cfb100f0f9a1d446857e23c3633df6ab12c266333c978428edd96b1367\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x61010060405234801561001157600080fd5b50604051614176380380614176833981016040819052610030916100e9565b82828115801561003e575080155b1561005c576040516302723dfb60e21b815260040160405180910390fd5b81801561006857508015155b156100865760405163ae0fcab360e01b815260040160405180910390fd5b81151560a05281610097578061009d565b6301e133805b608052816100b4576100e160201b611d0c176100bf565b6100e560201b611d10175b6001600160401b031660c05250506001600160a01b031660e0525061013d9050565b4390565b4290565b6000806000606084860312156100fe57600080fd5b8351801515811461010e57600080fd5b6020850151604086015191945092506001600160a01b038116811461013257600080fd5b809150509250925092565b60805160a05160c05160e051613ff2610184600039600081816102e80152611d8201526000611ce00152600081816102b10152611f80015260006101dc0152613ff26000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c80637c51b642116100a2578063c7ad089511610071578063c7ad0895146102ac578063d26998e9146102e3578063d77ebf961461030a578063e0a67f111461032a578063e1d146fb1461034a57600080fd5b80637c51b6421461022c5780637c84e3b31461024c578063aa5dbd231461026c578063b31242391461028c57600080fd5b806347d86a81116100de57806347d86a811461019957806355dd9515146101ac5780636857249c146101d75780637a27db571461020c57600080fd5b80630d3ae318146101105780631f884fdf14610139578063345954dc146101595780633e3e399c14610179575b600080fd5b61012361011e366004612ff0565b610352565b604051610130919061335d565b60405180910390f35b61014c6101473660046133bb565b610626565b60405161013091906133fc565b61016c61016736600461345c565b6106ee565b6040516101309190613479565b61018c61018736600461345c565b610821565b60405161013091906134dd565b6101236101a7366004613567565b610b30565b6101bf6101ba3660046135a0565b610bb7565b6040516001600160a01b039091168152602001610130565b6101fe7f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610130565b61021f61021a366004613567565b610c37565b60405161013091906135eb565b61023f61023a3660046136c7565b610ee7565b6040516101309190613752565b61025f61025a36600461345c565b610fa0565b60405161013091906137a0565b61027f61027a36600461345c565b61110a565b60405161013091906137c0565b61029f61029a366004613567565b6118ca565b60405161013091906137cf565b6102d37f000000000000000000000000000000000000000000000000000000000000000081565b6040519015158152602001610130565b6101bf7f000000000000000000000000000000000000000000000000000000000000000081565b61031d610318366004613567565b611bb1565b60405161013091906137dd565b61033d610338366004613841565b611c24565b60405161013091906138da565b6101fe611cd9565b61035a612db7565b6040820151600061036a82611d14565b9050600061037782611c24565b60408681015190516328ebbe8b60e21b81526001600160a01b039182166004820152919250879160009183169063a3aefa2c90602401600060405180830381865afa1580156103ca573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526103f29190810190613962565b90506000876040015190506000604051806101a001604052808a6000015181526020018a602001516001600160a01b031681526020018a604001516001600160a01b031681526020018a6060015181526020018a608001518152602001846000015181526020018460200151815260200184604001518152602001836001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104cf9190613a16565b6001600160a01b03168152602001836001600160a01b031663e87554466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561051b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053f9190613a33565b8152602001836001600160a01b0316634ada90af6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610582573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105a69190613a33565b8152602001836001600160a01b031663db5c65de6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060d9190613a33565b8152602001959095525092955050505050505b92915050565b6060816000816001600160401b0381111561064357610643612f39565b60405190808252806020026020018201604052801561068857816020015b60408051808201909152600080825260208201528152602001906001900390816106615790505b50905060005b828110156106e5576106c08686838181106106ab576106ab613a4c565b905060200201602081019061025a919061345c565b8282815181106106d2576106d2613a4c565b602090810291909101015260010161068e565b50949350505050565b606060008290506000816001600160a01b031663d88ff1f46040518163ffffffff1660e01b8152600401600060405180830381865afa158015610735573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261075d9190810190613ae5565b80519091506000816001600160401b0381111561077c5761077c612f39565b6040519080825280602002602001820160405280156107b557816020015b6107a2612db7565b81526020019060019003908161079a5790505b50905060005b828110156108175760008482815181106107d7576107d7613a4c565b6020026020010151905060006107ed8983610352565b90508084848151811061080257610802613a4c565b602090810291909101015250506001016107bb565b5095945050505050565b60408051606080820183526000808352602083018190529282015290828161084882611d14565b90506000826001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561088a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ae9190613a16565b9050600082516001600160401b038111156108cb576108cb612f39565b60405190808252806020026020018201604052801561091057816020015b60408051808201909152600080825260208201528152602001906001900390816108e95790505b509050610940604051806060016040528060006001600160a01b0316815260200160008152602001606081525090565b6001600160a01b03881681526040810182905260005b8451811015610b1c57604080518082019091526000808252602082015285828151811061098557610985613a4c565b602002602001015181600001906001600160a01b031690816001600160a01b031681525050670de0b6b3a7640000856001600160a01b031663fc57d4df8885815181106109d4576109d4613a4c565b60200260200101516040518263ffffffff1660e01b8152600401610a0791906001600160a01b0391909116815260200190565b602060405180830381865afa158015610a24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a489190613a33565b878481518110610a5a57610a5a613a4c565b60200260200101516001600160a01b031663bbcac5576040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac39190613a33565b610acd9190613bab565b610ad79190613bc2565b60208201526040830151805182919084908110610af657610af6613a4c565b6020026020010181905250806020015188610b119190613be4565b975050600101610956565b506020810195909552509295945050505050565b610b38612db7565b604051637aee632d60e01b81526001600160a01b0383811660048301528491610baf91839190821690637aee632d90602401600060405180830381865afa158015610b87573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261011e9190810190613bf7565b949350505050565b60405163266e0a7f60e01b81526001600160a01b0383811660048301528281166024830152600091859182169063266e0a7f90604401602060405180830381865afa158015610c0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2e9190613a16565b95945050505050565b60606000610c4483611d14565b90506000836001600160a01b03166361252fd16040518163ffffffff1660e01b8152600401600060405180830381865afa158015610c86573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cae9190810190613c2b565b9050600081516001600160401b03811115610ccb57610ccb612f39565b604051908082528060200260200182016040528015610d1c57816020015b6040805160808101825260008082526020808301829052928201526060808201528252600019909201910181610ce95790505b50905060005b8251811015610817576040805160808101825260008082526020820181905291810191909152606080820152838281518110610d6057610d60613a4c565b60209081029190910101516001600160a01b031681528351849083908110610d8a57610d8a613a4c565b60200260200101516001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dcf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df39190613a16565b6001600160a01b031660208201528351849083908110610e1557610e15613a4c565b6020908102919091010151604051631627ee8960e01b81526001600160a01b038a8116600483015290911690631627ee8990602401602060405180830381865afa158015610e67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8b9190613a33565b816040018181525050610eb88886868581518110610eab57610eab613a4c565b6020026020010151611eb3565b816060018190525080838381518110610ed357610ed3613a4c565b602090810291909101015250600101610d22565b6060826000816001600160401b03811115610f0457610f04612f39565b604051908082528060200260200182016040528015610f3d57816020015b610f2a612e3a565b815260200190600190039081610f225790505b50905060005b8281101561081757610f7b878783818110610f6057610f60613a4c565b9050602002016020810190610f75919061345c565b866118ca565b828281518110610f8d57610f8d613a4c565b6020908102919091010152600101610f43565b60408051808201909152600080825260208201526000826001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ff4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110189190613a16565b90506000816001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561105a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061107e9190613a16565b6040805180820182526001600160a01b03808816808352925163fc57d4df60e01b815260048101939093529293509160208301919084169063fc57d4df90602401602060405180830381865afa1580156110dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111009190613a33565b9052949350505050565b611112612e79565b6000826001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611152573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111769190613a33565b90506000836001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111dc9190613a16565b604051638e8f294b60e01b81526001600160a01b03868116600483015291925082916000918291841690638e8f294b906024016040805180830381865afa15801561122b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061124f9190613cc9565b915091506000876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611293573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b79190613a16565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061131d9190613cf5565b60ff1690506000805b600860ff8216116113e3576000886001600160a01b031663e85a29608d8460ff16600881111561135857611358613d18565b6040518363ffffffff1660e01b8152600401611375929190613d2e565b602060405180830381865afa158015611392573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b69190613d69565b6113c15760006113c4565b60015b60ff9081169083161b9290921791506113dc81613d84565b9050611326565b506000808b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611425573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114499190613a33565b11156114b4578a6001600160a01b031663ae9d70b06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561148d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114b19190613a33565b90505b6040518061022001604052808c6001600160a01b031681526020018a81526020018281526020018c6001600160a01b031663f8f9da286040518163ffffffff1660e01b8152600401602060405180830381865afa158015611519573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153d9190613a33565b81526020018c6001600160a01b031663173b99046040518163ffffffff1660e01b8152600401602060405180830381865afa158015611580573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a49190613a33565b81526040516302c3bcbb60e01b81526001600160a01b038e811660048301526020909201918a16906302c3bcbb90602401602060405180830381865afa1580156115f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116169190613a33565b815260405163252c221960e11b81526001600160a01b038e811660048301526020909201918a1690634a58443290602401602060405180830381865afa158015611664573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116889190613a33565b81526020018c6001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ef9190613a33565b81526020018c6001600160a01b0316638f840ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611732573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117569190613a33565b81526020018c6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611799573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117bd9190613a33565b81526020018c6001600160a01b0316633b1d21a26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611800573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118249190613a33565b81526020018715158152602001868152602001856001600160a01b031681526020018c6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611884573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118a89190613cf5565b60ff168152602001848152602001838152509950505050505050505050919050565b6118d2612e3a565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908516906370a0823190602401602060405180830381865afa15801561191c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119409190613a33565b6040516305eff7ef60e21b81526001600160a01b0385811660048301529192506000918616906317bfdfbc906024016020604051808303816000875af115801561198e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b29190613a33565b604051633af9e66960e01b81526001600160a01b038681166004830152919250600091871690633af9e669906024016020604051808303816000875af1158015611a00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a249190613a33565b90506000806000886001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a8d9190613a16565b6040516370a0823160e01b81526001600160a01b038a81166004830152919250908216906370a0823190602401602060405180830381865afa158015611ad7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611afb9190613a33565b604051636eb1769f60e11b81526001600160a01b038a811660048301528b811660248301529194509082169063dd62ed3e90604401602060405180830381865afa158015611b4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b719190613a33565b6040805160c0810182526001600160a01b038c168152602081019890985287019590955250506060840191909152608083015260a0820152905092915050565b604051631e6db74760e31b81526001600160a01b038281166004830152606091849182169063f36dba3890602401600060405180830381865afa158015611bfc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610baf9190810190613da3565b80516060906000816001600160401b03811115611c4357611c43612f39565b604051908082528060200260200182016040528015611c7c57816020015b611c69612e79565b815260200190600190039081611c615790505b50905060005b82811015611cd157611cac858281518110611c9f57611c9f613a4c565b602002602001015161110a565b828281518110611cbe57611cbe613a4c565b6020908102919091010152600101611c82565b509392505050565b6000611d077f000000000000000000000000000000000000000000000000000000000000000063ffffffff16565b905090565b4390565b4290565b60606000826001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015611d56573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d7e9190810190613e31565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031603611dbf5792915050565b8051600090815b81811015611ea9576000848281518110611de257611de2613a4c565b60200260200101516001600160a01b03166322abdbf56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e4b9190613a33565b1115611ea157838181518110611e6357611e63613a4c565b6020026020010151848481518110611e7d57611e7d613a4c565b6001600160a01b0390921660209283029190910190910152611e9e83613ebf565b92505b600101611dc6565b5050815292915050565b6060600083516001600160401b03811115611ed057611ed0612f39565b604051908082528060200260200182016040528015611f1557816020015b6040805180820190915260008082526020820152815260200190600190039081611eee5790505b50905060005b84518110156106e557611f51604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b611f7e604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b7f00000000000000000000000000000000000000000000000000000000000000001561210157856001600160a01b0316638f693ec7888581518110611fc557611fc5613a4c565b60200260200101516040518263ffffffff1660e01b8152600401611ff891906001600160a01b0391909116815260200190565b606060405180830381865afa158015612015573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120399190613eef565b604085015260208401526001600160e01b0316825286516001600160a01b0387169063818149459089908690811061207357612073613a4c565b60200260200101516040518263ffffffff1660e01b81526004016120a691906001600160a01b0391909116815260200190565b606060405180830381865afa1580156120c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e79190613eef565b604084015260208301526001600160e01b0316815261226c565b856001600160a01b0316632c427b5788858151811061212257612122613a4c565b60200260200101516040518263ffffffff1660e01b815260040161215591906001600160a01b0391909116815260200190565b606060405180830381865afa158015612172573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121969190613f38565b63ffffffff90811660408601521660208401526001600160e01b0316825286516001600160a01b038716906392a18235908990869081106121d9576121d9613a4c565b60200260200101516040518263ffffffff1660e01b815260040161220c91906001600160a01b0391909116815260200190565b606060405180830381865afa158015612229573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061224d9190613f38565b63ffffffff90811660408501521660208301526001600160e01b031681525b6000604051806020016040528089868151811061228b5761228b613a4c565b60200260200101516001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122f49190613a33565b815250905061231e88858151811061230e5761230e613a4c565b6020026020010151888584612413565b61234288858151811061233357612333613a4c565b60200260200101518884612614565b600061236a89868151811061235957612359613a4c565b6020026020010151898c878661280b565b905060006123938a878151811061238357612383613a4c565b60200260200101518a8d87612a3b565b60408051808201909152600080825260208201529091508a87815181106123bc576123bc613a4c565b60209081029190910101516001600160a01b031681526123dc8284613be4565b6020820152875181908990899081106123f7576123f7613a4c565b6020026020010181905250505050505050806001019050611f1b565b604051637c05a7c560e01b81526001600160a01b03858116600483015260009190851690637c05a7c590602401602060405180830381865afa15801561245d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124819190613a33565b9050600061248d611cd9565b9050600084604001511180156124a65750836040015181115b156124b2575060408301515b60006124c2828660200151612c5f565b90506000811180156124d45750600083115b156125fd576000612546886001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561251c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125409190613a33565b86612c72565b905060006125548386612c90565b90506000808311612574576040518060200160405280600081525061257e565b61257e8284612c9c565b905060006125a760405180602001604052808b600001516001600160e01b031681525083612ce1565b90506125e28160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612d0d565b6001600160e01b03168952505050506020850182905261260b565b801561260b57602085018290525b50505050505050565b604051631d31307360e21b81526001600160a01b038481166004830152600091908416906374c4c1cc90602401602060405180830381865afa15801561265e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126829190613a33565b9050600061268e611cd9565b9050600083604001511180156126a75750826040015181115b156126b3575060408201515b60006126c3828560200151612c5f565b90506000811180156126d55750600083115b156127f5576000866001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561271a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061273e9190613a33565b9050600061274c8386612c90565b9050600080831161276c5760405180602001604052806000815250612776565b6127768284612c9c565b9050600061279f60405180602001604052808a600001516001600160e01b031681525083612ce1565b90506127da8160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612d0d565b6001600160e01b031688525050505060208401829052612803565b801561280357602084018290525b505050505050565b604080516020808201835284516001600160e01b031682528251908101928390526336fe846560e11b9092526001600160a01b0387811660248401528581166044840152600092839181908916636dfd08ca60648301602060405180830381865afa15801561287e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a29190613a33565b905280519091501580156129245750866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129139190613f7b565b6001600160e01b0316826000015110155b1561299757866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061298b9190613f7b565b6001600160e01b031681525b60006129a38383612d49565b6040516395dd919360e01b81526001600160a01b038981166004830152919250600091612a1e91908c16906395dd919390602401602060405180830381865afa1580156129f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a189190613a33565b87612c72565b90506000612a2c8284612d75565b9b9a5050505050505050505050565b604080516020808201835283516001600160e01b0316825282519081019283905263552c097160e01b9092526001600160a01b038681166024840152848116604484015260009283918190881663552c097160648301602060405180830381865afa158015612aae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ad29190613a33565b90528051909150158015612b545750856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b439190613f7b565b6001600160e01b0316826000015110155b15612bc757856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bbb9190613f7b565b6001600160e01b031681525b6000612bd38383612d49565b6040516370a0823160e01b81526001600160a01b0388811660048301529192506000918a16906370a0823190602401602060405180830381865afa158015612c1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c439190613a33565b90506000612c518284612d75565b9a9950505050505050505050565b6000612c6b8284613f96565b9392505050565b6000612c6b612c8984670de0b6b3a7640000612c90565b8351612d9f565b6000612c6b8284613bab565b6040805160208101909152600081526040518060200160405280612cd8612cd2866ec097ce7bc90715b34b9f1000000000612c90565b85612d9f565b90529392505050565b6040805160208101909152600081526040518060200160405280612cd885600001518560000151612dab565b6000816001600160e01b03841115612d415760405162461bcd60e51b8152600401612d389190613fa9565b60405180910390fd5b509192915050565b6040805160208101909152600081526040518060200160405280612cd885600001518560000151612c5f565b60006ec097ce7bc90715b34b9f1000000000612d95848460000151612c90565b612c6b9190613bc2565b6000612c6b8284613bc2565b6000612c6b8284613be4565b604051806101a001604052806060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160608152602001606081526020016060815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001606081525090565b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180610220016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b6001600160a01b0381168114612f2657600080fd5b50565b8035612f3481612f11565b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715612f7157612f71612f39565b60405290565b604051606081016001600160401b0381118282101715612f7157612f71612f39565b604051601f8201601f191681016001600160401b0381118282101715612fc157612fc1612f39565b604052919050565b60006001600160401b03821115612fe257612fe2612f39565b50601f01601f191660200190565b6000806040838503121561300357600080fd5b823561300e81612f11565b91506020838101356001600160401b038082111561302b57600080fd5b9085019060a0828803121561303f57600080fd5b613047612f4f565b82358281111561305657600080fd5b83019150601f8201881361306957600080fd5b813561307c61307782612fc9565b612f99565b818152898683860101111561309057600080fd5b8186850187830137600086838301015280835250506130b0848401612f29565b848201526130c060408401612f29565b60408201526060830135606082015260808301356080820152809450505050509250929050565b60005b838110156131025781810151838201526020016130ea565b50506000910152565b600081518084526131238160208601602086016130e7565b601f01601f19169290920160200192915050565b80516001600160a01b031682526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e0830152610100808201518184015250610120808201518184015250610140808201518184015250610160808201516131c28285018215159052565b505061018081810151908301526101a0808201516001600160a01b0316908301526101c080820151908301526101e0808201519083015261020090810151910152565b60008151808452602080850194506020840160005b838110156132415761322d878351613137565b61022096909601959082019060010161321a565b509495945050505050565b60006101a082518185526132628286018261310b565b915050602083015161327f60208601826001600160a01b03169052565b50604083015161329a60408601826001600160a01b03169052565b50606083015160608501526080830151608085015260a083015184820360a08601526132c6828261310b565b91505060c083015184820360c08601526132e0828261310b565b91505060e083015184820360e08601526132fa828261310b565b91505061010080840151613318828701826001600160a01b03169052565b505061012083810151908501526101408084015190850152610160808401519085015261018080840151858303828701526133538382613205565b9695505050505050565b602081526000612c6b602083018461324c565b60008083601f84011261338257600080fd5b5081356001600160401b0381111561339957600080fd5b6020830191508360208260051b85010111156133b457600080fd5b9250929050565b600080602083850312156133ce57600080fd5b82356001600160401b038111156133e457600080fd5b6133f085828601613370565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b8281101561344f5761343f84835180516001600160a01b03168252602090810151910152565b9284019290850190600101613419565b5091979650505050505050565b60006020828403121561346e57600080fd5b8135612c6b81612f11565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156134d057603f198886030184526134be85835161324c565b945092850192908501906001016134a2565b5092979650505050505050565b602080825282516001600160a01b03168282015282810151604080840191909152808401516060808501528051608085018190526000939291830191849160a08701905b8084101561355b5761354782865180516001600160a01b03168252602090810151910152565b938501936001939093019290820190613521565b50979650505050505050565b6000806040838503121561357a57600080fd5b823561358581612f11565b9150602083013561359581612f11565b809150509250929050565b6000806000606084860312156135b557600080fd5b83356135c081612f11565b925060208401356135d081612f11565b915060408401356135e081612f11565b809150509250925092565b600060208083018184528085518083526040925060408601915060408160051b8701018488016000805b848110156136b857898403603f19018652825180516001600160a01b03908116865289820151168986015287810151888601526060908101516080918601829052805191860182905289019060a086019084905b808210156136a35761368f83855180516001600160a01b03168252602090810151910152565b928b0192918a019160019190910190613669565b50509689019694505091870191600101613615565b50919998505050505050505050565b6000806000604084860312156136dc57600080fd5b83356001600160401b038111156136f257600080fd5b6136fe86828701613370565b90945092505060208401356135e081612f11565b80516001600160a01b031682526020808201519083015260408082015190830152606080820151908301526080808201519083015260a090810151910152565b6020808252825182820181905260009190848201906040850190845b8181101561379457613781838551613712565b9284019260c0929092019160010161376e565b50909695505050505050565b81516001600160a01b031681526020808301519082015260408101610620565b61022081016106208284613137565b60c081016106208284613712565b6020808252825182820181905260009190848201906040850190845b818110156137945783516001600160a01b0316835292840192918401916001016137f9565b60006001600160401b0382111561383757613837612f39565b5060051b60200190565b6000602080838503121561385457600080fd5b82356001600160401b0381111561386a57600080fd5b8301601f8101851361387b57600080fd5b80356138896130778261381e565b81815260059190911b820183019083810190878311156138a857600080fd5b928401925b828410156138cf5783356138c081612f11565b825292840192908401906138ad565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561379457613909838551613137565b9284019261022092909201916001016138f6565b600082601f83011261392e57600080fd5b815161393c61307782612fc9565b81815284602083860101111561395157600080fd5b610baf8260208301602087016130e7565b60006020828403121561397457600080fd5b81516001600160401b038082111561398b57600080fd5b908301906060828603121561399f57600080fd5b6139a7612f77565b8251828111156139b657600080fd5b6139c28782860161391d565b8252506020830151828111156139d757600080fd5b6139e38782860161391d565b6020830152506040830151828111156139fb57600080fd5b613a078782860161391d565b60408301525095945050505050565b600060208284031215613a2857600080fd5b8151612c6b81612f11565b600060208284031215613a4557600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600060a08284031215613a7457600080fd5b613a7c612f4f565b905081516001600160401b03811115613a9457600080fd5b613aa08482850161391d565b8252506020820151613ab181612f11565b60208201526040820151613ac481612f11565b80604083015250606082015160608201526080820151608082015292915050565b60006020808385031215613af857600080fd5b82516001600160401b0380821115613b0f57600080fd5b818501915085601f830112613b2357600080fd5b8151613b316130778261381e565b81815260059190911b83018401908481019088831115613b5057600080fd5b8585015b83811015613b8857805185811115613b6c5760008081fd5b613b7a8b89838a0101613a62565b845250918601918601613b54565b5098975050505050505050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761062057610620613b95565b600082613bdf57634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561062057610620613b95565b600060208284031215613c0957600080fd5b81516001600160401b03811115613c1f57600080fd5b610baf84828501613a62565b60006020808385031215613c3e57600080fd5b82516001600160401b03811115613c5457600080fd5b8301601f81018513613c6557600080fd5b8051613c736130778261381e565b81815260059190911b82018301908381019087831115613c9257600080fd5b928401925b828410156138cf578351613caa81612f11565b82529284019290840190613c97565b80518015158114612f3457600080fd5b60008060408385031215613cdc57600080fd5b613ce583613cb9565b9150602083015190509250929050565b600060208284031215613d0757600080fd5b815160ff81168114612c6b57600080fd5b634e487b7160e01b600052602160045260246000fd5b6001600160a01b03831681526040810160098310613d5c57634e487b7160e01b600052602160045260246000fd5b8260208301529392505050565b600060208284031215613d7b57600080fd5b612c6b82613cb9565b600060ff821660ff8103613d9a57613d9a613b95565b60010192915050565b60006020808385031215613db657600080fd5b82516001600160401b03811115613dcc57600080fd5b8301601f81018513613ddd57600080fd5b8051613deb6130778261381e565b81815260059190911b82018301908381019087831115613e0a57600080fd5b928401925b828410156138cf578351613e2281612f11565b82529284019290840190613e0f565b60006020808385031215613e4457600080fd5b82516001600160401b03811115613e5a57600080fd5b8301601f81018513613e6b57600080fd5b8051613e796130778261381e565b81815260059190911b82018301908381019087831115613e9857600080fd5b928401925b828410156138cf578351613eb081612f11565b82529284019290840190613e9d565b600060018201613ed157613ed1613b95565b5060010190565b80516001600160e01b0381168114612f3457600080fd5b600080600060608486031215613f0457600080fd5b613f0d84613ed8565b925060208401519150604084015190509250925092565b805163ffffffff81168114612f3457600080fd5b600080600060608486031215613f4d57600080fd5b613f5684613ed8565b9250613f6460208501613f24565b9150613f7260408501613f24565b90509250925092565b600060208284031215613f8d57600080fd5b612c6b82613ed8565b8181038181111561062057610620613b95565b602081526000612c6b602083018461310b56fea264697066735822122096dca9ef030f65331631c7305d4d9405c1d0b56d48eb3787508d19369d85297764736f6c63430008190033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061010b5760003560e01c80637c51b642116100a2578063c7ad089511610071578063c7ad0895146102ac578063d26998e9146102e3578063d77ebf961461030a578063e0a67f111461032a578063e1d146fb1461034a57600080fd5b80637c51b6421461022c5780637c84e3b31461024c578063aa5dbd231461026c578063b31242391461028c57600080fd5b806347d86a81116100de57806347d86a811461019957806355dd9515146101ac5780636857249c146101d75780637a27db571461020c57600080fd5b80630d3ae318146101105780631f884fdf14610139578063345954dc146101595780633e3e399c14610179575b600080fd5b61012361011e366004612ff0565b610352565b604051610130919061335d565b60405180910390f35b61014c6101473660046133bb565b610626565b60405161013091906133fc565b61016c61016736600461345c565b6106ee565b6040516101309190613479565b61018c61018736600461345c565b610821565b60405161013091906134dd565b6101236101a7366004613567565b610b30565b6101bf6101ba3660046135a0565b610bb7565b6040516001600160a01b039091168152602001610130565b6101fe7f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610130565b61021f61021a366004613567565b610c37565b60405161013091906135eb565b61023f61023a3660046136c7565b610ee7565b6040516101309190613752565b61025f61025a36600461345c565b610fa0565b60405161013091906137a0565b61027f61027a36600461345c565b61110a565b60405161013091906137c0565b61029f61029a366004613567565b6118ca565b60405161013091906137cf565b6102d37f000000000000000000000000000000000000000000000000000000000000000081565b6040519015158152602001610130565b6101bf7f000000000000000000000000000000000000000000000000000000000000000081565b61031d610318366004613567565b611bb1565b60405161013091906137dd565b61033d610338366004613841565b611c24565b60405161013091906138da565b6101fe611cd9565b61035a612db7565b6040820151600061036a82611d14565b9050600061037782611c24565b60408681015190516328ebbe8b60e21b81526001600160a01b039182166004820152919250879160009183169063a3aefa2c90602401600060405180830381865afa1580156103ca573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526103f29190810190613962565b90506000876040015190506000604051806101a001604052808a6000015181526020018a602001516001600160a01b031681526020018a604001516001600160a01b031681526020018a6060015181526020018a608001518152602001846000015181526020018460200151815260200184604001518152602001836001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104cf9190613a16565b6001600160a01b03168152602001836001600160a01b031663e87554466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561051b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053f9190613a33565b8152602001836001600160a01b0316634ada90af6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610582573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105a69190613a33565b8152602001836001600160a01b031663db5c65de6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060d9190613a33565b8152602001959095525092955050505050505b92915050565b6060816000816001600160401b0381111561064357610643612f39565b60405190808252806020026020018201604052801561068857816020015b60408051808201909152600080825260208201528152602001906001900390816106615790505b50905060005b828110156106e5576106c08686838181106106ab576106ab613a4c565b905060200201602081019061025a919061345c565b8282815181106106d2576106d2613a4c565b602090810291909101015260010161068e565b50949350505050565b606060008290506000816001600160a01b031663d88ff1f46040518163ffffffff1660e01b8152600401600060405180830381865afa158015610735573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261075d9190810190613ae5565b80519091506000816001600160401b0381111561077c5761077c612f39565b6040519080825280602002602001820160405280156107b557816020015b6107a2612db7565b81526020019060019003908161079a5790505b50905060005b828110156108175760008482815181106107d7576107d7613a4c565b6020026020010151905060006107ed8983610352565b90508084848151811061080257610802613a4c565b602090810291909101015250506001016107bb565b5095945050505050565b60408051606080820183526000808352602083018190529282015290828161084882611d14565b90506000826001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561088a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ae9190613a16565b9050600082516001600160401b038111156108cb576108cb612f39565b60405190808252806020026020018201604052801561091057816020015b60408051808201909152600080825260208201528152602001906001900390816108e95790505b509050610940604051806060016040528060006001600160a01b0316815260200160008152602001606081525090565b6001600160a01b03881681526040810182905260005b8451811015610b1c57604080518082019091526000808252602082015285828151811061098557610985613a4c565b602002602001015181600001906001600160a01b031690816001600160a01b031681525050670de0b6b3a7640000856001600160a01b031663fc57d4df8885815181106109d4576109d4613a4c565b60200260200101516040518263ffffffff1660e01b8152600401610a0791906001600160a01b0391909116815260200190565b602060405180830381865afa158015610a24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a489190613a33565b878481518110610a5a57610a5a613a4c565b60200260200101516001600160a01b031663bbcac5576040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac39190613a33565b610acd9190613bab565b610ad79190613bc2565b60208201526040830151805182919084908110610af657610af6613a4c565b6020026020010181905250806020015188610b119190613be4565b975050600101610956565b506020810195909552509295945050505050565b610b38612db7565b604051637aee632d60e01b81526001600160a01b0383811660048301528491610baf91839190821690637aee632d90602401600060405180830381865afa158015610b87573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261011e9190810190613bf7565b949350505050565b60405163266e0a7f60e01b81526001600160a01b0383811660048301528281166024830152600091859182169063266e0a7f90604401602060405180830381865afa158015610c0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2e9190613a16565b95945050505050565b60606000610c4483611d14565b90506000836001600160a01b03166361252fd16040518163ffffffff1660e01b8152600401600060405180830381865afa158015610c86573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cae9190810190613c2b565b9050600081516001600160401b03811115610ccb57610ccb612f39565b604051908082528060200260200182016040528015610d1c57816020015b6040805160808101825260008082526020808301829052928201526060808201528252600019909201910181610ce95790505b50905060005b8251811015610817576040805160808101825260008082526020820181905291810191909152606080820152838281518110610d6057610d60613a4c565b60209081029190910101516001600160a01b031681528351849083908110610d8a57610d8a613a4c565b60200260200101516001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dcf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df39190613a16565b6001600160a01b031660208201528351849083908110610e1557610e15613a4c565b6020908102919091010151604051631627ee8960e01b81526001600160a01b038a8116600483015290911690631627ee8990602401602060405180830381865afa158015610e67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8b9190613a33565b816040018181525050610eb88886868581518110610eab57610eab613a4c565b6020026020010151611eb3565b816060018190525080838381518110610ed357610ed3613a4c565b602090810291909101015250600101610d22565b6060826000816001600160401b03811115610f0457610f04612f39565b604051908082528060200260200182016040528015610f3d57816020015b610f2a612e3a565b815260200190600190039081610f225790505b50905060005b8281101561081757610f7b878783818110610f6057610f60613a4c565b9050602002016020810190610f75919061345c565b866118ca565b828281518110610f8d57610f8d613a4c565b6020908102919091010152600101610f43565b60408051808201909152600080825260208201526000826001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ff4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110189190613a16565b90506000816001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561105a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061107e9190613a16565b6040805180820182526001600160a01b03808816808352925163fc57d4df60e01b815260048101939093529293509160208301919084169063fc57d4df90602401602060405180830381865afa1580156110dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111009190613a33565b9052949350505050565b611112612e79565b6000826001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611152573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111769190613a33565b90506000836001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111dc9190613a16565b604051638e8f294b60e01b81526001600160a01b03868116600483015291925082916000918291841690638e8f294b906024016040805180830381865afa15801561122b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061124f9190613cc9565b915091506000876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611293573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b79190613a16565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061131d9190613cf5565b60ff1690506000805b600860ff8216116113e3576000886001600160a01b031663e85a29608d8460ff16600881111561135857611358613d18565b6040518363ffffffff1660e01b8152600401611375929190613d2e565b602060405180830381865afa158015611392573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b69190613d69565b6113c15760006113c4565b60015b60ff9081169083161b9290921791506113dc81613d84565b9050611326565b506000808b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611425573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114499190613a33565b11156114b4578a6001600160a01b031663ae9d70b06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561148d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114b19190613a33565b90505b6040518061022001604052808c6001600160a01b031681526020018a81526020018281526020018c6001600160a01b031663f8f9da286040518163ffffffff1660e01b8152600401602060405180830381865afa158015611519573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153d9190613a33565b81526020018c6001600160a01b031663173b99046040518163ffffffff1660e01b8152600401602060405180830381865afa158015611580573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a49190613a33565b81526040516302c3bcbb60e01b81526001600160a01b038e811660048301526020909201918a16906302c3bcbb90602401602060405180830381865afa1580156115f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116169190613a33565b815260405163252c221960e11b81526001600160a01b038e811660048301526020909201918a1690634a58443290602401602060405180830381865afa158015611664573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116889190613a33565b81526020018c6001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ef9190613a33565b81526020018c6001600160a01b0316638f840ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611732573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117569190613a33565b81526020018c6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611799573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117bd9190613a33565b81526020018c6001600160a01b0316633b1d21a26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611800573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118249190613a33565b81526020018715158152602001868152602001856001600160a01b031681526020018c6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611884573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118a89190613cf5565b60ff168152602001848152602001838152509950505050505050505050919050565b6118d2612e3a565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908516906370a0823190602401602060405180830381865afa15801561191c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119409190613a33565b6040516305eff7ef60e21b81526001600160a01b0385811660048301529192506000918616906317bfdfbc906024016020604051808303816000875af115801561198e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b29190613a33565b604051633af9e66960e01b81526001600160a01b038681166004830152919250600091871690633af9e669906024016020604051808303816000875af1158015611a00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a249190613a33565b90506000806000886001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a8d9190613a16565b6040516370a0823160e01b81526001600160a01b038a81166004830152919250908216906370a0823190602401602060405180830381865afa158015611ad7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611afb9190613a33565b604051636eb1769f60e11b81526001600160a01b038a811660048301528b811660248301529194509082169063dd62ed3e90604401602060405180830381865afa158015611b4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b719190613a33565b6040805160c0810182526001600160a01b038c168152602081019890985287019590955250506060840191909152608083015260a0820152905092915050565b604051631e6db74760e31b81526001600160a01b038281166004830152606091849182169063f36dba3890602401600060405180830381865afa158015611bfc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610baf9190810190613da3565b80516060906000816001600160401b03811115611c4357611c43612f39565b604051908082528060200260200182016040528015611c7c57816020015b611c69612e79565b815260200190600190039081611c615790505b50905060005b82811015611cd157611cac858281518110611c9f57611c9f613a4c565b602002602001015161110a565b828281518110611cbe57611cbe613a4c565b6020908102919091010152600101611c82565b509392505050565b6000611d077f000000000000000000000000000000000000000000000000000000000000000063ffffffff16565b905090565b4390565b4290565b60606000826001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015611d56573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d7e9190810190613e31565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031603611dbf5792915050565b8051600090815b81811015611ea9576000848281518110611de257611de2613a4c565b60200260200101516001600160a01b03166322abdbf56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e4b9190613a33565b1115611ea157838181518110611e6357611e63613a4c565b6020026020010151848481518110611e7d57611e7d613a4c565b6001600160a01b0390921660209283029190910190910152611e9e83613ebf565b92505b600101611dc6565b5050815292915050565b6060600083516001600160401b03811115611ed057611ed0612f39565b604051908082528060200260200182016040528015611f1557816020015b6040805180820190915260008082526020820152815260200190600190039081611eee5790505b50905060005b84518110156106e557611f51604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b611f7e604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b7f00000000000000000000000000000000000000000000000000000000000000001561210157856001600160a01b0316638f693ec7888581518110611fc557611fc5613a4c565b60200260200101516040518263ffffffff1660e01b8152600401611ff891906001600160a01b0391909116815260200190565b606060405180830381865afa158015612015573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120399190613eef565b604085015260208401526001600160e01b0316825286516001600160a01b0387169063818149459089908690811061207357612073613a4c565b60200260200101516040518263ffffffff1660e01b81526004016120a691906001600160a01b0391909116815260200190565b606060405180830381865afa1580156120c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e79190613eef565b604084015260208301526001600160e01b0316815261226c565b856001600160a01b0316632c427b5788858151811061212257612122613a4c565b60200260200101516040518263ffffffff1660e01b815260040161215591906001600160a01b0391909116815260200190565b606060405180830381865afa158015612172573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121969190613f38565b63ffffffff90811660408601521660208401526001600160e01b0316825286516001600160a01b038716906392a18235908990869081106121d9576121d9613a4c565b60200260200101516040518263ffffffff1660e01b815260040161220c91906001600160a01b0391909116815260200190565b606060405180830381865afa158015612229573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061224d9190613f38565b63ffffffff90811660408501521660208301526001600160e01b031681525b6000604051806020016040528089868151811061228b5761228b613a4c565b60200260200101516001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122f49190613a33565b815250905061231e88858151811061230e5761230e613a4c565b6020026020010151888584612413565b61234288858151811061233357612333613a4c565b60200260200101518884612614565b600061236a89868151811061235957612359613a4c565b6020026020010151898c878661280b565b905060006123938a878151811061238357612383613a4c565b60200260200101518a8d87612a3b565b60408051808201909152600080825260208201529091508a87815181106123bc576123bc613a4c565b60209081029190910101516001600160a01b031681526123dc8284613be4565b6020820152875181908990899081106123f7576123f7613a4c565b6020026020010181905250505050505050806001019050611f1b565b604051637c05a7c560e01b81526001600160a01b03858116600483015260009190851690637c05a7c590602401602060405180830381865afa15801561245d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124819190613a33565b9050600061248d611cd9565b9050600084604001511180156124a65750836040015181115b156124b2575060408301515b60006124c2828660200151612c5f565b90506000811180156124d45750600083115b156125fd576000612546886001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561251c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125409190613a33565b86612c72565b905060006125548386612c90565b90506000808311612574576040518060200160405280600081525061257e565b61257e8284612c9c565b905060006125a760405180602001604052808b600001516001600160e01b031681525083612ce1565b90506125e28160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612d0d565b6001600160e01b03168952505050506020850182905261260b565b801561260b57602085018290525b50505050505050565b604051631d31307360e21b81526001600160a01b038481166004830152600091908416906374c4c1cc90602401602060405180830381865afa15801561265e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126829190613a33565b9050600061268e611cd9565b9050600083604001511180156126a75750826040015181115b156126b3575060408201515b60006126c3828560200151612c5f565b90506000811180156126d55750600083115b156127f5576000866001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561271a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061273e9190613a33565b9050600061274c8386612c90565b9050600080831161276c5760405180602001604052806000815250612776565b6127768284612c9c565b9050600061279f60405180602001604052808a600001516001600160e01b031681525083612ce1565b90506127da8160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612d0d565b6001600160e01b031688525050505060208401829052612803565b801561280357602084018290525b505050505050565b604080516020808201835284516001600160e01b031682528251908101928390526336fe846560e11b9092526001600160a01b0387811660248401528581166044840152600092839181908916636dfd08ca60648301602060405180830381865afa15801561287e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a29190613a33565b905280519091501580156129245750866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129139190613f7b565b6001600160e01b0316826000015110155b1561299757866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061298b9190613f7b565b6001600160e01b031681525b60006129a38383612d49565b6040516395dd919360e01b81526001600160a01b038981166004830152919250600091612a1e91908c16906395dd919390602401602060405180830381865afa1580156129f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a189190613a33565b87612c72565b90506000612a2c8284612d75565b9b9a5050505050505050505050565b604080516020808201835283516001600160e01b0316825282519081019283905263552c097160e01b9092526001600160a01b038681166024840152848116604484015260009283918190881663552c097160648301602060405180830381865afa158015612aae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ad29190613a33565b90528051909150158015612b545750856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b439190613f7b565b6001600160e01b0316826000015110155b15612bc757856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bbb9190613f7b565b6001600160e01b031681525b6000612bd38383612d49565b6040516370a0823160e01b81526001600160a01b0388811660048301529192506000918a16906370a0823190602401602060405180830381865afa158015612c1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c439190613a33565b90506000612c518284612d75565b9a9950505050505050505050565b6000612c6b8284613f96565b9392505050565b6000612c6b612c8984670de0b6b3a7640000612c90565b8351612d9f565b6000612c6b8284613bab565b6040805160208101909152600081526040518060200160405280612cd8612cd2866ec097ce7bc90715b34b9f1000000000612c90565b85612d9f565b90529392505050565b6040805160208101909152600081526040518060200160405280612cd885600001518560000151612dab565b6000816001600160e01b03841115612d415760405162461bcd60e51b8152600401612d389190613fa9565b60405180910390fd5b509192915050565b6040805160208101909152600081526040518060200160405280612cd885600001518560000151612c5f565b60006ec097ce7bc90715b34b9f1000000000612d95848460000151612c90565b612c6b9190613bc2565b6000612c6b8284613bc2565b6000612c6b8284613be4565b604051806101a001604052806060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160608152602001606081526020016060815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001606081525090565b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180610220016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b6001600160a01b0381168114612f2657600080fd5b50565b8035612f3481612f11565b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715612f7157612f71612f39565b60405290565b604051606081016001600160401b0381118282101715612f7157612f71612f39565b604051601f8201601f191681016001600160401b0381118282101715612fc157612fc1612f39565b604052919050565b60006001600160401b03821115612fe257612fe2612f39565b50601f01601f191660200190565b6000806040838503121561300357600080fd5b823561300e81612f11565b91506020838101356001600160401b038082111561302b57600080fd5b9085019060a0828803121561303f57600080fd5b613047612f4f565b82358281111561305657600080fd5b83019150601f8201881361306957600080fd5b813561307c61307782612fc9565b612f99565b818152898683860101111561309057600080fd5b8186850187830137600086838301015280835250506130b0848401612f29565b848201526130c060408401612f29565b60408201526060830135606082015260808301356080820152809450505050509250929050565b60005b838110156131025781810151838201526020016130ea565b50506000910152565b600081518084526131238160208601602086016130e7565b601f01601f19169290920160200192915050565b80516001600160a01b031682526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e0830152610100808201518184015250610120808201518184015250610140808201518184015250610160808201516131c28285018215159052565b505061018081810151908301526101a0808201516001600160a01b0316908301526101c080820151908301526101e0808201519083015261020090810151910152565b60008151808452602080850194506020840160005b838110156132415761322d878351613137565b61022096909601959082019060010161321a565b509495945050505050565b60006101a082518185526132628286018261310b565b915050602083015161327f60208601826001600160a01b03169052565b50604083015161329a60408601826001600160a01b03169052565b50606083015160608501526080830151608085015260a083015184820360a08601526132c6828261310b565b91505060c083015184820360c08601526132e0828261310b565b91505060e083015184820360e08601526132fa828261310b565b91505061010080840151613318828701826001600160a01b03169052565b505061012083810151908501526101408084015190850152610160808401519085015261018080840151858303828701526133538382613205565b9695505050505050565b602081526000612c6b602083018461324c565b60008083601f84011261338257600080fd5b5081356001600160401b0381111561339957600080fd5b6020830191508360208260051b85010111156133b457600080fd5b9250929050565b600080602083850312156133ce57600080fd5b82356001600160401b038111156133e457600080fd5b6133f085828601613370565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b8281101561344f5761343f84835180516001600160a01b03168252602090810151910152565b9284019290850190600101613419565b5091979650505050505050565b60006020828403121561346e57600080fd5b8135612c6b81612f11565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156134d057603f198886030184526134be85835161324c565b945092850192908501906001016134a2565b5092979650505050505050565b602080825282516001600160a01b03168282015282810151604080840191909152808401516060808501528051608085018190526000939291830191849160a08701905b8084101561355b5761354782865180516001600160a01b03168252602090810151910152565b938501936001939093019290820190613521565b50979650505050505050565b6000806040838503121561357a57600080fd5b823561358581612f11565b9150602083013561359581612f11565b809150509250929050565b6000806000606084860312156135b557600080fd5b83356135c081612f11565b925060208401356135d081612f11565b915060408401356135e081612f11565b809150509250925092565b600060208083018184528085518083526040925060408601915060408160051b8701018488016000805b848110156136b857898403603f19018652825180516001600160a01b03908116865289820151168986015287810151888601526060908101516080918601829052805191860182905289019060a086019084905b808210156136a35761368f83855180516001600160a01b03168252602090810151910152565b928b0192918a019160019190910190613669565b50509689019694505091870191600101613615565b50919998505050505050505050565b6000806000604084860312156136dc57600080fd5b83356001600160401b038111156136f257600080fd5b6136fe86828701613370565b90945092505060208401356135e081612f11565b80516001600160a01b031682526020808201519083015260408082015190830152606080820151908301526080808201519083015260a090810151910152565b6020808252825182820181905260009190848201906040850190845b8181101561379457613781838551613712565b9284019260c0929092019160010161376e565b50909695505050505050565b81516001600160a01b031681526020808301519082015260408101610620565b61022081016106208284613137565b60c081016106208284613712565b6020808252825182820181905260009190848201906040850190845b818110156137945783516001600160a01b0316835292840192918401916001016137f9565b60006001600160401b0382111561383757613837612f39565b5060051b60200190565b6000602080838503121561385457600080fd5b82356001600160401b0381111561386a57600080fd5b8301601f8101851361387b57600080fd5b80356138896130778261381e565b81815260059190911b820183019083810190878311156138a857600080fd5b928401925b828410156138cf5783356138c081612f11565b825292840192908401906138ad565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561379457613909838551613137565b9284019261022092909201916001016138f6565b600082601f83011261392e57600080fd5b815161393c61307782612fc9565b81815284602083860101111561395157600080fd5b610baf8260208301602087016130e7565b60006020828403121561397457600080fd5b81516001600160401b038082111561398b57600080fd5b908301906060828603121561399f57600080fd5b6139a7612f77565b8251828111156139b657600080fd5b6139c28782860161391d565b8252506020830151828111156139d757600080fd5b6139e38782860161391d565b6020830152506040830151828111156139fb57600080fd5b613a078782860161391d565b60408301525095945050505050565b600060208284031215613a2857600080fd5b8151612c6b81612f11565b600060208284031215613a4557600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600060a08284031215613a7457600080fd5b613a7c612f4f565b905081516001600160401b03811115613a9457600080fd5b613aa08482850161391d565b8252506020820151613ab181612f11565b60208201526040820151613ac481612f11565b80604083015250606082015160608201526080820151608082015292915050565b60006020808385031215613af857600080fd5b82516001600160401b0380821115613b0f57600080fd5b818501915085601f830112613b2357600080fd5b8151613b316130778261381e565b81815260059190911b83018401908481019088831115613b5057600080fd5b8585015b83811015613b8857805185811115613b6c5760008081fd5b613b7a8b89838a0101613a62565b845250918601918601613b54565b5098975050505050505050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761062057610620613b95565b600082613bdf57634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561062057610620613b95565b600060208284031215613c0957600080fd5b81516001600160401b03811115613c1f57600080fd5b610baf84828501613a62565b60006020808385031215613c3e57600080fd5b82516001600160401b03811115613c5457600080fd5b8301601f81018513613c6557600080fd5b8051613c736130778261381e565b81815260059190911b82018301908381019087831115613c9257600080fd5b928401925b828410156138cf578351613caa81612f11565b82529284019290840190613c97565b80518015158114612f3457600080fd5b60008060408385031215613cdc57600080fd5b613ce583613cb9565b9150602083015190509250929050565b600060208284031215613d0757600080fd5b815160ff81168114612c6b57600080fd5b634e487b7160e01b600052602160045260246000fd5b6001600160a01b03831681526040810160098310613d5c57634e487b7160e01b600052602160045260246000fd5b8260208301529392505050565b600060208284031215613d7b57600080fd5b612c6b82613cb9565b600060ff821660ff8103613d9a57613d9a613b95565b60010192915050565b60006020808385031215613db657600080fd5b82516001600160401b03811115613dcc57600080fd5b8301601f81018513613ddd57600080fd5b8051613deb6130778261381e565b81815260059190911b82018301908381019087831115613e0a57600080fd5b928401925b828410156138cf578351613e2281612f11565b82529284019290840190613e0f565b60006020808385031215613e4457600080fd5b82516001600160401b03811115613e5a57600080fd5b8301601f81018513613e6b57600080fd5b8051613e796130778261381e565b81815260059190911b82018301908381019087831115613e9857600080fd5b928401925b828410156138cf578351613eb081612f11565b82529284019290840190613e9d565b600060018201613ed157613ed1613b95565b5060010190565b80516001600160e01b0381168114612f3457600080fd5b600080600060608486031215613f0457600080fd5b613f0d84613ed8565b925060208401519150604084015190509250925092565b805163ffffffff81168114612f3457600080fd5b600080600060608486031215613f4d57600080fd5b613f5684613ed8565b9250613f6460208501613f24565b9150613f7260408501613f24565b90509250925092565b600060208284031215613f8d57600080fd5b612c6b82613ed8565b8181038181111561062057610620613b95565b602081526000612c6b602083018461310b56fea264697066735822122096dca9ef030f65331631c7305d4d9405c1d0b56d48eb3787508d19369d85297764736f6c63430008190033", "devdoc": { "author": "Venus", "kind": "dev", @@ -1198,6 +1216,7 @@ "custom:oz-upgrades-unsafe-allow": "constructor", "params": { "blocksPerYear_": "The number of blocks per year", + "corePoolComptroller_": "The address of the core pool comptroller", "timeBased_": "A boolean indicating whether the contract is based on time or block." } }, @@ -1342,6 +1361,9 @@ "blocksOrSecondsPerYear()": { "notice": "Stores blocksPerYear if isTimeBased is true else secondsPerYear is stored" }, + "corePoolComptroller()": { + "notice": "Address of the core pool comptroller (all markets are returned for this pool, including paused ones)" + }, "getAllPools(address)": { "notice": "Queries all pools with addtional details for each of them" }, @@ -1391,7 +1413,7 @@ "storageLayout": { "storage": [ { - "astId": 7500, + "astId": 1737, "contract": "contracts/Lens/PoolLens.sol:PoolLens", "label": "__gap", "offset": 0, diff --git a/deployments/opbnbmainnet/solcInputs/09f8b2889a382752688c03578bc27f8d.json b/deployments/opbnbmainnet/solcInputs/09f8b2889a382752688c03578bc27f8d.json new file mode 100644 index 000000000..b2e4f0f5c --- /dev/null +++ b/deployments/opbnbmainnet/solcInputs/09f8b2889a382752688c03578bc27f8d.json @@ -0,0 +1,139 @@ +{ + "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/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/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/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/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" + }, + "@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/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/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\ninterface IProtocolShareReserve {\n /// @notice it represents the type of vToken income\n enum IncomeType {\n SPREAD,\n LIQUIDATION,\n ERC4626_WRAPPER_REWARDS,\n FLASHLOAN\n }\n\n function updateAssetsState(\n address comptroller,\n address asset,\n IncomeType incomeType\n ) external;\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/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/venus-protocol/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" + }, + "@venusprotocol/venus-protocol/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/Comptroller.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { IPrime } from \"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\";\n\nimport { ComptrollerInterface, Action } from \"./ComptrollerInterface.sol\";\nimport { ComptrollerStorage } from \"./ComptrollerStorage.sol\";\nimport { ExponentialNoError } from \"./ExponentialNoError.sol\";\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.sol\";\nimport { MaxLoopsLimitHelper } from \"./MaxLoopsLimitHelper.sol\";\nimport { ensureNonzeroAddress } from \"./lib/validators.sol\";\n\n/**\n * @title Comptroller\n * @author Venus\n * @notice The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating,\n * and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts\n * with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows\n * or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing\n * liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow,\n * as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the\n * markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market’s corresponding liquidation threshold,\n * the borrow is eligible for liquidation.\n *\n * The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed\n * the `minLiquidatableCollateral` for the `Comptroller`:\n *\n * - `healAccount()`: This function is called to seize all of a given user’s collateral, requiring the `msg.sender` repay a certain percentage\n * of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed\n * 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt\n * and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool.\n * - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation\n * incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic\n * verifying that the repay amount does not exceed the close factor.\n */\ncontract Comptroller is\n Ownable2StepUpgradeable,\n AccessControlledV8,\n ComptrollerStorage,\n ComptrollerInterface,\n ExponentialNoError,\n MaxLoopsLimitHelper\n{\n // PoolRegistry, immutable to save on gas\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable poolRegistry;\n\n /// @notice Emitted when an account enters a market\n event MarketEntered(VToken indexed vToken, address indexed account);\n\n /// @notice Emitted when an account exits a market\n event MarketExited(VToken indexed vToken, address indexed account);\n\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(VToken vToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa);\n\n /// @notice Emitted when liquidation threshold is changed by admin\n event NewLiquidationThreshold(\n VToken vToken,\n uint256 oldLiquidationThresholdMantissa,\n uint256 newLiquidationThresholdMantissa\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 an action is paused on a market\n event ActionPausedMarket(VToken vToken, Action action, bool pauseState);\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 the collateral threshold (in USD) for non-batch liquidations is changed\n event NewMinLiquidatableCollateral(uint256 oldMinLiquidatableCollateral, uint256 newMinLiquidatableCollateral);\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 a rewards distributor is added\n event NewRewardsDistributor(address indexed rewardsDistributor, address indexed rewardToken);\n\n /// @notice Emitted when a market is supported\n event MarketSupported(VToken vToken);\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 a market\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\n\n /// @notice Emitted when a market is unlisted\n event MarketUnlisted(address indexed vToken);\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 Thrown when collateral factor exceeds the upper bound\n error InvalidCollateralFactor();\n\n /// @notice Thrown when liquidation threshold exceeds the collateral factor\n error InvalidLiquidationThreshold();\n\n /// @notice Thrown when the action is only available to specific sender, but the real sender was different\n error UnexpectedSender(address expectedSender, address actualSender);\n\n /// @notice Thrown when the oracle returns an invalid price for some asset\n error PriceError(address vToken);\n\n /// @notice Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\n error SnapshotError(address vToken, address user);\n\n /// @notice Thrown when the market is not listed\n error MarketNotListed(address market);\n\n /// @notice Thrown when a market has an unexpected comptroller\n error ComptrollerMismatch();\n\n /// @notice Thrown when user is not member of market\n error MarketNotCollateral(address vToken, address user);\n\n /// @notice Thrown when borrow action is not paused\n error BorrowActionNotPaused();\n\n /// @notice Thrown when mint action is not paused\n error MintActionNotPaused();\n\n /// @notice Thrown when redeem action is not paused\n error RedeemActionNotPaused();\n\n /// @notice Thrown when repay action is not paused\n error RepayActionNotPaused();\n\n /// @notice Thrown when seize action is not paused\n error SeizeActionNotPaused();\n\n /// @notice Thrown when exit market action is not paused\n error ExitMarketActionNotPaused();\n\n /// @notice Thrown when transfer action is not paused\n error TransferActionNotPaused();\n\n /// @notice Thrown when enter market action is not paused\n error EnterMarketActionNotPaused();\n\n /// @notice Thrown when liquidate action is not paused\n error LiquidateActionNotPaused();\n\n /// @notice Thrown when borrow cap is not zero\n error BorrowCapIsNotZero();\n\n /// @notice Thrown when supply cap is not zero\n error SupplyCapIsNotZero();\n\n /// @notice Thrown when collateral factor is not zero\n error CollateralFactorIsNotZero();\n\n /**\n * @notice Thrown during the liquidation if user's total collateral amount is lower than\n * a predefined threshold. In this case only batch liquidations (either liquidateAccount\n * or healAccount) are available.\n */\n error MinimalCollateralViolated(uint256 expectedGreaterThan, uint256 actual);\n error CollateralExceedsThreshold(uint256 expectedLessThanOrEqualTo, uint256 actual);\n error InsufficientCollateral(uint256 collateralToSeize, uint256 availableCollateral);\n\n /// @notice Thrown when the account doesn't have enough liquidity to redeem or borrow\n error InsufficientLiquidity();\n\n /// @notice Thrown when trying to liquidate a healthy account\n error InsufficientShortfall();\n\n /// @notice Thrown when trying to repay more than allowed by close factor\n error TooMuchRepay();\n\n /// @notice Thrown if the user is trying to exit a market in which they have an outstanding debt\n error NonzeroBorrowBalance();\n\n /// @notice Thrown when trying to perform an action that is paused\n error ActionPaused(address market, Action action);\n\n /// @notice Thrown when trying to add a market that is already listed\n error MarketAlreadyListed(address market);\n\n /// @notice Thrown if the supply cap is exceeded\n error SupplyCapExceeded(address market, uint256 cap);\n\n /// @notice Thrown if the borrow cap is exceeded\n error BorrowCapExceeded(address market, uint256 cap);\n\n /// @notice Thrown if delegate approval status is already set to the requested value\n error DelegationStatusUnchanged();\n\n /// @param poolRegistry_ Pool registry address\n /// @custom:oz-upgrades-unsafe-allow constructor\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n constructor(address poolRegistry_) {\n ensureNonzeroAddress(poolRegistry_);\n\n poolRegistry = poolRegistry_;\n _disableInitializers();\n }\n\n /**\n * @param loopLimit Limit for the loops can iterate to avoid the DOS\n * @param accessControlManager Access control manager contract address\n */\n function initialize(uint256 loopLimit, address accessControlManager) external initializer {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager);\n\n _setMaxLoopsLimit(loopLimit);\n }\n\n /**\n * @notice Add assets to be included in account liquidity calculation; enabling them to be used as collateral\n * @param vTokens The list of addresses of the vToken markets to be enabled\n * @return errors An array of NO_ERROR for compatibility with Venus core tooling\n * @custom:event MarketEntered is emitted for each market on success\n * @custom:error ActionPaused error is thrown if entering any of the markets is paused\n * @custom:error MarketNotListed error is thrown if any of the markets is not listed\n * @custom:access Not restricted\n */\n function enterMarkets(address[] memory vTokens) external override returns (uint256[] memory) {\n uint256 len = vTokens.length;\n\n uint256[] memory results = new uint256[](len);\n for (uint256 i; i < len; ++i) {\n VToken vToken = VToken(vTokens[i]);\n\n _addToMarket(vToken, msg.sender);\n results[i] = NO_ERROR;\n }\n\n return results;\n }\n\n /**\n * @notice Unlist a market by setting isListed to false\n * @dev Checks if all actions are paused, borrow/supply caps is set to 0 and collateral factor is to 0.\n * @param market The address of the market (token) to unlist\n * @return uint256 Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event MarketUnlisted is emitted on success\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error BorrowActionNotPaused error is thrown if borrow action is not paused\n * @custom:error MintActionNotPaused error is thrown if mint action is not paused\n * @custom:error RedeemActionNotPaused error is thrown if redeem action is not paused\n * @custom:error RepayActionNotPaused error is thrown if repay action is not paused\n * @custom:error EnterMarketActionNotPaused error is thrown if enter market action is not paused\n * @custom:error LiquidateActionNotPaused error is thrown if liquidate action is not paused\n * @custom:error BorrowCapIsNotZero error is thrown if borrow cap is not zero\n * @custom:error SupplyCapIsNotZero error is thrown if supply cap is not zero\n * @custom:error CollateralFactorIsNotZero error is thrown if collateral factor is not zero\n */\n function unlistMarket(address market) external returns (uint256) {\n _checkAccessAllowed(\"unlistMarket(address)\");\n\n Market storage _market = markets[market];\n\n if (!_market.isListed) {\n revert MarketNotListed(market);\n }\n\n if (!actionPaused(market, Action.BORROW)) {\n revert BorrowActionNotPaused();\n }\n\n if (!actionPaused(market, Action.MINT)) {\n revert MintActionNotPaused();\n }\n\n if (!actionPaused(market, Action.REDEEM)) {\n revert RedeemActionNotPaused();\n }\n\n if (!actionPaused(market, Action.REPAY)) {\n revert RepayActionNotPaused();\n }\n\n if (!actionPaused(market, Action.SEIZE)) {\n revert SeizeActionNotPaused();\n }\n\n if (!actionPaused(market, Action.ENTER_MARKET)) {\n revert EnterMarketActionNotPaused();\n }\n\n if (!actionPaused(market, Action.LIQUIDATE)) {\n revert LiquidateActionNotPaused();\n }\n\n if (!actionPaused(market, Action.TRANSFER)) {\n revert TransferActionNotPaused();\n }\n\n if (!actionPaused(market, Action.EXIT_MARKET)) {\n revert ExitMarketActionNotPaused();\n }\n\n if (borrowCaps[market] != 0) {\n revert BorrowCapIsNotZero();\n }\n\n if (supplyCaps[market] != 0) {\n revert SupplyCapIsNotZero();\n }\n\n if (_market.collateralFactorMantissa != 0) {\n revert CollateralFactorIsNotZero();\n }\n\n _market.isListed = false;\n emit MarketUnlisted(market);\n\n return NO_ERROR;\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 * @custom:event DelegateUpdated emits on success\n * @custom:error ZeroAddressNotAllowed is thrown when delegate address is zero\n * @custom:error DelegationStatusUnchanged is thrown if approval status is already set to the requested value\n * @custom:access Not restricted\n */\n function updateDelegate(address delegate, bool approved) external {\n ensureNonzeroAddress(delegate);\n if (approvedDelegates[msg.sender][delegate] == approved) {\n revert DelegationStatusUnchanged();\n }\n\n approvedDelegates[msg.sender][delegate] = approved;\n emit DelegateUpdated(msg.sender, delegate, approved);\n }\n\n /**\n * @notice Removes asset from sender's account liquidity calculation; disabling them as collateral\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event MarketExited is emitted on success\n * @custom:error ActionPaused error is thrown if exiting the market is paused\n * @custom:error NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function exitMarket(address vTokenAddress) external override returns (uint256) {\n _checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\n VToken vToken = VToken(vTokenAddress);\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\n (uint256 tokensHeld, uint256 amountOwed, ) = _safeGetAccountSnapshot(vToken, msg.sender);\n\n /* Fail if the sender has a borrow balance */\n if (amountOwed != 0) {\n revert NonzeroBorrowBalance();\n }\n\n /* Fail if the sender is not permitted to redeem all of their tokens */\n _checkRedeemAllowed(vTokenAddress, msg.sender, tokensHeld);\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 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 // load into memory for faster iteration\n VToken[] memory userAssetList = accountAssets[msg.sender];\n uint256 len = userAssetList.length;\n\n uint256 assetIndex = len;\n for (uint256 i; i < len; ++i) {\n if (userAssetList[i] == vToken) {\n assetIndex = i;\n break;\n }\n }\n\n // We *must* have found the asset in the list or our redundant data structure is broken\n assert(assetIndex < len);\n\n // copy last item in list to location of item to be removed, reduce length by 1\n VToken[] storage storedList = accountAssets[msg.sender];\n storedList[assetIndex] = storedList[storedList.length - 1];\n storedList.pop();\n\n emit MarketExited(vToken, msg.sender);\n\n return NO_ERROR;\n }\n\n /*** Policy Hooks ***/\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 * @custom:error ActionPaused error is thrown if supplying to this market is paused\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\n * @custom:access Not restricted\n */\n function preMintHook(address vToken, address minter, uint256 mintAmount) external override {\n _checkActionPauseState(vToken, Action.MINT);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n uint256 supplyCap = supplyCaps[vToken];\n // Skipping the cap check for uncapped coins to save some gas\n if (supplyCap != type(uint256).max) {\n uint256 vTokenSupply = VToken(vToken).totalSupply();\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\n if (nextTotalSupply > supplyCap) {\n revert SupplyCapExceeded(vToken, supplyCap);\n }\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, minter);\n }\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external override {\n _checkActionPauseState(vToken, Action.REDEEM);\n\n _checkRedeemAllowed(vToken, redeemer, redeemTokens);\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, redeemer);\n }\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 if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(redeemer, vToken);\n }\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 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 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 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 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 * @custom:error ActionPaused error is thrown if borrowing is paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if there is not enough collateral to borrow\n * @custom:error BorrowCapExceeded is thrown if the borrow cap will be exceeded should this borrow succeed\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted if vToken is enabled as collateral, otherwise only vToken\n */\n /// disable-eslint\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external override {\n _checkActionPauseState(vToken, Action.BORROW);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n if (!markets[vToken].accountMembership[borrower]) {\n // only vTokens may call borrowAllowed if borrower not in market\n _checkSenderIs(vToken);\n\n // attempt to add borrower to the market or revert\n _addToMarket(VToken(msg.sender), borrower);\n }\n\n // Update the prices of tokens\n updatePrices(borrower);\n\n if (oracle.getUnderlyingPrice(vToken) == 0) {\n revert PriceError(address(vToken));\n }\n\n uint256 borrowCap = borrowCaps[vToken];\n // Skipping the cap check for uncapped coins to save some gas\n if (borrowCap != type(uint256).max) {\n uint256 totalBorrows = VToken(vToken).totalBorrows();\n uint256 badDebt = VToken(vToken).badDebt();\n uint256 nextTotalBorrows = totalBorrows + borrowAmount + badDebt;\n if (nextTotalBorrows > borrowCap) {\n revert BorrowCapExceeded(vToken, borrowCap);\n }\n }\n\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n borrower,\n VToken(vToken),\n 0,\n borrowAmount,\n _getCollateralFactor\n );\n\n if (snapshot.shortfall > 0) {\n revert InsufficientLiquidity();\n }\n\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\n }\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 borrower The account which would borrowed the asset\n * @custom:error ActionPaused error is thrown if repayments are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:access Not restricted\n */\n function preRepayHook(address vToken, address borrower) external override {\n _checkActionPauseState(vToken, Action.REPAY);\n\n oracle.updatePrice(vToken);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\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 borrower The address of the borrower\n * @param repayAmount The amount of underlying being repaid\n * @param skipLiquidityCheck Allows the borrow to be liquidated regardless of the account liquidity\n * @custom:error ActionPaused error is thrown if liquidations are paused in this market\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\n * @custom:error TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor\n * @custom:error MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations\n * @custom:error InsufficientShortfall is thrown when trying to liquidate a healthy account\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n */\n function preLiquidateHook(\n address vTokenBorrowed,\n address vTokenCollateral,\n address borrower,\n uint256 repayAmount,\n bool skipLiquidityCheck\n ) external override {\n // Pause Action.LIQUIDATE on BORROWED TOKEN to prevent liquidating it.\n // If we want to pause liquidating to vTokenCollateral, we should pause\n // Action.SEIZE on it\n _checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\n\n // Update the prices of tokens\n updatePrices(borrower);\n\n if (!markets[vTokenBorrowed].isListed) {\n revert MarketNotListed(address(vTokenBorrowed));\n }\n if (!markets[vTokenCollateral].isListed) {\n revert MarketNotListed(address(vTokenCollateral));\n }\n\n uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\n\n /* Allow accounts to be liquidated if it is a forced liquidation */\n if (skipLiquidityCheck || isForcedLiquidationEnabled[vTokenBorrowed]) {\n if (repayAmount > borrowBalance) {\n revert TooMuchRepay();\n }\n return;\n }\n\n /* The borrower must have shortfall and collateral > threshold in order to be liquidatable */\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral <= minLiquidatableCollateral) {\n /* The liquidator should use either liquidateAccount or healAccount */\n revert MinimalCollateralViolated(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n /* The liquidator may not repay more than what is allowed by the closeFactor */\n uint256 maxClose = mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance);\n if (repayAmount > maxClose) {\n revert TooMuchRepay();\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 seizerContract Contract that tries to seize the asset (either borrowed vToken or Comptroller)\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @custom:error ActionPaused error is thrown if seizing this type of collateral is paused\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\n * @custom:error ComptrollerMismatch error is when seizer contract or seized asset belong to different pools\n * @custom:access Not restricted\n */\n function preSeizeHook(\n address vTokenCollateral,\n address seizerContract,\n address liquidator,\n address borrower\n ) external override {\n // Pause Action.SEIZE on COLLATERAL to prevent seizing it.\n // If we want to pause liquidating vTokenBorrowed, we should pause\n // Action.LIQUIDATE on it\n _checkActionPauseState(vTokenCollateral, Action.SEIZE);\n\n Market storage market = markets[vTokenCollateral];\n\n if (!market.isListed) {\n revert MarketNotListed(vTokenCollateral);\n }\n\n if (seizerContract == address(this)) {\n // If Comptroller is the seizer, just check if collateral's comptroller\n // is equal to the current address\n if (address(VToken(vTokenCollateral).comptroller()) != address(this)) {\n revert ComptrollerMismatch();\n }\n } else {\n // If the seizer is not the Comptroller, check that the seizer is a\n // listed market, and that the markets' comptrollers match\n if (!markets[seizerContract].isListed) {\n revert MarketNotListed(seizerContract);\n }\n if (VToken(vTokenCollateral).comptroller() != VToken(seizerContract).comptroller()) {\n revert ComptrollerMismatch();\n }\n }\n\n if (!market.accountMembership[borrower]) {\n revert MarketNotCollateral(vTokenCollateral, borrower);\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vTokenCollateral);\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, borrower);\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, liquidator);\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external override {\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 _checkRedeemAllowed(vToken, src, transferTokens);\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, src);\n rewardsDistributor.distributeSupplierRewardToken(vToken, dst);\n }\n }\n\n /*** Pool-level operations ***/\n\n /**\n * @notice Seizes all the remaining collateral, makes msg.sender repay the existing\n * borrows, and treats the rest of the debt as bad debt (for each market).\n * The sender has to repay a certain percentage of the debt, computed as\n * collateral / (borrows * liquidationIncentive).\n * @param user account to heal\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for healing\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function healAccount(address user) external {\n VToken[] memory userAssets = getAssetsIn(user);\n uint256 userAssetsCount = userAssets.length;\n\n address liquidator = msg.sender;\n {\n ResilientOracleInterface oracle_ = oracle;\n // We need all user's markets to be fresh for the computations to be correct\n for (uint256 i; i < userAssetsCount; ++i) {\n userAssets[i].accrueInterest();\n oracle_.updatePrice(address(userAssets[i]));\n }\n }\n\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(user, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n // percentage = collateral / (borrows * liquidation incentive)\n Exp memory collateral = Exp({ mantissa: snapshot.totalCollateral });\n Exp memory scaledBorrows = mul_(\n Exp({ mantissa: snapshot.borrows }),\n Exp({ mantissa: liquidationIncentiveMantissa })\n );\n\n Exp memory percentage = div_(collateral, scaledBorrows);\n if (lessThanExp(Exp({ mantissa: MANTISSA_ONE }), percentage)) {\n revert CollateralExceedsThreshold(scaledBorrows.mantissa, collateral.mantissa);\n }\n\n for (uint256 i; i < userAssetsCount; ++i) {\n VToken market = userAssets[i];\n\n (uint256 tokens, uint256 borrowBalance, ) = _safeGetAccountSnapshot(market, user);\n uint256 repaymentAmount = mul_ScalarTruncate(percentage, borrowBalance);\n\n // Seize the entire collateral\n if (tokens != 0) {\n market.seize(liquidator, user, tokens);\n }\n // Repay a certain percentage of the borrow, forgive the rest\n if (borrowBalance != 0) {\n market.healBorrow(liquidator, user, repaymentAmount);\n }\n }\n }\n\n /**\n * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than\n * a predefined threshold, and the account collateral can be seized to cover all borrows. If\n * the collateral is higher than the threshold, use regular liquidations. If the collateral is\n * below the threshold, and the account is insolvent, use healAccount.\n * @param borrower the borrower address\n * @param orders an array of liquidation orders\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation\n * @custom:error InsufficientCollateral error is thrown when there is not enough collateral to cover the debt\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function liquidateAccount(address borrower, LiquidationOrder[] calldata orders) external {\n // We will accrue interest and update the oracle prices later during the liquidation\n\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\n // You should use the regular vToken.liquidateBorrow(...) call\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n uint256 collateralToSeize = mul_ScalarTruncate(\n Exp({ mantissa: liquidationIncentiveMantissa }),\n snapshot.borrows\n );\n if (collateralToSeize >= snapshot.totalCollateral) {\n // There is not enough collateral to seize. Use healBorrow to repay some part of the borrow\n // and record bad debt.\n revert InsufficientCollateral(collateralToSeize, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n uint256 ordersCount = orders.length;\n\n _ensureMaxLoops(ordersCount / 2);\n\n for (uint256 i; i < ordersCount; ++i) {\n if (!markets[address(orders[i].vTokenBorrowed)].isListed) {\n revert MarketNotListed(address(orders[i].vTokenBorrowed));\n }\n if (!markets[address(orders[i].vTokenCollateral)].isListed) {\n revert MarketNotListed(address(orders[i].vTokenCollateral));\n }\n\n LiquidationOrder calldata order = orders[i];\n order.vTokenBorrowed.forceLiquidateBorrow(\n msg.sender,\n borrower,\n order.repayAmount,\n order.vTokenCollateral,\n true\n );\n }\n\n VToken[] memory borrowMarkets = getAssetsIn(borrower);\n uint256 marketsCount = borrowMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower);\n require(borrowBalance == 0, \"Nonzero borrow balance after liquidation\");\n }\n }\n\n /**\n * @notice Sets the closeFactor to use when liquidating borrows\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\n * @custom:event Emits NewCloseFactor on success\n * @custom:access Controlled by AccessControlManager\n */\n function setCloseFactor(uint256 newCloseFactorMantissa) external {\n _checkAccessAllowed(\"setCloseFactor(uint256)\");\n require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, \"Close factor greater than maximum close factor\");\n require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, \"Close factor smaller than minimum close factor\");\n\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\n closeFactorMantissa = newCloseFactorMantissa;\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\n }\n\n /**\n * @notice Sets the collateralFactor for a market\n * @dev This function is restricted by the AccessControlManager\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 * @custom:event Emits NewCollateralFactor when collateral factor is updated\n * and NewLiquidationThreshold when liquidation threshold is updated\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InvalidCollateralFactor error is thrown when collateral factor is too high\n * @custom:error InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor\n * @custom:error PriceError is thrown when the oracle returns an invalid price for the asset\n * @custom:access Controlled by AccessControlManager\n */\n function setCollateralFactor(\n VToken vToken,\n uint256 newCollateralFactorMantissa,\n uint256 newLiquidationThresholdMantissa\n ) external {\n _checkAccessAllowed(\"setCollateralFactor(address,uint256,uint256)\");\n\n // Verify market is listed\n Market storage market = markets[address(vToken)];\n if (!market.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n // Check collateral factor <= 0.9\n if (newCollateralFactorMantissa > MAX_COLLATERAL_FACTOR_MANTISSA) {\n revert InvalidCollateralFactor();\n }\n\n // Ensure that liquidation threshold <= 1\n if (newLiquidationThresholdMantissa > MANTISSA_ONE) {\n revert InvalidLiquidationThreshold();\n }\n\n // Ensure that liquidation threshold >= CF\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\n revert InvalidLiquidationThreshold();\n }\n\n // If collateral factor != 0, fail if price == 0\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\n revert PriceError(address(vToken));\n }\n\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\n market.collateralFactorMantissa = newCollateralFactorMantissa;\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\n }\n\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\n emit NewLiquidationThreshold(vToken, oldLiquidationThresholdMantissa, newLiquidationThresholdMantissa);\n }\n }\n\n /**\n * @notice Sets liquidationIncentive\n * @dev This function is restricted by the AccessControlManager\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\n * @custom:event Emits NewLiquidationIncentive on success\n * @custom:access Controlled by AccessControlManager\n */\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external {\n require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, \"liquidation incentive should be greater than 1e18\");\n\n _checkAccessAllowed(\"setLiquidationIncentive(uint256)\");\n\n // Save current value for use in log\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\n\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\n /**\n * @notice Add the market to the markets mapping and set it as listed\n * @dev Only callable by the PoolRegistry\n * @param vToken The address of the market (token) to list\n * @custom:error MarketAlreadyListed is thrown if the market is already listed in this pool\n * @custom:access Only PoolRegistry\n */\n function supportMarket(VToken vToken) external {\n _checkSenderIs(poolRegistry);\n\n if (markets[address(vToken)].isListed) {\n revert MarketAlreadyListed(address(vToken));\n }\n\n require(vToken.isVToken(), \"Comptroller: Invalid vToken\"); // Sanity check to make sure its really a VToken\n\n Market storage newMarket = markets[address(vToken)];\n newMarket.isListed = true;\n newMarket.collateralFactorMantissa = 0;\n newMarket.liquidationThresholdMantissa = 0;\n\n _addMarket(address(vToken));\n\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n rewardsDistributors[i].initializeMarket(address(vToken));\n }\n\n emit MarketSupported(vToken);\n }\n\n /**\n * @notice Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\n * @dev This function is restricted by the AccessControlManager\n * @dev A borrow cap of type(uint256).max corresponds to unlimited borrowing.\n * @dev Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed\n until the total borrows amount goes below the new borrow cap\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 type(uint256).max corresponds to unlimited borrowing.\n * @custom:access Controlled by AccessControlManager\n */\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\n _checkAccessAllowed(\"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 _ensureMaxLoops(numMarkets);\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 * @notice Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\n * @dev This function is restricted by the AccessControlManager\n * @dev A supply cap of type(uint256).max corresponds to unlimited supply.\n * @dev Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed\n until the total supplies amount goes below the new supply cap\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 type(uint256).max corresponds to unlimited supply.\n * @custom:access Controlled by AccessControlManager\n */\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\n _checkAccessAllowed(\"setMarketSupplyCaps(address[],uint256[])\");\n uint256 vTokensCount = vTokens.length;\n\n require(vTokensCount != 0, \"invalid number of markets\");\n require(vTokensCount == newSupplyCaps.length, \"invalid number of markets\");\n\n _ensureMaxLoops(vTokensCount);\n\n for (uint256 i; i < vTokensCount; ++i) {\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\n }\n }\n\n /**\n * @notice Pause/unpause specified actions\n * @dev This function is restricted by the AccessControlManager\n * @param marketsList Markets to pause/unpause the actions on\n * @param actionsList List of action ids to pause/unpause\n * @param paused The new paused state (true=paused, false=unpaused)\n * @custom:access Controlled by AccessControlManager\n */\n function setActionsPaused(VToken[] calldata marketsList, Action[] calldata actionsList, bool paused) external {\n _checkAccessAllowed(\"setActionsPaused(address[],uint256[],bool)\");\n\n uint256 marketsCount = marketsList.length;\n uint256 actionsCount = actionsList.length;\n\n _ensureMaxLoops(marketsCount * actionsCount);\n\n for (uint256 marketIdx; marketIdx < marketsCount; ++marketIdx) {\n for (uint256 actionIdx; actionIdx < actionsCount; ++actionIdx) {\n _setActionPaused(address(marketsList[marketIdx]), actionsList[actionIdx], paused);\n }\n }\n }\n\n /**\n * @notice Set the given collateral threshold for non-batch liquidations. Regular liquidations\n * will fail if the collateral amount is less than this threshold. Liquidators should use batch\n * operations like liquidateAccount or healAccount.\n * @dev This function is restricted by the AccessControlManager\n * @param newMinLiquidatableCollateral The new min liquidatable collateral (in USD).\n * @custom:access Controlled by AccessControlManager\n */\n function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external {\n _checkAccessAllowed(\"setMinLiquidatableCollateral(uint256)\");\n\n uint256 oldMinLiquidatableCollateral = minLiquidatableCollateral;\n minLiquidatableCollateral = newMinLiquidatableCollateral;\n emit NewMinLiquidatableCollateral(oldMinLiquidatableCollateral, newMinLiquidatableCollateral);\n }\n\n /**\n * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor\n * contracts with the same rewardToken, and there could be overlaping among them considering the last reward slot (block or second)\n * @dev Only callable by the admin\n * @param _rewardsDistributor Address of the RewardDistributor contract to add\n * @custom:access Only Governance\n * @custom:event Emits NewRewardsDistributor with distributor address\n */\n function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner {\n require(!rewardsDistributorExists[address(_rewardsDistributor)], \"already exists\");\n\n uint256 rewardsDistributorsLen = rewardsDistributors.length;\n _ensureMaxLoops(rewardsDistributorsLen + 1);\n\n rewardsDistributors.push(_rewardsDistributor);\n rewardsDistributorExists[address(_rewardsDistributor)] = true;\n\n uint256 marketsCount = allMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n _rewardsDistributor.initializeMarket(address(allMarkets[i]));\n }\n\n emit NewRewardsDistributor(address(_rewardsDistributor), address(_rewardsDistributor.rewardToken()));\n }\n\n /**\n * @notice Sets a new price oracle for the Comptroller\n * @dev Only callable by the admin\n * @param newOracle Address of the new price oracle to set\n * @custom:event Emits NewPriceOracle on success\n * @custom:error ZeroAddressNotAllowed is thrown when the new oracle address is zero\n */\n function setPriceOracle(ResilientOracleInterface newOracle) external onlyOwner {\n ensureNonzeroAddress(address(newOracle));\n\n ResilientOracleInterface oldOracle = oracle;\n oracle = newOracle;\n emit NewPriceOracle(oldOracle, newOracle);\n }\n\n /**\n * @notice Set the for loop iteration limit to avoid DOS\n * @param limit Limit for the max loops can execute at a time\n */\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\n _setMaxLoopsLimit(limit);\n }\n\n /**\n * @notice Sets the prime token contract for the comptroller\n * @param _prime Address of the Prime contract\n */\n function setPrimeToken(IPrime _prime) external onlyOwner {\n ensureNonzeroAddress(address(_prime));\n\n emit NewPrimeToken(prime, _prime);\n prime = _prime;\n }\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 * @param vTokenBorrowed Borrowed vToken\n * @param enable Whether to enable forced liquidations\n */\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\n _checkAccessAllowed(\"setForcedLiquidation(address,bool)\");\n ensureNonzeroAddress(vTokenBorrowed);\n\n if (!markets[vTokenBorrowed].isListed) {\n revert MarketNotListed(vTokenBorrowed);\n }\n\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\n }\n\n /**\n * @notice Determine the current account liquidity with respect to liquidation threshold requirements\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\n * @param account The account get liquidity for\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Account liquidity in excess of liquidation threshold requirements,\n * @return shortfall Account shortfall below liquidation threshold requirements\n */\n function getAccountLiquidity(\n address account\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getLiquidationThreshold);\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\n }\n\n /**\n * @notice Determine the current account liquidity with respect to collateral requirements\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\n * @param account The account get liquidity for\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Account liquidity in excess of collateral requirements,\n * @return shortfall Account shortfall below collateral requirements\n */\n function getBorrowingPower(\n address account\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getCollateralFactor);\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\n }\n\n /**\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Hypothetical account liquidity in excess of collateral requirements,\n * @return shortfall 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 error, uint256 liquidity, uint256 shortfall) {\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n account,\n VToken(vTokenModify),\n redeemTokens,\n borrowAmount,\n _getCollateralFactor\n );\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\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 markets The list of market addresses\n */\n function getAllMarkets() external view override returns (VToken[] memory) {\n return allMarkets;\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 /*** Assets You Are In ***/\n\n /**\n * @notice Returns whether the given account is entered in a given market\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 market specified, 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 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 error Always NO_ERROR for compatibility with Venus core tooling\n * @return tokensToSeize Number of vTokenCollateral tokens to be seized in a liquidation\n * @custom:error PriceError if the oracle returns an invalid price\n */\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view override returns (uint256 error, uint256 tokensToSeize) {\n /* Read oracle prices for borrowed and collateral markets */\n uint256 priceBorrowedMantissa = _safeGetUnderlyingPrice(VToken(vTokenBorrowed));\n uint256 priceCollateralMantissa = _safeGetUnderlyingPrice(VToken(vTokenCollateral));\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 uint256 exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\n uint256 seizeTokens;\n Exp memory numerator;\n Exp memory denominator;\n Exp memory ratio;\n\n numerator = mul_(Exp({ mantissa: liquidationIncentiveMantissa }), Exp({ mantissa: priceBorrowedMantissa }));\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\n ratio = div_(numerator, denominator);\n\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\n\n return (NO_ERROR, seizeTokens);\n }\n\n /**\n * @notice Returns reward speed given a vToken\n * @param vToken The vToken to get the reward speeds for\n * @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors\n */\n function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {\n uint256 rewardsDistributorsLength = rewardsDistributors.length;\n rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);\n for (uint256 i; i < rewardsDistributorsLength; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n address rewardToken = address(rewardsDistributor.rewardToken());\n rewardSpeeds[i] = RewardSpeeds({\n rewardToken: rewardToken,\n supplySpeed: rewardsDistributor.rewardTokenSupplySpeeds(vToken),\n borrowSpeed: rewardsDistributor.rewardTokenBorrowSpeeds(vToken)\n });\n }\n return rewardSpeeds;\n }\n\n /**\n * @notice Return all reward distributors for this pool\n * @return Array of RewardDistributor addresses\n */\n function getRewardDistributors() external view returns (RewardsDistributor[] memory) {\n return rewardsDistributors;\n }\n\n /**\n * @notice A marker method that returns true for a valid Comptroller contract\n * @return Always true\n */\n function isComptroller() external pure override returns (bool) {\n return true;\n }\n\n /**\n * @notice Update the prices of all the tokens associated with the provided account\n * @param account Address of the account to get associated tokens with\n */\n function updatePrices(address account) public {\n VToken[] memory vTokens = getAssetsIn(account);\n uint256 vTokensCount = vTokens.length;\n\n ResilientOracleInterface oracle_ = oracle;\n\n for (uint256 i; i < vTokensCount; ++i) {\n oracle_.updatePrice(address(vTokens[i]));\n }\n }\n\n /**\n * @notice Checks if a certain action is paused on a market\n * @param market vToken address\n * @param action Action to check\n * @return paused True if the action is paused otherwise false\n */\n function actionPaused(address market, Action action) public view returns (bool) {\n return _actionPaused[market][action];\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 list with the assets the account has entered\n */\n function getAssetsIn(address account) public 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 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 */\n function _addToMarket(VToken vToken, address borrower) internal {\n _checkActionPauseState(address(vToken), Action.ENTER_MARKET);\n Market storage marketToJoin = markets[address(vToken)];\n\n if (!marketToJoin.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n if (marketToJoin.accountMembership[borrower]) {\n // already joined\n return;\n }\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\n /**\n * @notice Internal function to validate that a market hasn't already been added\n * and if it hasn't adds it\n * @param vToken The market to support\n */\n function _addMarket(address vToken) internal {\n uint256 marketsCount = allMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n if (allMarkets[i] == VToken(vToken)) {\n revert MarketAlreadyListed(vToken);\n }\n }\n allMarkets.push(VToken(vToken));\n marketsCount = allMarkets.length;\n _ensureMaxLoops(marketsCount);\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 _setActionPaused(address market, Action action, bool paused) internal {\n require(markets[market].isListed, \"cannot pause a market that is not listed\");\n _actionPaused[market][action] = paused;\n emit ActionPausedMarket(VToken(market), action, paused);\n }\n\n /**\n * @dev Internal function to check that vTokens can be safely redeemed for the underlying asset.\n * @param vToken Address of the vTokens to redeem\n * @param redeemer Account redeeming the tokens\n * @param redeemTokens The number of tokens to redeem\n */\n function _checkRedeemAllowed(address vToken, address redeemer, uint256 redeemTokens) internal {\n Market storage market = markets[vToken];\n\n if (!market.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\n if (!market.accountMembership[redeemer]) {\n return;\n }\n\n // Update the prices of tokens\n updatePrices(redeemer);\n\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n redeemer,\n VToken(vToken),\n redeemTokens,\n 0,\n _getCollateralFactor\n );\n if (snapshot.shortfall > 0) {\n revert InsufficientLiquidity();\n }\n }\n\n /**\n * @notice Get the total collateral, weighted collateral, borrow balance, liquidity, shortfall\n * @param account The account to get the snapshot for\n * @param weight The function to compute the weight of the collateral – either collateral factor or\n * liquidation threshold. Accepts the address of the vToken and returns the weight as Exp.\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\n * without calculating accumulated interest.\n * @return snapshot Account liquidity snapshot\n */\n function _getCurrentLiquiditySnapshot(\n address account,\n function(VToken) internal view returns (Exp memory) weight\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\n return _getHypotheticalLiquiditySnapshot(account, VToken(address(0)), 0, 0, weight);\n }\n\n /**\n * @notice Determine what the supply/borrow balances 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 weight The function to compute the weight of the collateral – either collateral factor or\n liquidation threshold. Accepts the address of the VToken and returns the weight\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\n * without calculating accumulated interest.\n * @return snapshot Account liquidity snapshot\n */\n function _getHypotheticalLiquiditySnapshot(\n address account,\n VToken vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount,\n function(VToken) internal view returns (Exp memory) weight\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\n // For each asset the account is in\n VToken[] memory assets = getAssetsIn(account);\n uint256 assetsCount = assets.length;\n\n for (uint256 i; i < assetsCount; ++i) {\n VToken asset = assets[i];\n\n // Read the balances and exchange rate from the vToken\n (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) = _safeGetAccountSnapshot(\n asset,\n account\n );\n\n // Get the normalized price of the asset\n Exp memory oraclePrice = Exp({ mantissa: _safeGetUnderlyingPrice(asset) });\n\n // Pre-compute conversion factors from vTokens -> usd\n Exp memory vTokenPrice = mul_(Exp({ mantissa: exchangeRateMantissa }), oraclePrice);\n Exp memory weightedVTokenPrice = mul_(weight(asset), vTokenPrice);\n\n // weightedCollateral += weightedVTokenPrice * vTokenBalance\n snapshot.weightedCollateral = mul_ScalarTruncateAddUInt(\n weightedVTokenPrice,\n vTokenBalance,\n snapshot.weightedCollateral\n );\n\n // totalCollateral += vTokenPrice * vTokenBalance\n snapshot.totalCollateral = mul_ScalarTruncateAddUInt(vTokenPrice, vTokenBalance, snapshot.totalCollateral);\n\n // borrows += oraclePrice * borrowBalance\n snapshot.borrows = mul_ScalarTruncateAddUInt(oraclePrice, borrowBalance, snapshot.borrows);\n\n // Calculate effects of interacting with vTokenModify\n if (asset == vTokenModify) {\n // redeem effect\n // effects += tokensToDenom * redeemTokens\n snapshot.effects = mul_ScalarTruncateAddUInt(weightedVTokenPrice, redeemTokens, snapshot.effects);\n\n // borrow effect\n // effects += oraclePrice * borrowAmount\n snapshot.effects = mul_ScalarTruncateAddUInt(oraclePrice, borrowAmount, snapshot.effects);\n }\n }\n\n uint256 borrowPlusEffects = snapshot.borrows + snapshot.effects;\n // These are safe, as the underflow condition is checked first\n unchecked {\n if (snapshot.weightedCollateral > borrowPlusEffects) {\n snapshot.liquidity = snapshot.weightedCollateral - borrowPlusEffects;\n snapshot.shortfall = 0;\n } else {\n snapshot.liquidity = 0;\n snapshot.shortfall = borrowPlusEffects - snapshot.weightedCollateral;\n }\n }\n\n return snapshot;\n }\n\n /**\n * @dev Retrieves price from oracle for an asset and checks it is nonzero\n * @param asset Address for asset to query price\n * @return Underlying price\n */\n function _safeGetUnderlyingPrice(VToken asset) internal view returns (uint256) {\n uint256 oraclePriceMantissa = oracle.getUnderlyingPrice(address(asset));\n if (oraclePriceMantissa == 0) {\n revert PriceError(address(asset));\n }\n return oraclePriceMantissa;\n }\n\n /**\n * @dev Return collateral factor for a market\n * @param asset Address for asset\n * @return Collateral factor as exponential\n */\n function _getCollateralFactor(VToken asset) internal view returns (Exp memory) {\n return Exp({ mantissa: markets[address(asset)].collateralFactorMantissa });\n }\n\n /**\n * @dev Retrieves liquidation threshold for a market as an exponential\n * @param asset Address for asset to liquidation threshold\n * @return Liquidation threshold as exponential\n */\n function _getLiquidationThreshold(VToken asset) internal view returns (Exp memory) {\n return Exp({ mantissa: markets[address(asset)].liquidationThresholdMantissa });\n }\n\n /**\n * @dev Returns supply and borrow balances of user in vToken, reverts on failure\n * @param vToken Market to query\n * @param user Account address\n * @return vTokenBalance Balance of vTokens, the same as vToken.balanceOf(user)\n * @return borrowBalance Borrowed amount, including the interest\n * @return exchangeRateMantissa Stored exchange rate\n */\n function _safeGetAccountSnapshot(\n VToken vToken,\n address user\n ) internal view returns (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) {\n uint256 err;\n (err, vTokenBalance, borrowBalance, exchangeRateMantissa) = vToken.getAccountSnapshot(user);\n if (err != 0) {\n revert SnapshotError(address(vToken), user);\n }\n return (vTokenBalance, borrowBalance, exchangeRateMantissa);\n }\n\n /// @notice Reverts if the call is not from expectedSender\n /// @param expectedSender Expected transaction sender\n function _checkSenderIs(address expectedSender) internal view {\n if (msg.sender != expectedSender) {\n revert UnexpectedSender(expectedSender, msg.sender);\n }\n }\n\n /// @notice Reverts if a certain action is paused on a market\n /// @param market Market to check\n /// @param action Action to check\n function _checkActionPauseState(address market, Action action) private view {\n if (actionPaused(market, action)) {\n revert ActionPaused(market, action);\n }\n }\n}\n" + }, + "contracts/ComptrollerInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.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\n/**\n * @title ComptrollerInterface\n * @author Venus\n * @notice Interface implemented by the `Comptroller` contract.\n */\ninterface ComptrollerInterface {\n /*** Assets You Are In ***/\n\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\n\n function exitMarket(address vToken) external returns (uint256);\n\n /*** Policy Hooks ***/\n\n function preMintHook(address vToken, address minter, uint256 mintAmount) external;\n\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external;\n\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external;\n\n function preRepayHook(address vToken, address borrower) external;\n\n function preLiquidateHook(\n address vTokenBorrowed,\n address vTokenCollateral,\n address borrower,\n uint256 repayAmount,\n bool skipLiquidityCheck\n ) external;\n\n function preSeizeHook(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower\n ) external;\n\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\n\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\n\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\n\n function repayBorrowVerify(\n address vToken,\n address payer,\n address borrower,\n uint repayAmount,\n uint borrowerIndex\n ) external;\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 seizeVerify(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint seizeTokens\n ) external;\n\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\n\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external;\n\n function isComptroller() external view returns (bool);\n\n /*** Liquidity/Liquidation Calculations ***/\n\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 repayAmount\n ) external view returns (uint256, uint256);\n\n function getAllMarkets() external view returns (VToken[] memory);\n\n function actionPaused(address market, Action action) external view returns (bool);\n}\n\n/**\n * @title ComptrollerViewInterface\n * @author Venus\n * @notice Interface implemented by the `Comptroller` contract, including only some util view functions.\n */\ninterface ComptrollerViewInterface {\n function markets(address) external view returns (bool, uint256);\n\n function oracle() external view returns (ResilientOracleInterface);\n\n function getAssetsIn(address) external view returns (VToken[] memory);\n\n function closeFactorMantissa() external view returns (uint256);\n\n function liquidationIncentiveMantissa() external view returns (uint256);\n\n function minLiquidatableCollateral() external view returns (uint256);\n\n function getRewardDistributors() external view returns (RewardsDistributor[] memory);\n\n function getAllMarkets() external view returns (VToken[] memory);\n\n function borrowCaps(address) external view returns (uint256);\n\n function supplyCaps(address) external view returns (uint256);\n\n function approvedDelegates(address user, address delegate) external view returns (bool);\n}\n" + }, + "contracts/ComptrollerStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.sol\";\nimport { IPrime } from \"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\";\nimport { Action } from \"./ComptrollerInterface.sol\";\n\n/**\n * @title ComptrollerStorage\n * @author Venus\n * @notice Storage layout for the `Comptroller` contract.\n */\ncontract ComptrollerStorage {\n struct LiquidationOrder {\n VToken vTokenCollateral;\n VToken vTokenBorrowed;\n uint256 repayAmount;\n }\n\n struct AccountLiquiditySnapshot {\n uint256 totalCollateral;\n uint256 weightedCollateral;\n uint256 borrows;\n uint256 effects;\n uint256 liquidity;\n uint256 shortfall;\n }\n\n struct RewardSpeeds {\n address rewardToken;\n uint256 supplySpeed;\n uint256 borrowSpeed;\n }\n\n struct Market {\n // Whether or not this market is listed\n bool isListed;\n // 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 uint256 collateralFactorMantissa;\n // 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 uint256 liquidationThresholdMantissa;\n // Per-market mapping of \"accounts in this asset\"\n mapping(address => bool) accountMembership;\n }\n\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 Per-account mapping of \"assets you are in\"\n */\n mapping(address => VToken[]) public accountAssets;\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 /// @notice A list of all markets\n VToken[] public allMarkets;\n\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\n mapping(address => uint256) public borrowCaps;\n\n /// @notice Minimal collateral required for regular (non-batch) liquidations\n uint256 public minLiquidatableCollateral;\n\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\n mapping(address => uint256) public supplyCaps;\n\n /// @notice True if a certain action is paused on a certain market\n mapping(address => mapping(Action => bool)) internal _actionPaused;\n\n // List of Reward Distributors added\n RewardsDistributor[] internal rewardsDistributors;\n\n // Used to check if rewards distributor is added\n mapping(address => bool) internal rewardsDistributorExists;\n\n /// @notice Flag indicating whether forced liquidation enabled for a market\n mapping(address => bool) public isForcedLiquidationEnabled;\n\n uint256 internal constant NO_ERROR = 0;\n\n // closeFactorMantissa must be strictly greater than this value\n uint256 internal constant MIN_CLOSE_FACTOR_MANTISSA = 0.05e18; // 0.05\n\n // closeFactorMantissa must not exceed this value\n uint256 internal constant MAX_CLOSE_FACTOR_MANTISSA = 0.9e18; // 0.9\n\n // No collateralFactorMantissa may exceed this value\n uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.95e18; // 0.95\n\n /// Prime token address\n IPrime public prime;\n\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 /**\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[47] private __gap;\n}\n" + }, + "contracts/ErrorReporter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n/**\n * @title TokenErrorReporter\n * @author Venus\n * @notice Errors that can be thrown by the `VToken` contract.\n */\ncontract TokenErrorReporter {\n uint256 public constant NO_ERROR = 0; // support legacy return codes\n\n error TransferNotAllowed();\n\n error MintFreshnessCheck();\n\n error RedeemFreshnessCheck();\n error RedeemTransferOutNotPossible();\n\n error BorrowFreshnessCheck();\n error BorrowCashNotAvailable();\n error DelegateNotApproved();\n\n error RepayBorrowFreshnessCheck();\n\n error HealBorrowUnauthorized();\n error ForceLiquidateBorrowUnauthorized();\n\n error LiquidateFreshnessCheck();\n error LiquidateCollateralFreshnessCheck();\n error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\n error LiquidateLiquidatorIsBorrower();\n error LiquidateCloseAmountIsZero();\n error LiquidateCloseAmountIsUintMax();\n\n error LiquidateSeizeLiquidatorIsBorrower();\n\n error ProtocolSeizeShareTooBig();\n\n error SetReserveFactorFreshCheck();\n error SetReserveFactorBoundsCheck();\n\n error AddReservesFactorFreshCheck(uint256 actualAddAmount);\n\n error ReduceReservesFreshCheck();\n error ReduceReservesCashNotAvailable();\n error ReduceReservesCashValidation();\n\n error SetInterestRateModelFreshCheck();\n}\n" + }, + "contracts/ExponentialNoError.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from \"./lib/constants.sol\";\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 struct Exp {\n uint256 mantissa;\n }\n\n struct Double {\n uint256 mantissa;\n }\n\n uint256 internal constant EXP_SCALE = EXP_SCALE_;\n uint256 internal constant DOUBLE_SCALE = 1e36;\n uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;\n uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;\n\n /**\n * @dev Truncates the given exp to a whole number value.\n * For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15\n */\n function truncate(Exp memory exp) internal pure returns (uint256) {\n // Note: We are not using careful math here as we're performing a division that cannot fail\n return exp.mantissa / EXP_SCALE;\n }\n\n /**\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\n */\n // solhint-disable-next-line func-name-mixedcase\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\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 // solhint-disable-next-line func-name-mixedcase\n function mul_ScalarTruncateAddUInt(Exp memory a, uint256 scalar, uint256 addend) internal pure returns (uint256) {\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 function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\n require(n <= type(uint224).max, errorMessage);\n return uint224(n);\n }\n\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\n require(n <= type(uint32).max, 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_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a + b;\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_(uint256 a, uint256 b) internal pure returns (uint256) {\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) / EXP_SCALE });\n }\n\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\n return Exp({ mantissa: mul_(a.mantissa, b) });\n }\n\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\n return mul_(a, b.mantissa) / EXP_SCALE;\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) / DOUBLE_SCALE });\n }\n\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: mul_(a.mantissa, b) });\n }\n\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\n return mul_(a, b.mantissa) / DOUBLE_SCALE;\n }\n\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a * b;\n }\n\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });\n }\n\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\n return Exp({ mantissa: div_(a.mantissa, b) });\n }\n\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\n return div_(mul_(a, EXP_SCALE), 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, DOUBLE_SCALE), b.mantissa) });\n }\n\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(a.mantissa, b) });\n }\n\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\n return div_(mul_(a, DOUBLE_SCALE), b.mantissa);\n }\n\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a / b;\n }\n\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });\n }\n}\n" + }, + "contracts/InterestRateModel.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n/**\n * @title Compound's InterestRateModel Interface\n * @author Compound\n */\nabstract contract InterestRateModel {\n /**\n * @notice Calculates the current borrow interest rate per slot (block or second)\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 amount of reserves the market has\n * @param badDebt The amount of badDebt in the market\n * @return The borrow rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\n */\n function getBorrowRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) external view virtual returns (uint256);\n\n /**\n * @notice Calculates the current supply interest rate per slot (block or second)\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 amount of reserves the market has\n * @param reserveFactorMantissa The current reserve factor the market has\n * @param badDebt The amount of badDebt in the market\n * @return The supply rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\n */\n function getSupplyRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 reserveFactorMantissa,\n uint256 badDebt\n ) external view virtual returns (uint256);\n\n /**\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\n * @return Always true\n */\n function isInterestRateModel() external pure virtual returns (bool) {\n return true;\n }\n}\n" + }, + "contracts/Lens/PoolLens.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IERC20Metadata } from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { ExponentialNoError } from \"../ExponentialNoError.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { Action, ComptrollerInterface, ComptrollerViewInterface } from \"../ComptrollerInterface.sol\";\nimport { PoolRegistryInterface } from \"../Pool/PoolRegistryInterface.sol\";\nimport { PoolRegistry } from \"../Pool/PoolRegistry.sol\";\nimport { RewardsDistributor } from \"../Rewards/RewardsDistributor.sol\";\nimport { TimeManagerV8 } from \"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\";\n\n/**\n * @title PoolLens\n * @author Venus\n * @notice The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information\n * for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be\n * looked up for specific pools and markets:\n- the vToken balance of a given user;\n- the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address;\n- the vToken address in a pool for a given asset;\n- a list of all pools that support an asset;\n- the underlying asset price of a vToken;\n- the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\n */\ncontract PoolLens is ExponentialNoError, TimeManagerV8 {\n /**\n * @dev Struct for PoolDetails.\n */\n struct PoolData {\n string name;\n address creator;\n address comptroller;\n uint256 blockPosted;\n uint256 timestampPosted;\n string category;\n string logoURL;\n string description;\n address priceOracle;\n uint256 closeFactor;\n uint256 liquidationIncentive;\n uint256 minLiquidatableCollateral;\n VTokenMetadata[] vTokens;\n }\n\n /**\n * @dev Struct for VToken.\n */\n struct VTokenMetadata {\n address vToken;\n uint256 exchangeRateCurrent;\n uint256 supplyRatePerBlockOrTimestamp;\n uint256 borrowRatePerBlockOrTimestamp;\n uint256 reserveFactorMantissa;\n uint256 supplyCaps;\n uint256 borrowCaps;\n uint256 totalBorrows;\n uint256 totalReserves;\n uint256 totalSupply;\n uint256 totalCash;\n bool isListed;\n uint256 collateralFactorMantissa;\n address underlyingAssetAddress;\n uint256 vTokenDecimals;\n uint256 underlyingDecimals;\n uint256 pausedActions;\n }\n\n /**\n * @dev Struct for VTokenBalance.\n */\n struct VTokenBalances {\n address vToken;\n uint256 balanceOf;\n uint256 borrowBalanceCurrent;\n uint256 balanceOfUnderlying;\n uint256 tokenBalance;\n uint256 tokenAllowance;\n }\n\n /**\n * @dev Struct for underlyingPrice of VToken.\n */\n struct VTokenUnderlyingPrice {\n address vToken;\n uint256 underlyingPrice;\n }\n\n /**\n * @dev Struct with pending reward info for a market.\n */\n struct PendingReward {\n address vTokenAddress;\n uint256 amount;\n }\n\n /**\n * @dev Struct with reward distribution totals for a single reward token and distributor.\n */\n struct RewardSummary {\n address distributorAddress;\n address rewardTokenAddress;\n uint256 totalRewards;\n PendingReward[] pendingRewards;\n }\n\n /**\n * @dev Struct used in RewardDistributor to save last updated market state.\n */\n struct RewardTokenState {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block number or timestamp the index was last updated at\n uint256 blockOrTimestamp;\n // The block number or timestamp at which to stop rewards\n uint256 lastRewardingBlockOrTimestamp;\n }\n\n /**\n * @dev Struct with bad debt of a market denominated\n */\n struct BadDebt {\n address vTokenAddress;\n uint256 badDebtUsd;\n }\n\n /**\n * @dev Struct with bad debt total denominated in usd for a pool and an array of BadDebt structs for each market\n */\n struct BadDebtSummary {\n address comptroller;\n uint256 totalBadDebtUsd;\n BadDebt[] badDebts;\n }\n\n /// @notice Address of the core pool comptroller (all markets are returned for this pool, including paused ones)\n address public immutable corePoolComptroller;\n\n /**\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\n * @param blocksPerYear_ The number of blocks per year\n * @param corePoolComptroller_ The address of the core pool comptroller\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor(\n bool timeBased_,\n uint256 blocksPerYear_,\n address corePoolComptroller_\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\n corePoolComptroller = corePoolComptroller_;\n }\n\n /**\n * @notice Queries the user's supply/borrow balances in vTokens\n * @param vTokens The list of vToken addresses\n * @param account The user Account\n * @return A list of structs containing balances data\n */\n function vTokenBalancesAll(VToken[] calldata vTokens, address account) external returns (VTokenBalances[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenBalances[] memory res = new VTokenBalances[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenBalances(vTokens[i], account);\n }\n return res;\n }\n\n /**\n * @notice Queries all pools with addtional details for each of them\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @return Arrays of all Venus pools' data\n */\n function getAllPools(address poolRegistryAddress) external view returns (PoolData[] memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n PoolRegistry.VenusPool[] memory venusPools = poolRegistryInterface.getAllPools();\n uint256 poolLength = venusPools.length;\n\n PoolData[] memory poolDataItems = new PoolData[](poolLength);\n\n for (uint256 i; i < poolLength; ++i) {\n PoolRegistry.VenusPool memory venusPool = venusPools[i];\n PoolData memory poolData = getPoolDataFromVenusPool(poolRegistryAddress, venusPool);\n poolDataItems[i] = poolData;\n }\n\n return poolDataItems;\n }\n\n /**\n * @notice Queries the details of a pool identified by Comptroller address\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param comptroller The Comptroller implementation address\n * @return PoolData structure containing the details of the pool\n */\n function getPoolByComptroller(\n address poolRegistryAddress,\n address comptroller\n ) external view returns (PoolData memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return getPoolDataFromVenusPool(poolRegistryAddress, poolRegistryInterface.getPoolByComptroller(comptroller));\n }\n\n /**\n * @notice Returns vToken holding the specified underlying asset in the specified pool\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param comptroller The pool comptroller\n * @param asset The underlyingAsset of VToken\n * @return Address of the vToken\n */\n function getVTokenForAsset(\n address poolRegistryAddress,\n address comptroller,\n address asset\n ) external view returns (address) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return poolRegistryInterface.getVTokenForAsset(comptroller, asset);\n }\n\n /**\n * @notice Returns all pools that support the specified underlying asset\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param asset The underlying asset of vToken\n * @return A list of Comptroller contracts\n */\n function getPoolsSupportedByAsset(\n address poolRegistryAddress,\n address asset\n ) external view returns (address[] memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return poolRegistryInterface.getPoolsSupportedByAsset(asset);\n }\n\n /**\n * @notice Returns the price data for the underlying assets of the specified vTokens\n * @param vTokens The list of vToken addresses\n * @return An array containing the price data for each asset\n */\n function vTokenUnderlyingPriceAll(\n VToken[] calldata vTokens\n ) external view returns (VTokenUnderlyingPrice[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenUnderlyingPrice[] memory res = new VTokenUnderlyingPrice[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenUnderlyingPrice(vTokens[i]);\n }\n return res;\n }\n\n /**\n * @notice Returns the pending rewards for a user for a given pool.\n * @param account The user account.\n * @param comptrollerAddress address\n * @return Pending rewards array\n */\n function getPendingRewards(\n address account,\n address comptrollerAddress\n ) external view returns (RewardSummary[] memory) {\n VToken[] memory markets = _getMarkets(ComptrollerInterface(comptrollerAddress));\n RewardsDistributor[] memory rewardsDistributors = ComptrollerViewInterface(comptrollerAddress)\n .getRewardDistributors();\n RewardSummary[] memory rewardSummary = new RewardSummary[](rewardsDistributors.length);\n for (uint256 i; i < rewardsDistributors.length; ++i) {\n RewardSummary memory reward;\n reward.distributorAddress = address(rewardsDistributors[i]);\n reward.rewardTokenAddress = address(rewardsDistributors[i].rewardToken());\n reward.totalRewards = rewardsDistributors[i].rewardTokenAccrued(account);\n reward.pendingRewards = _calculateNotDistributedAwards(account, markets, rewardsDistributors[i]);\n rewardSummary[i] = reward;\n }\n return rewardSummary;\n }\n\n /**\n * @notice Returns a summary of a pool's bad debt broken down by market\n *\n * @param comptrollerAddress Address of the comptroller\n *\n * @return badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and\n * a break down of bad debt by market\n */\n function getPoolBadDebt(address comptrollerAddress) external view returns (BadDebtSummary memory) {\n uint256 totalBadDebtUsd;\n\n // Get every listed market in the pool\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\n VToken[] memory markets = _getMarkets(ComptrollerInterface(comptrollerAddress));\n ResilientOracleInterface priceOracle = comptroller.oracle();\n\n BadDebt[] memory badDebts = new BadDebt[](markets.length);\n\n BadDebtSummary memory badDebtSummary;\n badDebtSummary.comptroller = comptrollerAddress;\n badDebtSummary.badDebts = badDebts;\n\n // // Calculate the bad debt is USD per market\n for (uint256 i; i < markets.length; ++i) {\n BadDebt memory badDebt;\n badDebt.vTokenAddress = address(markets[i]);\n badDebt.badDebtUsd =\n (VToken(address(markets[i])).badDebt() * priceOracle.getUnderlyingPrice(address(markets[i]))) /\n EXP_SCALE;\n badDebtSummary.badDebts[i] = badDebt;\n totalBadDebtUsd = totalBadDebtUsd + badDebt.badDebtUsd;\n }\n\n badDebtSummary.totalBadDebtUsd = totalBadDebtUsd;\n\n return badDebtSummary;\n }\n\n /**\n * @notice Queries the user's supply/borrow balances in the specified vToken\n * @param vToken vToken address\n * @param account The user Account\n * @return A struct containing the balances data\n */\n function vTokenBalances(VToken vToken, address account) public returns (VTokenBalances memory) {\n uint256 balanceOf = vToken.balanceOf(account);\n uint256 borrowBalanceCurrent = vToken.borrowBalanceCurrent(account);\n uint256 balanceOfUnderlying = vToken.balanceOfUnderlying(account);\n uint256 tokenBalance;\n uint256 tokenAllowance;\n\n IERC20 underlying = IERC20(vToken.underlying());\n tokenBalance = underlying.balanceOf(account);\n tokenAllowance = underlying.allowance(account, address(vToken));\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 Queries additional information for the pool\n * @param poolRegistryAddress Address of the PoolRegistry\n * @param venusPool The VenusPool Object from PoolRegistry\n * @return Enriched PoolData\n */\n function getPoolDataFromVenusPool(\n address poolRegistryAddress,\n PoolRegistry.VenusPool memory venusPool\n ) public view returns (PoolData memory) {\n // Get tokens in the Pool\n ComptrollerInterface comptrollerInstance = ComptrollerInterface(venusPool.comptroller);\n\n VToken[] memory vTokens = _getMarkets(comptrollerInstance);\n\n VTokenMetadata[] memory vTokenMetadataItems = vTokenMetadataAll(vTokens);\n\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n\n PoolRegistry.VenusPoolMetaData memory venusPoolMetaData = poolRegistryInterface.getVenusPoolMetadata(\n venusPool.comptroller\n );\n\n ComptrollerViewInterface comptrollerViewInstance = ComptrollerViewInterface(venusPool.comptroller);\n\n PoolData memory poolData = PoolData({\n name: venusPool.name,\n creator: venusPool.creator,\n comptroller: venusPool.comptroller,\n blockPosted: venusPool.blockPosted,\n timestampPosted: venusPool.timestampPosted,\n category: venusPoolMetaData.category,\n logoURL: venusPoolMetaData.logoURL,\n description: venusPoolMetaData.description,\n vTokens: vTokenMetadataItems,\n priceOracle: address(comptrollerViewInstance.oracle()),\n closeFactor: comptrollerViewInstance.closeFactorMantissa(),\n liquidationIncentive: comptrollerViewInstance.liquidationIncentiveMantissa(),\n minLiquidatableCollateral: comptrollerViewInstance.minLiquidatableCollateral()\n });\n\n return poolData;\n }\n\n /**\n * @notice Returns the metadata of VToken\n * @param vToken The address of vToken\n * @return VTokenMetadata struct\n */\n function vTokenMetadata(VToken vToken) public view returns (VTokenMetadata memory) {\n uint256 exchangeRateCurrent = vToken.exchangeRateStored();\n address comptrollerAddress = address(vToken.comptroller());\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\n (bool isListed, uint256 collateralFactorMantissa) = comptroller.markets(address(vToken));\n\n address underlyingAssetAddress = vToken.underlying();\n uint256 underlyingDecimals = IERC20Metadata(underlyingAssetAddress).decimals();\n\n uint256 pausedActions;\n for (uint8 i; i <= uint8(type(Action).max); ++i) {\n uint256 paused = ComptrollerInterface(comptrollerAddress).actionPaused(address(vToken), Action(i)) ? 1 : 0;\n pausedActions |= paused << i;\n }\n\n uint256 supplyRatePerBlock;\n\n if (vToken.totalSupply() > 0) {\n supplyRatePerBlock = vToken.supplyRatePerBlock();\n }\n\n return\n VTokenMetadata({\n vToken: address(vToken),\n exchangeRateCurrent: exchangeRateCurrent,\n supplyRatePerBlockOrTimestamp: supplyRatePerBlock,\n borrowRatePerBlockOrTimestamp: vToken.borrowRatePerBlock(),\n reserveFactorMantissa: vToken.reserveFactorMantissa(),\n supplyCaps: comptroller.supplyCaps(address(vToken)),\n borrowCaps: comptroller.borrowCaps(address(vToken)),\n totalBorrows: vToken.totalBorrows(),\n totalReserves: vToken.totalReserves(),\n totalSupply: vToken.totalSupply(),\n totalCash: vToken.getCash(),\n isListed: isListed,\n collateralFactorMantissa: collateralFactorMantissa,\n underlyingAssetAddress: underlyingAssetAddress,\n vTokenDecimals: vToken.decimals(),\n underlyingDecimals: underlyingDecimals,\n pausedActions: pausedActions\n });\n }\n\n /**\n * @notice Returns the metadata of all VTokens\n * @param vTokens The list of vToken addresses\n * @return An array of VTokenMetadata structs\n */\n function vTokenMetadataAll(VToken[] memory vTokens) public view returns (VTokenMetadata[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenMetadata[] memory res = new VTokenMetadata[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenMetadata(vTokens[i]);\n }\n return res;\n }\n\n /**\n * @notice Returns the price data for the underlying asset of the specified vToken\n * @param vToken vToken address\n * @return The price data for each asset\n */\n function vTokenUnderlyingPrice(VToken vToken) public view returns (VTokenUnderlyingPrice memory) {\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(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 Returns markets from a comptroller. For the core pool, all markets are returned.\n * For other pools, markets with zero internalCash are filtered.\n * @param comptroller The comptroller to query\n * @return An array of VToken addresses\n */\n function _getMarkets(ComptrollerInterface comptroller) internal view returns (VToken[] memory) {\n VToken[] memory allMarkets = comptroller.getAllMarkets();\n\n if (address(comptroller) == corePoolComptroller) {\n return allMarkets;\n }\n\n // Single-loop filter: pack active markets to the front of allMarkets\n uint256 count;\n uint256 len = allMarkets.length;\n for (uint256 i; i < len; ++i) {\n if (allMarkets[i].internalCash() > 0) {\n allMarkets[count] = allMarkets[i];\n ++count;\n }\n }\n\n // Trim the array to the active count\n assembly {\n mstore(allMarkets, count)\n }\n\n return allMarkets;\n }\n\n function _calculateNotDistributedAwards(\n address account,\n VToken[] memory markets,\n RewardsDistributor rewardsDistributor\n ) internal view returns (PendingReward[] memory) {\n PendingReward[] memory pendingRewards = new PendingReward[](markets.length);\n\n for (uint256 i; i < markets.length; ++i) {\n // Market borrow and supply state we will modify update in-memory, in order to not modify storage\n RewardTokenState memory borrowState;\n RewardTokenState memory supplyState;\n\n if (isTimeBased) {\n (\n borrowState.index,\n borrowState.blockOrTimestamp,\n borrowState.lastRewardingBlockOrTimestamp\n ) = rewardsDistributor.rewardTokenBorrowStateTimeBased(address(markets[i]));\n (\n supplyState.index,\n supplyState.blockOrTimestamp,\n supplyState.lastRewardingBlockOrTimestamp\n ) = rewardsDistributor.rewardTokenSupplyStateTimeBased(address(markets[i]));\n } else {\n (\n borrowState.index,\n borrowState.blockOrTimestamp,\n borrowState.lastRewardingBlockOrTimestamp\n ) = rewardsDistributor.rewardTokenBorrowState(address(markets[i]));\n (\n supplyState.index,\n supplyState.blockOrTimestamp,\n supplyState.lastRewardingBlockOrTimestamp\n ) = rewardsDistributor.rewardTokenSupplyState(address(markets[i]));\n }\n\n Exp memory marketBorrowIndex = Exp({ mantissa: markets[i].borrowIndex() });\n\n // Update market supply and borrow index in-memory\n updateMarketBorrowIndex(address(markets[i]), rewardsDistributor, borrowState, marketBorrowIndex);\n updateMarketSupplyIndex(address(markets[i]), rewardsDistributor, supplyState);\n\n // Calculate pending rewards\n uint256 borrowReward = calculateBorrowerReward(\n address(markets[i]),\n rewardsDistributor,\n account,\n borrowState,\n marketBorrowIndex\n );\n uint256 supplyReward = calculateSupplierReward(\n address(markets[i]),\n rewardsDistributor,\n account,\n supplyState\n );\n\n PendingReward memory pendingReward;\n pendingReward.vTokenAddress = address(markets[i]);\n pendingReward.amount = borrowReward + supplyReward;\n pendingRewards[i] = pendingReward;\n }\n return pendingRewards;\n }\n\n function updateMarketBorrowIndex(\n address vToken,\n RewardsDistributor rewardsDistributor,\n RewardTokenState memory borrowState,\n Exp memory marketBorrowIndex\n ) internal view {\n uint256 borrowSpeed = rewardsDistributor.rewardTokenBorrowSpeeds(vToken);\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n if (\n borrowState.lastRewardingBlockOrTimestamp > 0 &&\n blockNumberOrTimestamp > borrowState.lastRewardingBlockOrTimestamp\n ) {\n blockNumberOrTimestamp = borrowState.lastRewardingBlockOrTimestamp;\n }\n\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, borrowState.blockOrTimestamp);\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\n // Remove the total earned interest rate since the opening of the market from total borrows\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, borrowSpeed);\n Double memory ratio = borrowAmount > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\n } else if (deltaBlocksOrTimestamp > 0) {\n borrowState.blockOrTimestamp = blockNumberOrTimestamp;\n }\n }\n\n function updateMarketSupplyIndex(\n address vToken,\n RewardsDistributor rewardsDistributor,\n RewardTokenState memory supplyState\n ) internal view {\n uint256 supplySpeed = rewardsDistributor.rewardTokenSupplySpeeds(vToken);\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n if (\n supplyState.lastRewardingBlockOrTimestamp > 0 &&\n blockNumberOrTimestamp > supplyState.lastRewardingBlockOrTimestamp\n ) {\n blockNumberOrTimestamp = supplyState.lastRewardingBlockOrTimestamp;\n }\n\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, supplyState.blockOrTimestamp);\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\n uint256 supplyTokens = VToken(vToken).totalSupply();\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, supplySpeed);\n Double memory ratio = supplyTokens > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\n } else if (deltaBlocksOrTimestamp > 0) {\n supplyState.blockOrTimestamp = blockNumberOrTimestamp;\n }\n }\n\n function calculateBorrowerReward(\n address vToken,\n RewardsDistributor rewardsDistributor,\n address borrower,\n RewardTokenState memory borrowState,\n Exp memory marketBorrowIndex\n ) internal view returns (uint256) {\n Double memory borrowIndex = Double({ mantissa: borrowState.index });\n Double memory borrowerIndex = Double({\n mantissa: rewardsDistributor.rewardTokenBorrowerIndex(vToken, borrower)\n });\n if (borrowerIndex.mantissa == 0 && borrowIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\n // Covers the case where users borrowed tokens before the market's borrow state index was set\n borrowerIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\n }\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\n return borrowerDelta;\n }\n\n function calculateSupplierReward(\n address vToken,\n RewardsDistributor rewardsDistributor,\n address supplier,\n RewardTokenState memory supplyState\n ) internal view returns (uint256) {\n Double memory supplyIndex = Double({ mantissa: supplyState.index });\n Double memory supplierIndex = Double({\n mantissa: rewardsDistributor.rewardTokenSupplierIndex(vToken, supplier)\n });\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\n // Covers the case where users supplied tokens before the market's supply state index was set\n supplierIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\n }\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\n return supplierDelta;\n }\n}\n" + }, + "contracts/lib/constants.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\n/// @dev The approximate number of seconds per year\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\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" + }, + "contracts/lib/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 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" + }, + "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" + }, + "contracts/Pool/PoolRegistry.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\n\nimport { PoolRegistryInterface } from \"./PoolRegistryInterface.sol\";\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { ensureNonzeroAddress } from \"../lib/validators.sol\";\n\n/**\n * @title PoolRegistry\n * @author Venus\n * @notice The Isolated Pools architecture centers around the `PoolRegistry` contract. The `PoolRegistry` maintains a directory of isolated lending\n * pools and can perform actions like creating and registering new pools, adding new markets to existing pools, setting and updating the pool's required\n * metadata, and providing the getter methods to get information on the pools.\n *\n * Isolated lending has three main components: PoolRegistry, pools, and markets. The PoolRegistry is responsible for managing pools.\n * It can create new pools, update pool metadata and manage markets within pools. PoolRegistry contains getter methods to get the details of\n * any existing pool like `getVTokenForAsset` and `getPoolsSupportedByAsset`. It also contains methods for updating pool metadata (`updatePoolMetadata`)\n * and setting pool name (`setPoolName`).\n *\n * The directory of pools is managed through two mappings: `_poolByComptroller` which is a hashmap with the comptroller address as the key and `VenusPool` as\n * the value and `_poolsByID` which is an array of comptroller addresses. Individual pools can be accessed by calling `getPoolByComptroller` with the pool's\n * comptroller address. `_poolsByID` is used to iterate through all of the pools.\n *\n * PoolRegistry also contains a map of asset addresses called `_supportedPools` that maps to an array of assets suppored by each pool. This array of pools by\n * asset is retrieved by calling `getPoolsSupportedByAsset`.\n *\n * PoolRegistry registers new isolated pools in the directory with the `createRegistryPool` method. Isolated pools are composed of independent markets with\n * specific assets and custom risk management configurations according to their markets.\n */\ncontract PoolRegistry is Ownable2StepUpgradeable, AccessControlledV8, PoolRegistryInterface {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n struct AddMarketInput {\n VToken vToken;\n uint256 collateralFactor;\n uint256 liquidationThreshold;\n uint256 initialSupply;\n address vTokenReceiver;\n uint256 supplyCap;\n uint256 borrowCap;\n }\n\n uint256 internal constant MAX_POOL_NAME_LENGTH = 100;\n\n /**\n * @notice Maps pool's comptroller address to metadata.\n */\n mapping(address => VenusPoolMetaData) public metadata;\n\n /**\n * @dev Maps pool ID to pool's comptroller address\n */\n mapping(uint256 => address) private _poolsByID;\n\n /**\n * @dev Total number of pools created.\n */\n uint256 private _numberOfPools;\n\n /**\n * @dev Maps comptroller address to Venus pool Index.\n */\n mapping(address => VenusPool) private _poolByComptroller;\n\n /**\n * @dev Maps pool's comptroller address to asset to vToken.\n */\n mapping(address => mapping(address => address)) private _vTokens;\n\n /**\n * @dev Maps asset to list of supported pools.\n */\n mapping(address => address[]) private _supportedPools;\n\n /**\n * @notice Emitted when a new Venus pool is added to the directory.\n */\n event PoolRegistered(address indexed comptroller, VenusPool pool);\n\n /**\n * @notice Emitted when a pool name is set.\n */\n event PoolNameSet(address indexed comptroller, string oldName, string newName);\n\n /**\n * @notice Emitted when a pool metadata is updated.\n */\n event PoolMetadataUpdated(\n address indexed comptroller,\n VenusPoolMetaData oldMetadata,\n VenusPoolMetaData newMetadata\n );\n\n /**\n * @notice Emitted when a Market is added to the pool.\n */\n event MarketAdded(address indexed comptroller, address indexed vTokenAddress);\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the deployer to owner\n * @param accessControlManager_ AccessControlManager contract address\n */\n function initialize(address accessControlManager_) external initializer {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n }\n\n /**\n * @notice Adds a new Venus pool to the directory\n * @dev Price oracle must be configured before adding a pool\n * @param name The name of the pool\n * @param comptroller Pool's Comptroller contract\n * @param closeFactor The pool's close factor (scaled by 1e18)\n * @param liquidationIncentive The pool's liquidation incentive (scaled by 1e18)\n * @param minLiquidatableCollateral Minimal collateral for regular (non-batch) liquidations flow\n * @return index The index of the registered Venus pool\n * @custom:error ZeroAddressNotAllowed is thrown when Comptroller address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\n */\n function addPool(\n string calldata name,\n Comptroller comptroller,\n uint256 closeFactor,\n uint256 liquidationIncentive,\n uint256 minLiquidatableCollateral\n ) external virtual returns (uint256 index) {\n _checkAccessAllowed(\"addPool(string,address,uint256,uint256,uint256)\");\n // Input validation\n ensureNonzeroAddress(address(comptroller));\n ensureNonzeroAddress(address(comptroller.oracle()));\n\n uint256 poolId = _registerPool(name, address(comptroller));\n\n // Set Venus pool parameters\n comptroller.setCloseFactor(closeFactor);\n comptroller.setLiquidationIncentive(liquidationIncentive);\n comptroller.setMinLiquidatableCollateral(minLiquidatableCollateral);\n\n return poolId;\n }\n\n /**\n * @notice Add a market to an existing pool and then mint to provide initial supply\n * @param input The structure describing the parameters for adding a market to a pool\n * @custom:error ZeroAddressNotAllowed is thrown when vToken address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when vTokenReceiver address is zero\n */\n function addMarket(AddMarketInput memory input) external {\n _checkAccessAllowed(\"addMarket(AddMarketInput)\");\n ensureNonzeroAddress(address(input.vToken));\n ensureNonzeroAddress(input.vTokenReceiver);\n require(input.initialSupply > 0, \"PoolRegistry: initialSupply is zero\");\n\n VToken vToken = input.vToken;\n address vTokenAddress = address(vToken);\n address comptrollerAddress = address(vToken.comptroller());\n Comptroller comptroller = Comptroller(comptrollerAddress);\n address underlyingAddress = vToken.underlying();\n IERC20Upgradeable underlying = IERC20Upgradeable(underlyingAddress);\n\n require(_poolByComptroller[comptrollerAddress].creator != address(0), \"PoolRegistry: Pool not registered\");\n // solhint-disable-next-line reason-string\n require(\n _vTokens[comptrollerAddress][underlyingAddress] == address(0),\n \"PoolRegistry: Market already added for asset comptroller combination\"\n );\n\n comptroller.supportMarket(vToken);\n comptroller.setCollateralFactor(vToken, input.collateralFactor, input.liquidationThreshold);\n\n uint256[] memory newSupplyCaps = new uint256[](1);\n uint256[] memory newBorrowCaps = new uint256[](1);\n VToken[] memory vTokens = new VToken[](1);\n\n newSupplyCaps[0] = input.supplyCap;\n newBorrowCaps[0] = input.borrowCap;\n vTokens[0] = vToken;\n\n comptroller.setMarketSupplyCaps(vTokens, newSupplyCaps);\n comptroller.setMarketBorrowCaps(vTokens, newBorrowCaps);\n\n _vTokens[comptrollerAddress][underlyingAddress] = vTokenAddress;\n _supportedPools[underlyingAddress].push(comptrollerAddress);\n\n uint256 amountToSupply = _transferIn(underlying, msg.sender, input.initialSupply);\n underlying.forceApprove(vTokenAddress, 0);\n underlying.forceApprove(vTokenAddress, amountToSupply);\n vToken.mintBehalf(input.vTokenReceiver, amountToSupply);\n\n emit MarketAdded(comptrollerAddress, vTokenAddress);\n }\n\n /**\n * @notice Modify existing Venus pool name\n * @param comptroller Pool's Comptroller\n * @param name New pool name\n */\n function setPoolName(address comptroller, string calldata name) external {\n _checkAccessAllowed(\"setPoolName(address,string)\");\n _ensureValidName(name);\n VenusPool storage pool = _poolByComptroller[comptroller];\n string memory oldName = pool.name;\n pool.name = name;\n emit PoolNameSet(comptroller, oldName, name);\n }\n\n /**\n * @notice Update metadata of an existing pool\n * @param comptroller Pool's Comptroller\n * @param metadata_ New pool metadata\n */\n function updatePoolMetadata(address comptroller, VenusPoolMetaData calldata metadata_) external {\n _checkAccessAllowed(\"updatePoolMetadata(address,VenusPoolMetaData)\");\n VenusPoolMetaData memory oldMetadata = metadata[comptroller];\n metadata[comptroller] = metadata_;\n emit PoolMetadataUpdated(comptroller, oldMetadata, metadata_);\n }\n\n /**\n * @notice Returns arrays of all Venus pools' data\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\n * @return A list of all pools within PoolRegistry, with details for each pool\n */\n function getAllPools() external view override returns (VenusPool[] memory) {\n uint256 numberOfPools_ = _numberOfPools; // storage load to save gas\n VenusPool[] memory _pools = new VenusPool[](numberOfPools_);\n for (uint256 i = 1; i <= numberOfPools_; ++i) {\n address comptroller = _poolsByID[i];\n _pools[i - 1] = (_poolByComptroller[comptroller]);\n }\n return _pools;\n }\n\n /**\n * @param comptroller The comptroller proxy address associated to the pool\n * @return Returns Venus pool\n */\n function getPoolByComptroller(address comptroller) external view override returns (VenusPool memory) {\n return _poolByComptroller[comptroller];\n }\n\n /**\n * @param comptroller comptroller of Venus pool\n * @return Returns Metadata of Venus pool\n */\n function getVenusPoolMetadata(address comptroller) external view override returns (VenusPoolMetaData memory) {\n return metadata[comptroller];\n }\n\n function getVTokenForAsset(address comptroller, address asset) external view override returns (address) {\n return _vTokens[comptroller][asset];\n }\n\n function getPoolsSupportedByAsset(address asset) external view override returns (address[] memory) {\n return _supportedPools[asset];\n }\n\n /**\n * @dev Adds a new Venus pool to the directory (without checking msg.sender).\n * @param name The name of the pool\n * @param comptroller The pool's Comptroller proxy contract address\n * @return The index of the registered Venus pool\n */\n function _registerPool(string calldata name, address comptroller) internal returns (uint256) {\n VenusPool storage storedPool = _poolByComptroller[comptroller];\n\n require(storedPool.creator == address(0), \"PoolRegistry: Pool already exists in the directory.\");\n _ensureValidName(name);\n\n ++_numberOfPools;\n uint256 numberOfPools_ = _numberOfPools; // cache on stack to save storage read gas\n\n VenusPool memory pool = VenusPool(name, msg.sender, comptroller, block.number, block.timestamp);\n\n _poolsByID[numberOfPools_] = comptroller;\n _poolByComptroller[comptroller] = pool;\n\n emit PoolRegistered(comptroller, pool);\n return numberOfPools_;\n }\n\n function _transferIn(IERC20Upgradeable token, address from, uint256 amount) internal returns (uint256) {\n uint256 balanceBefore = token.balanceOf(address(this));\n token.safeTransferFrom(from, address(this), amount);\n uint256 balanceAfter = token.balanceOf(address(this));\n return balanceAfter - balanceBefore;\n }\n\n function _ensureValidName(string calldata name) internal pure {\n require(bytes(name).length <= MAX_POOL_NAME_LENGTH, \"Pool's name is too large\");\n }\n}\n" + }, + "contracts/Pool/PoolRegistryInterface.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 /**\n * @notice Struct for a Venus interest rate pool metadata.\n */\n struct VenusPoolMetaData {\n string category;\n string logoURL;\n string description;\n }\n\n /// @notice Get all pools in PoolRegistry\n function getAllPools() external view returns (VenusPool[] memory);\n\n /// @notice Get a pool by comptroller address\n function getPoolByComptroller(address comptroller) external view returns (VenusPool memory);\n\n /// @notice Get the address of the VToken contract in the Pool where the underlying token is the provided 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 /// @notice Get the metadata of a Pool by comptroller address\n function getVenusPoolMetadata(address comptroller) external view returns (VenusPoolMetaData memory);\n}\n" + }, + "contracts/Rewards/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\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 { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { TimeManagerV8 } from \"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\";\n\nimport { ExponentialNoError } from \"../ExponentialNoError.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { MaxLoopsLimitHelper } from \"../MaxLoopsLimitHelper.sol\";\nimport { RewardsDistributorStorage } from \"./RewardsDistributorStorage.sol\";\n\n/**\n * @title `RewardsDistributor`\n * @author Venus\n * @notice Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol.\n * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward\n * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool.\n * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward\n * token to be released each slot (block or second) for borrowers and suppliers, which is distributed based on a user’s percentage of the borrows or supplies\n * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting\n * their contributor reward token speed, which similarly allocates a fixed amount of reward token per slot (block or second).\n *\n * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed\n * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized\n * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\n */\ncontract RewardsDistributor is\n ExponentialNoError,\n Ownable2StepUpgradeable,\n AccessControlledV8,\n MaxLoopsLimitHelper,\n RewardsDistributorStorage,\n TimeManagerV8\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice The initial REWARD TOKEN index for a market\n uint224 public constant INITIAL_INDEX = 1e36;\n\n /// @notice Emitted when REWARD TOKEN is distributed to a supplier\n event DistributedSupplierRewardToken(\n VToken indexed vToken,\n address indexed supplier,\n uint256 rewardTokenDelta,\n uint256 rewardTokenTotal,\n uint256 rewardTokenSupplyIndex\n );\n\n /// @notice Emitted when REWARD TOKEN is distributed to a borrower\n event DistributedBorrowerRewardToken(\n VToken indexed vToken,\n address indexed borrower,\n uint256 rewardTokenDelta,\n uint256 rewardTokenTotal,\n uint256 rewardTokenBorrowIndex\n );\n\n /// @notice Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\n event RewardTokenSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /// @notice Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\n event RewardTokenBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /// @notice Emitted when REWARD TOKEN is granted by admin\n event RewardTokenGranted(address indexed recipient, uint256 amount);\n\n /// @notice Emitted when a new REWARD TOKEN speed is set for a contributor\n event ContributorRewardTokenSpeedUpdated(address indexed contributor, uint256 newSpeed);\n\n /// @notice Emitted when a market is initialized\n event MarketInitialized(address indexed vToken);\n\n /// @notice Emitted when a reward token supply index is updated\n event RewardTokenSupplyIndexUpdated(address indexed vToken);\n\n /// @notice Emitted when a reward token borrow index is updated\n event RewardTokenBorrowIndexUpdated(address indexed vToken, Exp marketBorrowIndex);\n\n /// @notice Emitted when a reward for contributor is updated\n event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued);\n\n /// @notice Emitted when a reward token last rewarding block for supply is updated\n event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\n\n /// @notice Emitted when a reward token last rewarding block for borrow is updated\n event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\n\n /// @notice Emitted when a reward token last rewarding timestamp for supply is updated\n event SupplyLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\n\n /// @notice Emitted when a reward token last rewarding timestamp for borrow is updated\n event BorrowLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\n\n modifier onlyComptroller() {\n require(address(comptroller) == msg.sender, \"Only comptroller can call this function\");\n _;\n }\n\n /**\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\n * @param blocksPerYear_ The number of blocks per year\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /**\n * @notice RewardsDistributor initializer\n * @dev Initializes the deployer to owner\n * @param comptroller_ Comptroller to attach the reward distributor to\n * @param rewardToken_ Reward token to distribute\n * @param loopsLimit_ Maximum number of iterations for the loops in this contract\n * @param accessControlManager_ AccessControlManager contract address\n */\n function initialize(\n Comptroller comptroller_,\n IERC20Upgradeable rewardToken_,\n uint256 loopsLimit_,\n address accessControlManager_\n ) external initializer {\n comptroller = comptroller_;\n rewardToken = rewardToken_;\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n\n _setMaxLoopsLimit(loopsLimit_);\n }\n\n /**\n * @notice Initializes the market state for a specific vToken\n * @param vToken The address of the vToken to be initialized\n * @custom:event MarketInitialized emits on success\n * @custom:access Only Comptroller\n */\n function initializeMarket(address vToken) external onlyComptroller {\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n isTimeBased\n ? _initializeMarketTimestampBased(vToken, blockNumberOrTimestamp)\n : _initializeMarketBlockBased(vToken, safe32(blockNumberOrTimestamp, \"block number exceeds 32 bits\"));\n\n emit MarketInitialized(vToken);\n }\n\n /*** Reward Token Distribution ***/\n\n /**\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them\n * Borrowers will begin to accrue after the first interaction with the protocol.\n * @dev This function should only be called when the user has a borrow position in the market\n * (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook)\n * We avoid an external call to check if they are in the market to save gas because this function is called in many places\n * @param vToken The market in which the borrower is interacting\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\n * @param marketBorrowIndex The current global borrow index of vToken\n */\n function distributeBorrowerRewardToken(\n address vToken,\n address borrower,\n Exp memory marketBorrowIndex\n ) external onlyComptroller {\n _distributeBorrowerRewardToken(vToken, borrower, marketBorrowIndex);\n }\n\n function updateRewardTokenSupplyIndex(address vToken) external onlyComptroller {\n _updateRewardTokenSupplyIndex(vToken);\n }\n\n /**\n * @notice Transfer REWARD TOKEN to the recipient\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\n * @param recipient The address of the recipient to transfer REWARD TOKEN to\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\n */\n function grantRewardToken(address recipient, uint256 amount) external onlyOwner {\n uint256 amountLeft = _grantRewardToken(recipient, amount);\n require(amountLeft == 0, \"insufficient rewardToken for grant\");\n emit RewardTokenGranted(recipient, amount);\n }\n\n function updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) external onlyComptroller {\n _updateRewardTokenBorrowIndex(vToken, marketBorrowIndex);\n }\n\n /**\n * @notice Set REWARD TOKEN borrow and supply speeds for the specified markets\n * @param vTokens The markets whose REWARD TOKEN speed to update\n * @param supplySpeeds New supply-side REWARD TOKEN speed for the corresponding market\n * @param borrowSpeeds New borrow-side REWARD TOKEN speed for the corresponding market\n */\n function setRewardTokenSpeeds(\n VToken[] memory vTokens,\n uint256[] memory supplySpeeds,\n uint256[] memory borrowSpeeds\n ) external {\n _checkAccessAllowed(\"setRewardTokenSpeeds(address[],uint256[],uint256[])\");\n uint256 numTokens = vTokens.length;\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \"invalid setRewardTokenSpeeds\");\n\n for (uint256 i; i < numTokens; ++i) {\n _setRewardTokenSpeed(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\n }\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding block for the specified markets, used when contract is block based\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\n * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market\n * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market\n */\n function setLastRewardingBlocks(\n VToken[] calldata vTokens,\n uint32[] calldata supplyLastRewardingBlocks,\n uint32[] calldata borrowLastRewardingBlocks\n ) external {\n _checkAccessAllowed(\"setLastRewardingBlocks(address[],uint32[],uint32[])\");\n require(!isTimeBased, \"Block-based operation only\");\n\n uint256 numTokens = vTokens.length;\n require(\n numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length,\n \"RewardsDistributor::setLastRewardingBlocks invalid input\"\n );\n\n for (uint256 i; i < numTokens; ) {\n _setLastRewardingBlock(vTokens[i], supplyLastRewardingBlocks[i], borrowLastRewardingBlocks[i]);\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding block timestamp for the specified markets, used when contract is time based\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\n * @param supplyLastRewardingBlockTimestamps New supply-side REWARD TOKEN last rewarding block timestamp for the corresponding market\n * @param borrowLastRewardingBlockTimestamps New borrow-side REWARD TOKEN last rewarding block timestamp for the corresponding market\n */\n function setLastRewardingBlockTimestamps(\n VToken[] calldata vTokens,\n uint256[] calldata supplyLastRewardingBlockTimestamps,\n uint256[] calldata borrowLastRewardingBlockTimestamps\n ) external {\n _checkAccessAllowed(\"setLastRewardingBlockTimestamps(address[],uint256[],uint256[])\");\n require(isTimeBased, \"Time-based operation only\");\n\n uint256 numTokens = vTokens.length;\n require(\n numTokens == supplyLastRewardingBlockTimestamps.length &&\n numTokens == borrowLastRewardingBlockTimestamps.length,\n \"RewardsDistributor::setLastRewardingBlockTimestamps invalid input\"\n );\n\n for (uint256 i; i < numTokens; ) {\n _setLastRewardingBlockTimestamp(\n vTokens[i],\n supplyLastRewardingBlockTimestamps[i],\n borrowLastRewardingBlockTimestamps[i]\n );\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Set REWARD TOKEN speed for a single contributor\n * @param contributor The contributor whose REWARD TOKEN speed to update\n * @param rewardTokenSpeed New REWARD TOKEN speed for contributor\n */\n function setContributorRewardTokenSpeed(address contributor, uint256 rewardTokenSpeed) external onlyOwner {\n // note that REWARD TOKEN speed could be set to 0 to halt liquidity rewards for a contributor\n updateContributorRewards(contributor);\n if (rewardTokenSpeed == 0) {\n // release storage\n delete lastContributorBlock[contributor];\n } else {\n lastContributorBlock[contributor] = getBlockNumberOrTimestamp();\n }\n rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed;\n\n emit ContributorRewardTokenSpeedUpdated(contributor, rewardTokenSpeed);\n }\n\n function distributeSupplierRewardToken(address vToken, address supplier) external onlyComptroller {\n _distributeSupplierRewardToken(vToken, supplier);\n }\n\n /**\n * @notice Claim all the rewardToken accrued by holder in all markets\n * @param holder The address to claim REWARD TOKEN for\n */\n function claimRewardToken(address holder) external {\n return claimRewardToken(holder, comptroller.getAllMarkets());\n }\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) external onlyOwner {\n _setMaxLoopsLimit(limit);\n }\n\n /**\n * @notice Calculate additional accrued REWARD TOKEN for a contributor since last accrual\n * @param contributor The address to calculate contributor rewards for\n */\n function updateContributorRewards(address contributor) public {\n uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor];\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, lastContributorBlock[contributor]);\n if (deltaBlocksOrTimestamp > 0 && rewardTokenSpeed > 0) {\n uint256 newAccrued = mul_(deltaBlocksOrTimestamp, rewardTokenSpeed);\n uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued);\n\n rewardTokenAccrued[contributor] = contributorAccrued;\n lastContributorBlock[contributor] = blockNumberOrTimestamp;\n\n emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]);\n }\n }\n\n /**\n * @notice Claim all the rewardToken accrued by holder in the specified markets\n * @param holder The address to claim REWARD TOKEN for\n * @param vTokens The list of markets to claim REWARD TOKEN in\n */\n function claimRewardToken(address holder, VToken[] memory vTokens) public {\n uint256 vTokensCount = vTokens.length;\n\n _ensureMaxLoops(vTokensCount);\n\n for (uint256 i; i < vTokensCount; ++i) {\n VToken vToken = vTokens[i];\n require(comptroller.isMarketListed(vToken), \"market must be listed\");\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\n _distributeBorrowerRewardToken(address(vToken), holder, borrowIndex);\n _updateRewardTokenSupplyIndex(address(vToken));\n _distributeSupplierRewardToken(address(vToken), holder);\n }\n rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]);\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding block for a single market.\n * @param vToken market's whose reward token last rewarding block to be updated\n * @param supplyLastRewardingBlock New supply-side REWARD TOKEN last rewarding block for market\n * @param borrowLastRewardingBlock New borrow-side REWARD TOKEN last rewarding block for market\n */\n function _setLastRewardingBlock(\n VToken vToken,\n uint32 supplyLastRewardingBlock,\n uint32 borrowLastRewardingBlock\n ) internal {\n require(comptroller.isMarketListed(vToken), \"rewardToken market is not listed\");\n\n uint256 blockNumber = getBlockNumberOrTimestamp();\n\n require(supplyLastRewardingBlock > blockNumber, \"setting last rewarding block in the past is not allowed\");\n require(borrowLastRewardingBlock > blockNumber, \"setting last rewarding block in the past is not allowed\");\n\n uint32 currentSupplyLastRewardingBlock = rewardTokenSupplyState[address(vToken)].lastRewardingBlock;\n uint32 currentBorrowLastRewardingBlock = rewardTokenBorrowState[address(vToken)].lastRewardingBlock;\n\n require(\n currentSupplyLastRewardingBlock == 0 || currentSupplyLastRewardingBlock > blockNumber,\n \"this RewardsDistributor is already locked\"\n );\n require(\n currentBorrowLastRewardingBlock == 0 || currentBorrowLastRewardingBlock > blockNumber,\n \"this RewardsDistributor is already locked\"\n );\n\n if (currentSupplyLastRewardingBlock != supplyLastRewardingBlock) {\n rewardTokenSupplyState[address(vToken)].lastRewardingBlock = supplyLastRewardingBlock;\n emit SupplyLastRewardingBlockUpdated(address(vToken), supplyLastRewardingBlock);\n }\n\n if (currentBorrowLastRewardingBlock != borrowLastRewardingBlock) {\n rewardTokenBorrowState[address(vToken)].lastRewardingBlock = borrowLastRewardingBlock;\n emit BorrowLastRewardingBlockUpdated(address(vToken), borrowLastRewardingBlock);\n }\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding timestamp for a single market.\n * @param vToken market's whose reward token last rewarding timestamp to be updated\n * @param supplyLastRewardingBlockTimestamp New supply-side REWARD TOKEN last rewarding timestamp for market\n * @param borrowLastRewardingBlockTimestamp New borrow-side REWARD TOKEN last rewarding timestamp for market\n */\n function _setLastRewardingBlockTimestamp(\n VToken vToken,\n uint256 supplyLastRewardingBlockTimestamp,\n uint256 borrowLastRewardingBlockTimestamp\n ) internal {\n require(comptroller.isMarketListed(vToken), \"rewardToken market is not listed\");\n\n uint256 blockTimestamp = getBlockNumberOrTimestamp();\n\n require(\n supplyLastRewardingBlockTimestamp > blockTimestamp,\n \"setting last rewarding timestamp in the past is not allowed\"\n );\n require(\n borrowLastRewardingBlockTimestamp > blockTimestamp,\n \"setting last rewarding timestamp in the past is not allowed\"\n );\n\n uint256 currentSupplyLastRewardingBlockTimestamp = rewardTokenSupplyStateTimeBased[address(vToken)]\n .lastRewardingTimestamp;\n uint256 currentBorrowLastRewardingBlockTimestamp = rewardTokenBorrowStateTimeBased[address(vToken)]\n .lastRewardingTimestamp;\n\n require(\n currentSupplyLastRewardingBlockTimestamp == 0 || currentSupplyLastRewardingBlockTimestamp > blockTimestamp,\n \"this RewardsDistributor is already locked\"\n );\n require(\n currentBorrowLastRewardingBlockTimestamp == 0 || currentBorrowLastRewardingBlockTimestamp > blockTimestamp,\n \"this RewardsDistributor is already locked\"\n );\n\n if (currentSupplyLastRewardingBlockTimestamp != supplyLastRewardingBlockTimestamp) {\n rewardTokenSupplyStateTimeBased[address(vToken)].lastRewardingTimestamp = supplyLastRewardingBlockTimestamp;\n emit SupplyLastRewardingBlockTimestampUpdated(address(vToken), supplyLastRewardingBlockTimestamp);\n }\n\n if (currentBorrowLastRewardingBlockTimestamp != borrowLastRewardingBlockTimestamp) {\n rewardTokenBorrowStateTimeBased[address(vToken)].lastRewardingTimestamp = borrowLastRewardingBlockTimestamp;\n emit BorrowLastRewardingBlockTimestampUpdated(address(vToken), borrowLastRewardingBlockTimestamp);\n }\n }\n\n /**\n * @notice Set REWARD TOKEN speed for a single market.\n * @param vToken market's whose reward token rate to be updated\n * @param supplySpeed New supply-side REWARD TOKEN speed for market\n * @param borrowSpeed New borrow-side REWARD TOKEN speed for market\n */\n function _setRewardTokenSpeed(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\n require(comptroller.isMarketListed(vToken), \"rewardToken market is not listed\");\n\n if (rewardTokenSupplySpeeds[address(vToken)] != supplySpeed) {\n // Supply speed updated so let's update supply state to ensure that\n // 1. REWARD TOKEN accrued properly for the old speed, and\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\n _updateRewardTokenSupplyIndex(address(vToken));\n\n // Update speed and emit event\n rewardTokenSupplySpeeds[address(vToken)] = supplySpeed;\n emit RewardTokenSupplySpeedUpdated(vToken, supplySpeed);\n }\n\n if (rewardTokenBorrowSpeeds[address(vToken)] != borrowSpeed) {\n // Borrow speed updated so let's update borrow state to ensure that\n // 1. REWARD TOKEN accrued properly for the old speed, and\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\n\n // Update speed and emit event\n rewardTokenBorrowSpeeds[address(vToken)] = borrowSpeed;\n emit RewardTokenBorrowSpeedUpdated(vToken, borrowSpeed);\n }\n }\n\n /**\n * @notice Calculate REWARD TOKEN 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 REWARD TOKEN to\n */\n function _distributeSupplierRewardToken(address vToken, address supplier) internal {\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\n\n uint256 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\n uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier];\n\n // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN\n rewardTokenSupplierIndex[vToken][supplier] = supplyIndex;\n\n if (supplierIndex == 0 && supplyIndex >= INITIAL_INDEX) {\n // Covers the case where users supplied tokens before the market's supply state index was set.\n // Rewards the user with REWARD TOKEN accrued from the start of when supplier rewards were first\n // set for the market.\n supplierIndex = INITIAL_INDEX;\n }\n\n // Calculate change in the cumulative sum of the REWARD TOKEN per vToken accrued\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\n\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\n\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerVToken\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\n\n uint256 supplierAccrued = add_(rewardTokenAccrued[supplier], supplierDelta);\n rewardTokenAccrued[supplier] = supplierAccrued;\n\n emit DistributedSupplierRewardToken(VToken(vToken), supplier, supplierDelta, supplierAccrued, supplyIndex);\n }\n\n /**\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them.\n * @param vToken The market in which the borrower is interacting\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\n * @param marketBorrowIndex The current global borrow index of vToken\n */\n function _distributeBorrowerRewardToken(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\n\n uint256 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\n uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower];\n\n // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN\n rewardTokenBorrowerIndex[vToken][borrower] = borrowIndex;\n\n if (borrowerIndex == 0 && borrowIndex >= INITIAL_INDEX) {\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\n // Rewards the user with REWARD TOKEN accrued from the start of when borrower rewards were first\n // set for the market.\n borrowerIndex = INITIAL_INDEX;\n }\n\n // Calculate change in the cumulative sum of the REWARD TOKEN per borrowed unit accrued\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\n\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\n\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerBorrowedUnit\n if (borrowerAmount != 0) {\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\n\n uint256 borrowerAccrued = add_(rewardTokenAccrued[borrower], borrowerDelta);\n rewardTokenAccrued[borrower] = borrowerAccrued;\n\n emit DistributedBorrowerRewardToken(VToken(vToken), borrower, borrowerDelta, borrowerAccrued, borrowIndex);\n }\n }\n\n /**\n * @notice Transfer REWARD TOKEN to the user.\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all.\n * @param user The address of the user to transfer REWARD TOKEN to\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\n * @return The amount of REWARD TOKEN which was NOT transferred to the user\n */\n function _grantRewardToken(address user, uint256 amount) internal returns (uint256) {\n uint256 rewardTokenRemaining = rewardToken.balanceOf(address(this));\n if (amount > 0 && amount <= rewardTokenRemaining) {\n rewardToken.safeTransfer(user, amount);\n return 0;\n }\n return amount;\n }\n\n /**\n * @notice Accrue REWARD TOKEN to the market by updating the supply index\n * @param vToken The market whose supply index to update\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\n */\n function _updateRewardTokenSupplyIndex(address vToken) internal {\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\n\n uint256 supplySpeed = rewardTokenSupplySpeeds[vToken];\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n if (!isTimeBased) {\n safe32(blockNumberOrTimestamp, \"block number exceeds 32 bits\");\n }\n\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\n ? supplyStateTimeBased.lastRewardingTimestamp\n : uint256(supplyState.lastRewardingBlock);\n\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\n }\n\n uint256 deltaBlocksOrTimestamp = sub_(\n blockNumberOrTimestamp,\n (isTimeBased ? supplyStateTimeBased.timestamp : uint256(supplyState.block))\n );\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\n uint256 supplyTokens = VToken(vToken).totalSupply();\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, supplySpeed);\n Double memory ratio = supplyTokens > 0\n ? fraction(accruedSinceUpdate, supplyTokens)\n : Double({ mantissa: 0 });\n uint224 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\n uint224 index = safe224(\n add_(Double({ mantissa: supplyIndex }), ratio).mantissa,\n \"new index exceeds 224 bits\"\n );\n\n if (isTimeBased) {\n supplyStateTimeBased.index = index;\n supplyStateTimeBased.timestamp = blockNumberOrTimestamp;\n } else {\n supplyState.index = index;\n supplyState.block = uint32(blockNumberOrTimestamp);\n }\n } else if (deltaBlocksOrTimestamp > 0) {\n isTimeBased ? supplyStateTimeBased.timestamp = blockNumberOrTimestamp : supplyState.block = uint32(\n blockNumberOrTimestamp\n );\n }\n\n emit RewardTokenSupplyIndexUpdated(vToken);\n }\n\n /**\n * @notice Accrue REWARD TOKEN to the market by updating the borrow index\n * @param vToken The market whose borrow index to update\n * @param marketBorrowIndex The current global borrow index of vToken\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\n */\n function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\n\n uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken];\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n if (!isTimeBased) {\n safe32(blockNumberOrTimestamp, \"block number exceeds 32 bits\");\n }\n\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\n ? borrowStateTimeBased.lastRewardingTimestamp\n : uint256(borrowState.lastRewardingBlock);\n\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\n }\n\n uint256 deltaBlocksOrTimestamp = sub_(\n blockNumberOrTimestamp,\n (isTimeBased ? borrowStateTimeBased.timestamp : uint256(borrowState.block))\n );\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, borrowSpeed);\n Double memory ratio = borrowAmount > 0\n ? fraction(accruedSinceUpdate, borrowAmount)\n : Double({ mantissa: 0 });\n uint224 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\n uint224 index = safe224(\n add_(Double({ mantissa: borrowIndex }), ratio).mantissa,\n \"new index exceeds 224 bits\"\n );\n\n if (isTimeBased) {\n borrowStateTimeBased.index = index;\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\n } else {\n borrowState.index = index;\n borrowState.block = uint32(blockNumberOrTimestamp);\n }\n } else if (deltaBlocksOrTimestamp > 0) {\n if (isTimeBased) {\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\n } else {\n borrowState.block = uint32(blockNumberOrTimestamp);\n }\n }\n\n emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex);\n }\n\n /**\n * @notice Initializes the market state for a specific vToken called when contract is block-based\n * @param vToken The address of the vToken to be initialized\n * @param blockNumber current block number\n */\n function _initializeMarketBlockBased(address vToken, uint32 blockNumber) internal {\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n RewardToken storage borrowState = rewardTokenBorrowState[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 = INITIAL_INDEX;\n }\n\n if (borrowState.index == 0) {\n // Initialize borrow state index with default value\n borrowState.index = INITIAL_INDEX;\n }\n\n /*\n * Update market state block numbers\n */\n supplyState.block = borrowState.block = blockNumber;\n }\n\n /**\n * @notice Initializes the market state for a specific vToken called when contract is time-based\n * @param vToken The address of the vToken to be initialized\n * @param blockTimestamp current block timestamp\n */\n function _initializeMarketTimestampBased(address vToken, uint256 blockTimestamp) internal {\n TimeBasedRewardToken storage supplyState = rewardTokenSupplyStateTimeBased[vToken];\n TimeBasedRewardToken storage borrowState = rewardTokenBorrowStateTimeBased[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 = INITIAL_INDEX;\n }\n\n if (borrowState.index == 0) {\n // Initialize borrow state index with default value\n borrowState.index = INITIAL_INDEX;\n }\n\n /*\n * Update market state block timestamp\n */\n supplyState.timestamp = borrowState.timestamp = blockTimestamp;\n }\n}\n" + }, + "contracts/Rewards/RewardsDistributorStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\nimport { Comptroller } from \"../Comptroller.sol\";\n\n/**\n * @title RewardsDistributorStorage\n * @author Venus\n * @dev Storage for RewardsDistributor\n */\ncontract RewardsDistributorStorage {\n struct RewardToken {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block number the index was last updated at\n uint32 block;\n // The block number at which to stop rewards\n uint32 lastRewardingBlock;\n }\n\n struct TimeBasedRewardToken {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block timestamp the index was last updated at\n uint256 timestamp;\n // The block timestamp at which to stop rewards\n uint256 lastRewardingTimestamp;\n }\n\n /// @notice The REWARD TOKEN market supply state for each market\n mapping(address => RewardToken) public rewardTokenSupplyState;\n\n /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\n mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex;\n\n /// @notice The REWARD TOKEN accrued but not yet transferred to each user\n mapping(address => uint256) public rewardTokenAccrued;\n\n /// @notice The rate at which rewardToken is distributed to the corresponding borrow market per slot (block or second)\n mapping(address => uint256) public rewardTokenBorrowSpeeds;\n\n /// @notice The rate at which rewardToken is distributed to the corresponding supply market per slot (block or second)\n mapping(address => uint256) public rewardTokenSupplySpeeds;\n\n /// @notice The REWARD TOKEN market borrow state for each market\n mapping(address => RewardToken) public rewardTokenBorrowState;\n\n /// @notice The portion of REWARD TOKEN that each contributor receives per slot (block or second)\n mapping(address => uint256) public rewardTokenContributorSpeeds;\n\n /// @notice Last slot (block or second) at which a contributor's REWARD TOKEN rewards have been allocated\n mapping(address => uint256) public lastContributorBlock;\n\n /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\n mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex;\n\n Comptroller internal comptroller;\n\n IERC20Upgradeable public rewardToken;\n\n /// @notice The REWARD TOKEN market supply state for each market\n mapping(address => TimeBasedRewardToken) public rewardTokenSupplyStateTimeBased;\n\n /// @notice The REWARD TOKEN market borrow state for each market\n mapping(address => TimeBasedRewardToken) public rewardTokenBorrowStateTimeBased;\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[37] private __gap;\n}\n" + }, + "contracts/VToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\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 { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { IProtocolShareReserve } from \"@venusprotocol/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\";\n\nimport { VTokenInterface } from \"./VTokenInterfaces.sol\";\nimport { ComptrollerInterface, ComptrollerViewInterface } from \"./ComptrollerInterface.sol\";\nimport { TokenErrorReporter } from \"./ErrorReporter.sol\";\nimport { InterestRateModel } from \"./InterestRateModel.sol\";\nimport { ExponentialNoError } from \"./ExponentialNoError.sol\";\nimport { TimeManagerV8 } from \"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\";\nimport { ensureNonzeroAddress } from \"./lib/validators.sol\";\n\n/**\n * @title VToken\n * @author Venus\n * @notice Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview,\n * each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of\n * the pool. The main actions a user regularly interacts with in a market are:\n\n- mint/redeem of vTokens;\n- transfer of vTokens;\n- borrow/repay a loan on an underlying asset;\n- liquidate a borrow or liquidate/heal an account.\n\n * A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`.\n * The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted\n * `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken`\n * as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that\n * a user may borrow up to a portion of their collateral determined by the market’s collateral factor. However, if their borrowed amount exceeds an amount\n * calculated using the market’s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also\n * pay off interest accrued on the borrow.\n * \n * The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller`\n * and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a\n * total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`.\n * Both functions settle all of an account’s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of\n * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\n */\ncontract VToken is\n Ownable2StepUpgradeable,\n AccessControlledV8,\n VTokenInterface,\n ExponentialNoError,\n TokenErrorReporter,\n TimeManagerV8\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5%\n\n // Maximum fraction of interest that can be set aside for reserves\n uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18;\n\n // Maximum borrow rate that can ever be applied per slot(block or second)\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n uint256 internal immutable MAX_BORROW_RATE_MANTISSA;\n\n /**\n * Reentrancy Guard **\n */\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 * @param timeBased_ A boolean indicating whether the contract is based on time or block.\n * @param blocksPerYear_ The number of blocks per year\n * @param maxBorrowRateMantissa_ The maximum value of borrowing rate mantissa\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor(\n bool timeBased_,\n uint256 blocksPerYear_,\n uint256 maxBorrowRateMantissa_\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n require(maxBorrowRateMantissa_ <= 1e18, \"Max borrow rate must be <= 1e18\");\n\n MAX_BORROW_RATE_MANTISSA = maxBorrowRateMantissa_;\n _disableInitializers();\n }\n\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_ ERC-20 name of this token\n * @param symbol_ ERC-20 symbol of this token\n * @param decimals_ ERC-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param accessControlManager_ AccessControlManager contract address\n * @param riskManagement Addresses of risk & income related contracts\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\n * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\n */\n function initialize(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address admin_,\n address accessControlManager_,\n RiskManagementInit memory riskManagement,\n uint256 reserveFactorMantissa_\n ) external initializer {\n ensureNonzeroAddress(admin_);\n\n // Initialize the market\n _initialize(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_,\n accessControlManager_,\n riskManagement,\n reserveFactorMantissa_\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 * @return success True if the transfer succeeded, reverts otherwise\n * @custom:event Emits Transfer event on success\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\n * @custom:access Not restricted\n */\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\n _transferTokens(msg.sender, msg.sender, dst, amount);\n return true;\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 success True if the transfer succeeded, reverts otherwise\n * @custom:event Emits Transfer event on success\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\n * @custom:access Not restricted\n */\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\n _transferTokens(msg.sender, src, dst, amount);\n return true;\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 (uint256.max means infinite)\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function approve(address spender, uint256 amount) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n transferAllowances[src][spender] = amount;\n emit Approval(src, spender, amount);\n return true;\n }\n\n /**\n * @notice Increase approval for `spender`\n * @param spender The address of the account which may transfer tokens\n * @param addedValue The number of additional tokens spender can transfer\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function increaseAllowance(address spender, uint256 addedValue) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n uint256 newAllowance = transferAllowances[src][spender];\n newAllowance += addedValue;\n transferAllowances[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n return true;\n }\n\n /**\n * @notice Decreases approval for `spender`\n * @param spender The address of the account which may transfer tokens\n * @param subtractedValue The number of tokens to remove from total approval\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n uint256 currentAllowance = transferAllowances[src][spender];\n require(currentAllowance >= subtractedValue, \"decreased allowance below zero\");\n unchecked {\n currentAllowance -= subtractedValue;\n }\n\n transferAllowances[src][spender] = currentAllowance;\n\n emit Approval(src, spender, currentAllowance);\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 amount The amount of underlying owned by `owner`\n */\n function balanceOfUnderlying(address owner) external override returns (uint256) {\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\n return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\n }\n\n /**\n * @notice Returns the current total borrows plus accrued interest\n * @return totalBorrows The total borrows with interest\n */\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\n accrueInterest();\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 borrowBalance The calculated balance\n */\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\n accrueInterest();\n return _borrowBalanceStored(account);\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function mint(uint256 mintAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _mintFresh(msg.sender, msg.sender, mintAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param minter User whom the supply will be attributed to\n * @param mintAmount The amount of the underlying asset to supply\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when minter address is zero\n */\n function mintBehalf(address minter, uint256 mintAmount) external override nonReentrant returns (uint256) {\n ensureNonzeroAddress(minter);\n\n accrueInterest();\n\n _mintFresh(msg.sender, minter, mintAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\n * @custom:access Not restricted\n */\n function redeem(uint256 redeemTokens) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _redeemFresh(msg.sender, msg.sender, redeemTokens, 0);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function redeemBehalf(address redeemer, uint256 redeemTokens) external override nonReentrant returns (uint256) {\n _ensureSenderIsDelegateOf(redeemer);\n\n accrueInterest();\n\n _redeemFresh(redeemer, msg.sender, redeemTokens, 0);\n return NO_ERROR;\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 receive from redeeming vTokens\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n */\n function redeemUnderlying(uint256 redeemAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _redeemFresh(msg.sender, msg.sender, 0, redeemAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function redeemUnderlyingBehalf(\n address redeemer,\n uint256 redeemAmount\n ) external override nonReentrant returns (uint256) {\n _ensureSenderIsDelegateOf(redeemer);\n\n accrueInterest();\n\n _redeemFresh(redeemer, msg.sender, 0, redeemAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Borrow event; may emit AccrueInterest\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\n * @custom:access Not restricted\n */\n function borrow(uint256 borrowAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _borrowFresh(msg.sender, msg.sender, borrowAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:error DelegateNotApproved is thrown if caller is not approved delegate\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\n * @custom:event Emits Borrow event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function borrowBehalf(address borrower, uint256 borrowAmount) external override returns (uint256) {\n _ensureSenderIsDelegateOf(borrower);\n accrueInterest();\n\n _borrowFresh(borrower, msg.sender, borrowAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function repayBorrow(uint256 repayAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _repayBorrowFresh(msg.sender, msg.sender, repayAmount);\n return NO_ERROR;\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, or type(uint256).max for the full outstanding amount\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _repayBorrowFresh(msg.sender, borrower, repayAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\n * @custom:access Not restricted\n */\n function liquidateBorrow(\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) external override returns (uint256) {\n _liquidateBorrow(msg.sender, borrower, repayAmount, vTokenCollateral, false);\n return NO_ERROR;\n }\n\n /**\n * @notice sets protocol share accumulated from liquidations\n * @dev must be equal or less than liquidation incentive - 1\n * @param newProtocolSeizeShareMantissa_ new protocol share mantissa\n * @custom:event Emits NewProtocolSeizeShare event on success\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:error ProtocolSeizeShareTooBig is thrown when the new seize share is too high\n * @custom:access Controlled by AccessControlManager\n */\n function setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa_) external {\n _checkAccessAllowed(\"setProtocolSeizeShare(uint256)\");\n uint256 liquidationIncentive = ComptrollerViewInterface(address(comptroller)).liquidationIncentiveMantissa();\n if (newProtocolSeizeShareMantissa_ + MANTISSA_ONE > liquidationIncentive) {\n revert ProtocolSeizeShareTooBig();\n }\n\n uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\n protocolSeizeShareMantissa = newProtocolSeizeShareMantissa_;\n emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa_);\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 * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\n * @custom:event Emits NewReserveFactor event; may emit AccrueInterest\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:error SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\n * @custom:access Controlled by AccessControlManager\n */\n function setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant {\n _checkAccessAllowed(\"setReserveFactor(uint256)\");\n\n accrueInterest();\n _setReserveFactorFresh(newReserveFactorMantissa);\n }\n\n /**\n * @notice Accrues interest and reduces reserves by transferring to the protocol reserve contract\n * @dev Gracefully return if reserves already reduced in accrueInterest\n * @param reduceAmount Amount of reduction to reserves\n * @custom:event Emits ReservesReduced event; may emit AccrueInterest\n * @custom:error ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash\n * @custom:error ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\n * @custom:access Not restricted\n */\n function reduceReserves(uint256 reduceAmount) external override nonReentrant {\n accrueInterest();\n if (reduceReservesBlockNumber == getBlockNumberOrTimestamp()) return;\n _reduceReservesFresh(reduceAmount);\n }\n\n /**\n * @notice The sender adds to reserves.\n * @param addAmount The amount of underlying token to add as reserves\n * @custom:event Emits ReservesAdded event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function addReserves(uint256 addAmount) external override nonReentrant {\n accrueInterest();\n _addReservesFresh(addAmount);\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 * @custom:event Emits NewMarketInterestRateModel event; may emit AccrueInterest\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:access Controlled by AccessControlManager\n */\n function setInterestRateModel(InterestRateModel newInterestRateModel) external override {\n _checkAccessAllowed(\"setInterestRateModel(address)\");\n\n accrueInterest();\n _setInterestRateModelFresh(newInterestRateModel);\n }\n\n /**\n * @notice Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially\n * \"forgiving\" the borrower. Healing is a situation that should rarely happen. However, some pools\n * may list risky assets or be configured improperly – we want to still handle such cases gracefully.\n * We assume that Comptroller does the seizing, so this function is only available to Comptroller.\n * @dev This function does not call any Comptroller hooks (like \"healAllowed\"), because we assume\n * the Comptroller does all the necessary checks before calling this function.\n * @param payer account who repays the debt\n * @param borrower account to heal\n * @param repayAmount amount to repay\n * @custom:event Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\n * @custom:error HealBorrowUnauthorized is thrown when the request does not come from Comptroller\n * @custom:access Only Comptroller\n */\n function healBorrow(address payer, address borrower, uint256 repayAmount) external override nonReentrant {\n if (repayAmount != 0) {\n comptroller.preRepayHook(address(this), borrower);\n }\n\n if (msg.sender != address(comptroller)) {\n revert HealBorrowUnauthorized();\n }\n\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n uint256 totalBorrowsNew = totalBorrows;\n\n uint256 actualRepayAmount;\n if (repayAmount != 0) {\n // _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\n // We violate checks-effects-interactions here to account for tokens that take transfer fees\n actualRepayAmount = _doTransferIn(payer, repayAmount);\n totalBorrowsNew = totalBorrowsNew - actualRepayAmount;\n emit RepayBorrow(\n payer,\n borrower,\n actualRepayAmount,\n accountBorrowsPrev - actualRepayAmount,\n totalBorrowsNew\n );\n }\n\n // The transaction will fail if trying to repay too much\n uint256 badDebtDelta = accountBorrowsPrev - actualRepayAmount;\n if (badDebtDelta != 0) {\n uint256 badDebtOld = badDebt;\n uint256 badDebtNew = badDebtOld + badDebtDelta;\n totalBorrowsNew = totalBorrowsNew - badDebtDelta;\n badDebt = badDebtNew;\n\n // We treat healing as \"repayment\", where vToken is the payer\n emit RepayBorrow(address(this), borrower, badDebtDelta, 0, totalBorrowsNew);\n emit BadDebtIncreased(borrower, badDebtDelta, badDebtOld, badDebtNew);\n }\n\n accountBorrows[borrower].principal = 0;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n emit HealBorrow(payer, borrower, repayAmount);\n }\n\n /**\n * @notice The extended version of liquidations, callable only by Comptroller. May skip\n * the close factor check. The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\n * @custom:error ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\n * @custom:access Only Comptroller\n */\n function forceLiquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) external override {\n if (msg.sender != address(comptroller)) {\n revert ForceLiquidateBorrowUnauthorized();\n }\n _liquidateBorrow(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\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 * @custom:event Emits Transfer, ReservesAdded events\n * @custom:error LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:access Not restricted\n */\n function seize(address liquidator, address borrower, uint256 seizeTokens) external override nonReentrant {\n _seize(msg.sender, liquidator, borrower, seizeTokens);\n }\n\n /**\n * @notice Updates bad debt\n * @dev Called only when bad debt is recovered from auction. Updates internal cash balance.\n * @param recoveredAmount_ The amount of bad debt recovered\n * @custom:event Emits BadDebtRecovered event\n * @custom:access Only Shortfall contract\n */\n function badDebtRecovered(uint256 recoveredAmount_) external {\n require(msg.sender == shortfall, \"only shortfall contract can update bad debt\");\n require(recoveredAmount_ <= badDebt, \"more than bad debt recovered from auction\");\n\n uint256 badDebtOld = badDebt;\n uint256 badDebtNew = badDebtOld - recoveredAmount_;\n badDebt = badDebtNew;\n internalCash += recoveredAmount_;\n\n emit BadDebtRecovered(badDebtOld, badDebtNew);\n }\n\n /**\n * @notice Sets protocol share reserve contract address\n * @param protocolShareReserve_ The address of the protocol share reserve contract\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\n * @custom:access Only Governance\n */\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\n _setProtocolShareReserve(protocolShareReserve_);\n }\n\n /**\n * @notice Sets shortfall contract address\n * @param shortfall_ The address of the shortfall contract\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\n * @custom:access Only Governance\n */\n function setShortfallContract(address shortfall_) external onlyOwner {\n _setShortfallContract(shortfall_);\n }\n\n /**\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\n * @param token The address of the ERC-20 token to sweep\n * @custom:access Only Governance\n */\n function sweepToken(IERC20Upgradeable token) external override {\n require(msg.sender == owner(), \"VToken::sweepToken: only admin can sweep tokens\");\n require(address(token) != underlying, \"VToken::sweepToken: can not sweep underlying token\");\n uint256 balance = token.balanceOf(address(this));\n token.safeTransfer(owner(), balance);\n\n emit SweepToken(address(token));\n }\n\n /**\n * @notice Sync internalCash with the actual underlying token balance\n * @dev Used for one-time migration after upgrade to initialize internalCash\n * @custom:event Emits CashSynced\n * @custom:access Controlled by AccessControlManager\n */\n function syncCash() external override nonReentrant {\n _checkAccessAllowed(\"syncCash()\");\n uint256 oldInternalCash = internalCash;\n uint256 actualCash = IERC20Upgradeable(underlying).balanceOf(address(this));\n internalCash = actualCash;\n emit CashSynced(oldInternalCash, actualCash);\n }\n\n /**\n * @notice A public function to set new threshold of slot(block or second) difference after which funds will be sent to the protocol share reserve\n * @param _newReduceReservesBlockOrTimestampDelta slot(block or second) difference value\n * @custom:access Only Governance\n */\n function setReduceReservesBlockDelta(uint256 _newReduceReservesBlockOrTimestampDelta) external {\n _checkAccessAllowed(\"setReduceReservesBlockDelta(uint256)\");\n require(_newReduceReservesBlockOrTimestampDelta > 0, \"Invalid Input\");\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, _newReduceReservesBlockOrTimestampDelta);\n reduceReservesBlockDelta = _newReduceReservesBlockOrTimestampDelta;\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 amount 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 amount 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 error Always NO_ERROR for compatibility with Venus core tooling\n * @return vTokenBalance User's balance of vTokens\n * @return borrowBalance Amount owed in terms of underlying\n * @return exchangeRate Stored exchange rate\n */\n function getAccountSnapshot(\n address account\n )\n external\n view\n override\n returns (uint256 error, uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRate)\n {\n return (NO_ERROR, accountTokens[account], _borrowBalanceStored(account), _exchangeRateStored());\n }\n\n /**\n * @notice Get the internally tracked cash balance of this vToken in the underlying asset\n * @return cash The quantity of underlying asset tracked internally by this contract\n */\n function getCash() external view override returns (uint256) {\n return _getCashPrior();\n }\n\n /**\n * @notice Returns the current per slot(block or second) borrow interest rate for this vToken\n * @return rate The borrow interest rate per slot(block or second), scaled by 1e18\n */\n function borrowRatePerBlock() external view override returns (uint256) {\n return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt);\n }\n\n /**\n * @notice Returns the current per-slot(block or second) supply interest rate for this v\n * @return rate The supply interest rate per slot(block or second), scaled by 1e18\n */\n function supplyRatePerBlock() external view override returns (uint256) {\n return\n interestRateModel.getSupplyRate(\n _getCashPrior(),\n totalBorrows,\n totalReserves,\n reserveFactorMantissa,\n badDebt\n );\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 borrowBalance The calculated balance\n */\n function borrowBalanceStored(address account) external view override returns (uint256) {\n return _borrowBalanceStored(account);\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 exchangeRate Calculated exchange rate scaled by 1e18\n */\n function exchangeRateStored() external view override returns (uint256) {\n return _exchangeRateStored();\n }\n\n /**\n * @notice Accrue interest then return the up-to-date exchange rate\n * @return exchangeRate Calculated exchange rate scaled by 1e18\n */\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\n accrueInterest();\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 slot(block or second)\n * up to the current slot(block or second) and writes new checkpoint to storage and\n * reduce spread reserves to protocol share reserve\n * if currentSlot - reduceReservesBlockNumber >= slotDelta\n * @return Always NO_ERROR\n * @custom:event Emits AccrueInterest event on success\n * @custom:access Not restricted\n */\n function accrueInterest() public virtual override returns (uint256) {\n /* Remember the initial block number or timestamp */\n uint256 currentSlotNumber = getBlockNumberOrTimestamp();\n uint256 accrualSlotNumberPrior = accrualBlockNumber;\n\n /* Short-circuit accumulating 0 interest */\n if (accrualSlotNumberPrior == currentSlotNumber) {\n return NO_ERROR;\n }\n\n /* Read the previous values out of storage */\n uint256 cashPrior = _getCashPrior();\n uint256 borrowsPrior = totalBorrows;\n uint256 reservesPrior = totalReserves;\n uint256 borrowIndexPrior = borrowIndex;\n\n /* Calculate the current borrow interest rate */\n uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt);\n require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, \"borrow rate is absurdly high\");\n\n /* Calculate the number of slots elapsed since the last accrual */\n uint256 slotDelta = currentSlotNumber - accrualSlotNumberPrior;\n\n /*\n * Calculate the interest accumulated into borrows and reserves and the new index:\n * simpleInterestFactor = borrowRate * slotDelta\n * interestAccumulated = simpleInterestFactor * totalBorrows\n * totalBorrowsNew = interestAccumulated + totalBorrows\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\n */\n\n Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), slotDelta);\n uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\n uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;\n uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\n Exp({ mantissa: reserveFactorMantissa }),\n interestAccumulated,\n reservesPrior\n );\n uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the previously calculated values into storage */\n accrualBlockNumber = currentSlotNumber;\n borrowIndex = borrowIndexNew;\n totalBorrows = totalBorrowsNew;\n totalReserves = totalReservesNew;\n\n if (currentSlotNumber - reduceReservesBlockNumber >= reduceReservesBlockDelta) {\n reduceReservesBlockNumber = currentSlotNumber;\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 NO_ERROR;\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 or timestamp\n * @param payer The address of the account which is sending the assets for supply\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 */\n function _mintFresh(address payer, address minter, uint256 mintAmount) internal {\n /* Fail if mint not allowed */\n comptroller.preMintHook(address(this), minter, mintAmount);\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert MintFreshnessCheck();\n }\n\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\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 * `_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 uint256 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 uint256 mintTokens = div_(actualMintAmount, exchangeRate);\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 * And write them into storage\n */\n totalSupply = totalSupply + mintTokens;\n uint256 balanceAfter = accountTokens[minter] + mintTokens;\n accountTokens[minter] = balanceAfter;\n\n /* We emit a Mint event, and a Transfer event */\n emit Mint(minter, actualMintAmount, mintTokens, balanceAfter);\n emit Transfer(address(0), minter, mintTokens);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.mintVerify(address(this), minter, actualMintAmount, mintTokens);\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 Comptroller.updateDelegate)\n * @dev Assumes interest has already been accrued up to the current slot(block or second)\n * @param redeemer The address of the account which is redeeming the tokens\n * @param receiver The receiver of the underlying 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 */\n function _redeemFresh(address redeemer, address receiver, uint256 redeemTokensIn, uint256 redeemAmountIn) internal {\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \"one of redeemTokensIn or redeemAmountIn must be zero\");\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert RedeemFreshnessCheck();\n }\n\n /* exchangeRate = invoke Exchange Rate Stored() */\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\n\n uint256 redeemTokens;\n uint256 redeemAmount;\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 */\n redeemTokens = redeemTokensIn;\n } else {\n /*\n * We get the current exchange rate and calculate the amount to be redeemed:\n * redeemTokens = redeemAmountIn / exchangeRate\n */\n redeemTokens = div_(redeemAmountIn, exchangeRate);\n\n uint256 _redeemAmount = mul_(redeemTokens, exchangeRate);\n if (_redeemAmount != 0 && _redeemAmount != redeemAmountIn) redeemTokens++; // round up\n }\n\n // redeemAmount = exchangeRate * redeemTokens\n redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokens);\n\n // Revert if amount is zero\n if (redeemAmount == 0) {\n revert(\"redeemAmount is zero\");\n }\n\n /* Fail if redeem not allowed */\n comptroller.preRedeemHook(address(this), redeemer, redeemTokens);\n\n /* Fail gracefully if protocol has insufficient cash */\n if (_getCashPrior() - totalReserves < redeemAmount) {\n revert RedeemTransferOutNotPossible();\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We write the previously calculated values into storage.\n * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\n */\n totalSupply = totalSupply - redeemTokens;\n uint256 balanceAfter = accountTokens[redeemer] - redeemTokens;\n accountTokens[redeemer] = balanceAfter;\n\n /*\n * We invoke _doTransferOut for the receiver and the redeemAmount.\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 _doTransferOut(receiver, redeemAmount);\n\n /* We emit a Transfer event, and a Redeem event */\n emit Transfer(redeemer, address(this), redeemTokens);\n emit Redeem(redeemer, redeemAmount, redeemTokens, balanceAfter);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.redeemVerify(address(this), redeemer, redeemAmount, redeemTokens);\n }\n\n /**\n * @notice Users or their delegates borrow assets from the protocol\n * @param borrower User who borrows the assets\n * @param receiver The receiver of the tokens, if called by a delegate\n * @param borrowAmount The amount of the underlying asset to borrow\n */\n function _borrowFresh(address borrower, address receiver, uint256 borrowAmount) internal {\n /* Fail if borrow not allowed */\n comptroller.preBorrowHook(address(this), borrower, borrowAmount);\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert BorrowFreshnessCheck();\n }\n\n /* Fail gracefully if protocol has insufficient underlying cash */\n if (_getCashPrior() - totalReserves < borrowAmount) {\n revert BorrowCashNotAvailable();\n }\n\n /*\n * We calculate the new borrower and total borrow balances, failing on overflow:\n * accountBorrowNew = accountBorrow + borrowAmount\n * totalBorrowsNew = totalBorrows + borrowAmount\n */\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;\n uint256 totalBorrowsNew = totalBorrows + borrowAmount;\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We write the previously calculated values into storage.\n * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\n `*/\n accountBorrows[borrower].principal = accountBorrowsNew;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n /*\n * We invoke _doTransferOut for the receiver and the borrowAmount.\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, accountBorrowsNew, totalBorrowsNew);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\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 underlying tokens being returned, or type(uint256).max for the full outstanding amount\n * @return (uint) the actual repayment amount.\n */\n function _repayBorrowFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256) {\n /* Fail if repayBorrow not allowed */\n comptroller.preRepayHook(address(this), borrower);\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert RepayBorrowFreshnessCheck();\n }\n\n /* We fetch the amount the borrower owes, with accumulated interest */\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n\n uint256 repayAmountFinal = repayAmount >= accountBorrowsPrev ? accountBorrowsPrev : 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 * 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 uint256 actualRepayAmount = _doTransferIn(payer, repayAmountFinal);\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 uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\n uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;\n\n /* We write the previously calculated values into storage */\n accountBorrows[borrower].principal = accountBorrowsNew;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n /* We emit a RepayBorrow event */\n emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.repayBorrowVerify(address(this), payer, borrower, actualRepayAmount, borrowIndex);\n\n return actualRepayAmount;\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n */\n function _liquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) internal nonReentrant {\n accrueInterest();\n\n uint256 error = vTokenCollateral.accrueInterest();\n if (error != NO_ERROR) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\n revert LiquidateAccrueCollateralInterestFailed(error);\n }\n\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\n }\n\n /**\n * @notice The liquidator liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n */\n function _liquidateBorrowFresh(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) internal {\n /* Fail if liquidate not allowed */\n comptroller.preLiquidateHook(\n address(this),\n address(vTokenCollateral),\n borrower,\n repayAmount,\n skipLiquidityCheck\n );\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert LiquidateFreshnessCheck();\n }\n\n /* Verify vTokenCollateral market's slot(block or second) number equals current slot(block or second) number */\n if (vTokenCollateral.accrualBlockNumber() != getBlockNumberOrTimestamp()) {\n revert LiquidateCollateralFreshnessCheck();\n }\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n revert LiquidateLiquidatorIsBorrower();\n }\n\n /* Fail if repayAmount = 0 */\n if (repayAmount == 0) {\n revert LiquidateCloseAmountIsZero();\n }\n\n /* Fail if repayAmount = type(uint256).max */\n if (repayAmount == type(uint256).max) {\n revert LiquidateCloseAmountIsUintMax();\n }\n\n /* Fail if repayBorrow fails */\n uint256 actualRepayAmount = _repayBorrowFresh(liquidator, borrower, repayAmount);\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.liquidateCalculateSeizeTokens(\n address(this),\n address(vTokenCollateral),\n actualRepayAmount\n );\n require(amountSeizeError == 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, call _seize internally to avoid re-entrancy, otherwise make an external call\n if (address(vTokenCollateral) == address(this)) {\n _seize(address(this), liquidator, borrower, seizeTokens);\n } else {\n vTokenCollateral.seize(liquidator, borrower, seizeTokens);\n }\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\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 * It's absolutely critical to use msg.sender as the seizer vToken and not a parameter.\n * @param seizerContract The contract seizing the collateral (either borrowed vToken or Comptroller)\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 */\n function _seize(address seizerContract, address liquidator, address borrower, uint256 seizeTokens) internal {\n /* Fail if seize not allowed */\n comptroller.preSeizeHook(address(this), seizerContract, liquidator, borrower);\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n revert LiquidateSeizeLiquidatorIsBorrower();\n }\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 uint256 liquidationIncentiveMantissa = ComptrollerViewInterface(address(comptroller))\n .liquidationIncentiveMantissa();\n uint256 numerator = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));\n uint256 protocolSeizeTokens = div_(numerator, Exp({ mantissa: liquidationIncentiveMantissa }));\n uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\n uint256 protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the calculated values into storage */\n totalSupply = totalSupply - protocolSeizeTokens;\n accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\n accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\n\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\n _doTransferOut(protocolShareReserve, protocolSeizeAmount);\n\n // Update the pool asset's state in the protocol share reserve for the above transfer.\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\n address(comptroller),\n underlying,\n IProtocolShareReserve.IncomeType.LIQUIDATION\n );\n\n /* Emit a Transfer event */\n emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\n emit ProtocolSeize(borrower, protocolShareReserve, protocolSeizeAmount);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.seizeVerify(address(this), seizerContract, liquidator, borrower, seizeTokens);\n }\n\n function _setComptroller(ComptrollerInterface newComptroller) internal {\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\n /**\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\n * @dev Admin function to set a new reserve factor\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\n */\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal {\n // Verify market's slot(block or second) number equals current slot(block or second) number\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert SetReserveFactorFreshCheck();\n }\n\n // Check newReserveFactor ≤ maxReserveFactor\n if (newReserveFactorMantissa > MAX_RESERVE_FACTOR_MANTISSA) {\n revert SetReserveFactorBoundsCheck();\n }\n\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\n reserveFactorMantissa = newReserveFactorMantissa;\n\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\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 actualAddAmount The actual amount added, excluding the potential token fees\n */\n function _addReservesFresh(uint256 addAmount) internal returns (uint256) {\n // totalReserves + actualAddAmount\n uint256 totalReservesNew;\n uint256 actualAddAmount;\n\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert AddReservesFactorFreshCheck(actualAddAmount);\n }\n\n actualAddAmount = _doTransferIn(msg.sender, addAmount);\n totalReservesNew = totalReserves + actualAddAmount;\n totalReserves = totalReservesNew;\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\n\n return actualAddAmount;\n }\n\n /**\n * @notice Reduces reserves by transferring to the protocol reserve contract\n * @dev Requires fresh interest accrual\n * @param reduceAmount Amount of reduction to reserves\n */\n function _reduceReservesFresh(uint256 reduceAmount) internal {\n if (reduceAmount == 0) {\n return;\n }\n // totalReserves - reduceAmount\n uint256 totalReservesNew;\n\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert ReduceReservesFreshCheck();\n }\n\n // Fail gracefully if protocol has insufficient underlying cash\n if (_getCashPrior() < reduceAmount) {\n revert ReduceReservesCashNotAvailable();\n }\n\n // Check reduceAmount ≤ reserves[n] (totalReserves)\n if (reduceAmount > totalReserves) {\n revert ReduceReservesCashValidation();\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 // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\n _doTransferOut(protocolShareReserve, reduceAmount);\n\n // Update the pool asset's state in the protocol share reserve for the above transfer.\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\n address(comptroller),\n underlying,\n IProtocolShareReserve.IncomeType.SPREAD\n );\n\n emit SpreadReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\n }\n\n /**\n * @notice updates the interest rate model (*requires fresh interest accrual)\n * @dev Admin function to update the interest rate model\n * @param newInterestRateModel the new interest rate model to use\n */\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal {\n // Used to store old model for use in the event that is emitted on success\n InterestRateModel oldInterestRateModel;\n\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert SetInterestRateModelFreshCheck();\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\n /**\n * Safe Token **\n */\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 returns (uint256) {\n IERC20Upgradeable token = IERC20Upgradeable(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 * @param to Receiver of the underlying tokens\n * @param amount Amount of underlying to transfer\n */\n function _doTransferOut(address to, uint256 amount) internal virtual {\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\n internalCash -= amount;\n token.safeTransfer(to, amount);\n }\n\n /**\n * @notice Transfer `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 */\n function _transferTokens(address spender, address src, address dst, uint256 tokens) internal {\n /* Fail if transfer not allowed */\n comptroller.preTransferHook(address(this), src, dst, tokens);\n\n /* Do not allow self-transfers */\n if (src == dst) {\n revert TransferNotAllowed();\n }\n\n /* Get the allowance, infinite for the account owner */\n uint256 startingAllowance;\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 uint256 allowanceNew = startingAllowance - tokens;\n uint256 srcTokensNew = accountTokens[src] - tokens;\n uint256 dstTokensNew = accountTokens[dst] + tokens;\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n\n accountTokens[src] = srcTokensNew;\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\n /**\n * @notice Initialize the 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_ ERC-20 name of this token\n * @param symbol_ ERC-20 symbol of this token\n * @param decimals_ ERC-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param accessControlManager_ AccessControlManager contract address\n * @param riskManagement Addresses of risk & income related contracts\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\n */\n function _initialize(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address admin_,\n address accessControlManager_,\n RiskManagementInit memory riskManagement,\n uint256 reserveFactorMantissa_\n ) internal onlyInitializing {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\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 _setComptroller(comptroller_);\n\n // Initialize slot(block or second) number and borrow index (slot(block or second) number mocks depend on comptroller being set)\n accrualBlockNumber = getBlockNumberOrTimestamp();\n borrowIndex = MANTISSA_ONE;\n\n // Set the interest rate model (depends on slot(block or second) number / borrow index)\n _setInterestRateModelFresh(interestRateModel_);\n\n _setReserveFactorFresh(reserveFactorMantissa_);\n\n name = name_;\n symbol = symbol_;\n decimals = decimals_;\n _setShortfallContract(riskManagement.shortfall);\n _setProtocolShareReserve(riskManagement.protocolShareReserve);\n protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA;\n\n // Set underlying and sanity check it\n underlying = underlying_;\n IERC20Upgradeable(underlying).totalSupply();\n\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\n _notEntered = true;\n _transferOwnership(admin_);\n }\n\n function _setShortfallContract(address shortfall_) internal {\n ensureNonzeroAddress(shortfall_);\n address oldShortfall = shortfall;\n shortfall = shortfall_;\n emit NewShortfallContract(oldShortfall, shortfall_);\n }\n\n function _setProtocolShareReserve(address payable protocolShareReserve_) internal {\n ensureNonzeroAddress(protocolShareReserve_);\n address oldProtocolShareReserve = address(protocolShareReserve);\n protocolShareReserve = protocolShareReserve_;\n emit NewProtocolShareReserve(oldProtocolShareReserve, address(protocolShareReserve_));\n }\n\n function _ensureSenderIsDelegateOf(address user) internal view {\n if (!ComptrollerViewInterface(address(comptroller)).approvedDelegates(user, msg.sender)) {\n revert DelegateNotApproved();\n }\n }\n\n /**\n * @notice Gets the internally tracked cash balance of this market\n * @dev Returns the internalCash state variable, which is updated on transfers in/out\n * @return The quantity of underlying tokens tracked internally by this contract\n */\n function _getCashPrior() internal view virtual returns (uint256) {\n return internalCash;\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 borrowBalance the calculated balance\n */\n function _borrowBalanceStored(address account) internal view returns (uint256) {\n /* Get borrowBalance and borrowIndex */\n BorrowSnapshot memory 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 0;\n }\n\n /* Calculate new borrow balance using the interest index:\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\n */\n uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;\n\n return principalTimesIndex / borrowSnapshot.interestIndex;\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 exchangeRate Calculated exchange rate scaled by 1e18\n */\n function _exchangeRateStored() internal view virtual returns (uint256) {\n uint256 _totalSupply = totalSupply;\n if (_totalSupply == 0) {\n /*\n * If there are no tokens minted:\n * exchangeRate = initialExchangeRate\n */\n return initialExchangeRateMantissa;\n }\n /*\n * Otherwise:\n * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply\n */\n uint256 totalCash = _getCashPrior();\n uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;\n uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply;\n\n return exchangeRate;\n }\n}\n" + }, + "contracts/VTokenInterfaces.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\nimport { ComptrollerInterface } from \"./ComptrollerInterface.sol\";\nimport { InterestRateModel } from \"./InterestRateModel.sol\";\n\n/**\n * @title VTokenStorage\n * @author Venus\n * @notice Storage layout used by the `VToken` contract\n */\n// solhint-disable-next-line max-states-count\ncontract VTokenStorage {\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 uint256 principal;\n uint256 interestIndex;\n }\n\n /**\n * @dev Guard variable for re-entrancy checks\n */\n bool internal _notEntered;\n\n /**\n * @notice Underlying asset for this VToken\n */\n address public underlying;\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 Protocol share Reserve contract address\n */\n address payable public protocolShareReserve;\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 InterestRateModel public interestRateModel;\n\n // Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\n uint256 internal initialExchangeRateMantissa;\n\n /**\n * @notice Fraction of interest currently set aside for reserves\n */\n uint256 public reserveFactorMantissa;\n\n /**\n * @notice Slot(block or second) number that interest was last accrued at\n */\n uint256 public accrualBlockNumber;\n\n /**\n * @notice Accumulator of the total earned interest rate since the opening of the market\n */\n uint256 public borrowIndex;\n\n /**\n * @notice Total amount of outstanding borrows of the underlying in this market\n */\n uint256 public totalBorrows;\n\n /**\n * @notice Total amount of reserves of the underlying held in this market\n */\n uint256 public totalReserves;\n\n /**\n * @notice Total number of tokens in circulation\n */\n uint256 public totalSupply;\n\n /**\n * @notice Total bad debt of the market\n */\n uint256 public badDebt;\n\n // Official record of token balances for each account\n mapping(address => uint256) internal accountTokens;\n\n // Approved token transfer amounts on behalf of others\n mapping(address => mapping(address => uint256)) internal transferAllowances;\n\n // Mapping of account addresses to outstanding borrow balances\n mapping(address => BorrowSnapshot) internal accountBorrows;\n\n /**\n * @notice Share of seized collateral that is added to reserves\n */\n uint256 public protocolSeizeShareMantissa;\n\n /**\n * @notice Storage of Shortfall contract address\n */\n address public shortfall;\n\n /**\n * @notice delta slot (block or second) after which reserves will be reduced\n */\n uint256 public reduceReservesBlockDelta;\n\n /**\n * @notice last slot (block or second) number at which reserves were reduced\n */\n uint256 public reduceReservesBlockNumber;\n\n /**\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\n * @dev Updated via _doTransferIn(), _doTransferOut(), syncCash(), and badDebtRecovered(). Must be initialized via syncCash() 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[47] private __gap;\n}\n\n/**\n * @title VTokenInterface\n * @author Venus\n * @notice Interface implemented by the `VToken` contract\n */\nabstract contract VTokenInterface is VTokenStorage {\n struct RiskManagementInit {\n address shortfall;\n address payable protocolShareReserve;\n }\n\n /*** Market Events ***/\n\n /**\n * @notice Event emitted when interest is accrued\n */\n event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\n\n /**\n * @notice Event emitted when tokens are minted\n */\n event Mint(address indexed minter, uint256 mintAmount, uint256 mintTokens, uint256 accountBalance);\n\n /**\n * @notice Event emitted when tokens are redeemed\n */\n event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens, uint256 accountBalance);\n\n /**\n * @notice Event emitted when underlying is borrowed\n */\n event Borrow(address indexed borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\n\n /**\n * @notice Event emitted when a borrow is repaid\n */\n event RepayBorrow(\n address indexed payer,\n address indexed borrower,\n uint256 repayAmount,\n uint256 accountBorrows,\n uint256 totalBorrows\n );\n\n /**\n * @notice Event emitted when bad debt is accumulated on a market\n * @param borrower borrower to \"forgive\"\n * @param badDebtDelta amount of new bad debt recorded\n * @param badDebtOld previous bad debt value\n * @param badDebtNew new bad debt value\n */\n event BadDebtIncreased(address indexed borrower, uint256 badDebtDelta, uint256 badDebtOld, uint256 badDebtNew);\n\n /**\n * @notice Event emitted when bad debt is recovered via an auction\n * @param badDebtOld previous bad debt value\n * @param badDebtNew new bad debt value\n */\n event BadDebtRecovered(uint256 badDebtOld, uint256 badDebtNew);\n\n /**\n * @notice Event emitted when a borrow is liquidated\n */\n event LiquidateBorrow(\n address indexed liquidator,\n address indexed borrower,\n uint256 repayAmount,\n address indexed vTokenCollateral,\n uint256 seizeTokens\n );\n\n /*** Admin Events ***/\n\n /**\n * @notice Event emitted when comptroller is changed\n */\n event NewComptroller(ComptrollerInterface indexed oldComptroller, ComptrollerInterface indexed newComptroller);\n\n /**\n * @notice Event emitted when shortfall contract address is changed\n */\n event NewShortfallContract(address indexed oldShortfall, address indexed newShortfall);\n\n /**\n * @notice Event emitted when protocol share reserve contract address is changed\n */\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\n\n /**\n * @notice Event emitted when interestRateModel is changed\n */\n event NewMarketInterestRateModel(\n InterestRateModel indexed oldInterestRateModel,\n InterestRateModel indexed newInterestRateModel\n );\n\n /**\n * @notice Event emitted when protocol seize share is changed\n */\n event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\n\n /**\n * @notice Event emitted when the reserve factor is changed\n */\n event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\n\n /**\n * @notice Event emitted when the reserves are added\n */\n event ReservesAdded(address indexed benefactor, uint256 addAmount, uint256 newTotalReserves);\n\n /**\n * @notice Event emitted when the spread reserves are reduced\n */\n event SpreadReservesReduced(address indexed protocolShareReserve, uint256 reduceAmount, uint256 newTotalReserves);\n\n /**\n * @notice EIP20 Transfer event\n */\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n /**\n * @notice EIP20 Approval event\n */\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /**\n * @notice Event emitted when healing the borrow\n */\n event HealBorrow(address indexed payer, address indexed borrower, uint256 repayAmount);\n\n /**\n * @notice Event emitted when tokens are swept\n */\n event SweepToken(address indexed token);\n\n /**\n * @notice Event emitted when reduce reserves slot (block or second) delta is changed\n */\n event NewReduceReservesBlockDelta(\n uint256 oldReduceReservesBlockOrTimestampDelta,\n uint256 newReduceReservesBlockOrTimestampDelta\n );\n\n /**\n * @notice Event emitted when liquidation reserves are reduced\n */\n event ProtocolSeize(address indexed from, address indexed to, uint256 amount);\n\n /**\n * @notice Event emitted when internalCash is synced with actual token balance\n */\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\n\n /*** User Interface ***/\n\n function mint(uint256 mintAmount) external virtual returns (uint256);\n\n function mintBehalf(address minter, uint256 mintAllowed) external virtual returns (uint256);\n\n function redeem(uint256 redeemTokens) external virtual returns (uint256);\n\n function redeemBehalf(address redeemer, uint256 redeemTokens) external virtual returns (uint256);\n\n function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);\n\n function redeemUnderlyingBehalf(address redeemer, uint256 redeemAmount) external virtual returns (uint256);\n\n function borrow(uint256 borrowAmount) external virtual returns (uint256);\n\n function borrowBehalf(address borrwwer, uint256 borrowAmount) external virtual returns (uint256);\n\n function repayBorrow(uint256 repayAmount) external virtual returns (uint256);\n\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);\n\n function liquidateBorrow(\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) external virtual returns (uint256);\n\n function healBorrow(address payer, address borrower, uint256 repayAmount) external virtual;\n\n function forceLiquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipCloseFactorCheck\n ) external virtual;\n\n function seize(address liquidator, address borrower, uint256 seizeTokens) external virtual;\n\n function transfer(address dst, uint256 amount) external virtual returns (bool);\n\n function transferFrom(address src, address dst, uint256 amount) external virtual returns (bool);\n\n function accrueInterest() external virtual returns (uint256);\n\n function sweepToken(IERC20Upgradeable token) external virtual;\n\n /*** Admin Functions ***/\n\n function setReserveFactor(uint256 newReserveFactorMantissa) external virtual;\n\n function reduceReserves(uint256 reduceAmount) external virtual;\n\n function exchangeRateCurrent() external virtual returns (uint256);\n\n function borrowBalanceCurrent(address account) external virtual returns (uint256);\n\n function setInterestRateModel(InterestRateModel newInterestRateModel) external virtual;\n\n function addReserves(uint256 addAmount) external virtual;\n\n function syncCash() external virtual;\n\n function totalBorrowsCurrent() external virtual returns (uint256);\n\n function balanceOfUnderlying(address owner) external virtual returns (uint256);\n\n function approve(address spender, uint256 amount) external virtual returns (bool);\n\n function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool);\n\n function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool);\n\n function allowance(address owner, address spender) external view virtual returns (uint256);\n\n function balanceOf(address owner) external view virtual returns (uint256);\n\n function getAccountSnapshot(address account) external view virtual returns (uint256, uint256, uint256, uint256);\n\n function borrowRatePerBlock() external view virtual returns (uint256);\n\n function supplyRatePerBlock() external view virtual returns (uint256);\n\n function borrowBalanceStored(address account) external view virtual returns (uint256);\n\n function exchangeRateStored() external view virtual returns (uint256);\n\n function getCash() external view virtual returns (uint256);\n\n /**\n * @notice Indicator that this is a VToken contract (for inspection)\n * @return Always true\n */\n function isVToken() external pure virtual returns (bool) {\n return true;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200, + "details": { + "yul": true + } + }, + "evmVersion": "paris", + "outputSelection": { + "*": { + "*": [ + "storageLayout", + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} diff --git a/deployments/opbnbmainnet_addresses.json b/deployments/opbnbmainnet_addresses.json index e7db1a682..d45ef174a 100644 --- a/deployments/opbnbmainnet_addresses.json +++ b/deployments/opbnbmainnet_addresses.json @@ -29,7 +29,7 @@ "JumpRateModelV2_base0bps_slope900bps_jump30000bps_kink4500bps_bpy63072000": "0x36D00Ae4A2efF223179DDF7535425400f7Fa93d9", "JumpRateModel_base0bps_slope1000bps_jump25000bps_kink8000bps_bpy31536000": "0xaf6862b20280818FA24fA6D17097517608Fe65d4", "NativeTokenGateway_vWBNB_Core": "0x7bAf6019C90B93aD30f8aD6a2EcCD2B11427b29f", - "PoolLens": "0xA21E48d143818aB0b5231542A486609dFcc20Ee8", + "PoolLens": "0x3367FFCcbB15f00635a00b2B4B234f4c3966C9d4", "PoolRegistry": "0x345a030Ad22e2317ac52811AC41C1A63cfa13aEe", "PoolRegistry_Implementation": "0xc5A64235ff4aad92b71eC69a925224b60aede1aa", "PoolRegistry_Proxy": "0x345a030Ad22e2317ac52811AC41C1A63cfa13aEe", diff --git a/deployments/opmainnet.json b/deployments/opmainnet.json index b3823b7fa..fcd123a40 100644 --- a/deployments/opmainnet.json +++ b/deployments/opmainnet.json @@ -3932,7 +3932,7 @@ ] }, "PoolLens": { - "address": "0x142160A2E699e33af337741f157D96aAd6bC72aA", + "address": "0x10f849a22f16DF086EF44B97ef8DF8D78B8Ac74E", "abi": [ { "inputs": [ @@ -3945,6 +3945,11 @@ "internalType": "uint256", "name": "blocksPerYear_", "type": "uint256" + }, + { + "internalType": "address", + "name": "corePoolComptroller_", + "type": "address" } ], "stateMutability": "nonpayable", @@ -3973,6 +3978,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "corePoolComptroller", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { diff --git a/deployments/opmainnet/PoolLens.json b/deployments/opmainnet/PoolLens.json index 0dadc0a5f..e146e1ad7 100644 --- a/deployments/opmainnet/PoolLens.json +++ b/deployments/opmainnet/PoolLens.json @@ -1,5 +1,5 @@ { - "address": "0x142160A2E699e33af337741f157D96aAd6bC72aA", + "address": "0x10f849a22f16DF086EF44B97ef8DF8D78B8Ac74E", "abi": [ { "inputs": [ @@ -12,6 +12,11 @@ "internalType": "uint256", "name": "blocksPerYear_", "type": "uint256" + }, + { + "internalType": "address", + "name": "corePoolComptroller_", + "type": "address" } ], "stateMutability": "nonpayable", @@ -40,6 +45,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "corePoolComptroller", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -1168,28 +1186,28 @@ "type": "function" } ], - "transactionHash": "0x0bfa039a009c56a26ea767897546ac762401a86ef0d0b4e012586ec2aa687ee0", + "transactionHash": "0xf2fbdf92eac27994738975ab038433b91474c89e537b1cf51fc04c3374b9b71f", "receipt": { "to": null, "from": "0xC76363B887031e79E6A2954c5515f5E5507A6387", - "contractAddress": "0x142160A2E699e33af337741f157D96aAd6bC72aA", - "transactionIndex": 23, - "gasUsed": "3524220", + "contractAddress": "0x10f849a22f16DF086EF44B97ef8DF8D78B8Ac74E", + "transactionIndex": 16, + "gasUsed": "3593126", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x9986616a1fc12ead09b70a86f11d6298e46d0f38a54e09a25ec3ad68e787c8f9", - "transactionHash": "0x0bfa039a009c56a26ea767897546ac762401a86ef0d0b4e012586ec2aa687ee0", + "blockHash": "0x58ebea499ee71bd9b956837963d7e47ca488a151ec1e0bd5f70f99340217b538", + "transactionHash": "0xf2fbdf92eac27994738975ab038433b91474c89e537b1cf51fc04c3374b9b71f", "logs": [], - "blockNumber": 126043449, - "cumulativeGasUsed": "8511768", + "blockNumber": 149681351, + "cumulativeGasUsed": "9537180", "status": 1, "byzantium": true }, - "args": [true, 0], - "numDeployments": 1, - "solcInputHash": "7a28e95a7186e06cde14ca21a979d10b", - "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"timeBased_\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"blocksPerYear_\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidBlocksPerYear\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTimeBasedConfiguration\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"blocksOrSecondsPerYear\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"}],\"name\":\"getAllPools\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockNumberOrTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getPendingRewards\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"distributorAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"rewardTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalRewards\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.PendingReward[]\",\"name\":\"pendingRewards\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.RewardSummary[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getPoolBadDebt\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalBadDebtUsd\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"badDebtUsd\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.BadDebt[]\",\"name\":\"badDebts\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.BadDebtSummary\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolByComptroller\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolRegistryInterface.VenusPool\",\"name\":\"venusPool\",\"type\":\"tuple\"}],\"name\":\"getPoolDataFromVenusPool\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getPoolsSupportedByAsset\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getVTokenForAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isTimeBased\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"vTokenBalances\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalanceCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balanceOfUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenAllowance\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenBalances\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"vTokenBalancesAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalanceCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balanceOfUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenAllowance\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenBalances[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"vTokenMetadata\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"vTokenMetadataAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"vTokenUnderlyingPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"underlyingPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenUnderlyingPrice\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"vTokenUnderlyingPriceAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"underlyingPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenUnderlyingPrice[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"params\":{\"blocksPerYear_\":\"The number of blocks per year\",\"timeBased_\":\"A boolean indicating whether the contract is based on time or block.\"}},\"getAllPools(address)\":{\"details\":\"This function is not designed to be called in a transaction: it is too gas-intensive\",\"params\":{\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"Arrays of all Venus pools' data\"}},\"getBlockNumberOrTimestamp()\":{\"details\":\"Function to simply retrieve block number or block timestamp\",\"returns\":{\"_0\":\"Current block number or block timestamp\"}},\"getPendingRewards(address,address)\":{\"params\":{\"account\":\"The user account.\",\"comptrollerAddress\":\"address\"},\"returns\":{\"_0\":\"Pending rewards array\"}},\"getPoolBadDebt(address)\":{\"params\":{\"comptrollerAddress\":\"Address of the comptroller\"},\"returns\":{\"_0\":\"badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and a break down of bad debt by market\"}},\"getPoolByComptroller(address,address)\":{\"params\":{\"comptroller\":\"The Comptroller implementation address\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"PoolData structure containing the details of the pool\"}},\"getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))\":{\"params\":{\"poolRegistryAddress\":\"Address of the PoolRegistry\",\"venusPool\":\"The VenusPool Object from PoolRegistry\"},\"returns\":{\"_0\":\"Enriched PoolData\"}},\"getPoolsSupportedByAsset(address,address)\":{\"params\":{\"asset\":\"The underlying asset of vToken\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"A list of Comptroller contracts\"}},\"getVTokenForAsset(address,address,address)\":{\"params\":{\"asset\":\"The underlyingAsset of VToken\",\"comptroller\":\"The pool comptroller\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"Address of the vToken\"}},\"vTokenBalances(address,address)\":{\"params\":{\"account\":\"The user Account\",\"vToken\":\"vToken address\"},\"returns\":{\"_0\":\"A struct containing the balances data\"}},\"vTokenBalancesAll(address[],address)\":{\"params\":{\"account\":\"The user Account\",\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"A list of structs containing balances data\"}},\"vTokenMetadata(address)\":{\"params\":{\"vToken\":\"The address of vToken\"},\"returns\":{\"_0\":\"VTokenMetadata struct\"}},\"vTokenMetadataAll(address[])\":{\"params\":{\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"An array of VTokenMetadata structs\"}},\"vTokenUnderlyingPrice(address)\":{\"params\":{\"vToken\":\"vToken address\"},\"returns\":{\"_0\":\"The price data for each asset\"}},\"vTokenUnderlyingPriceAll(address[])\":{\"params\":{\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"An array containing the price data for each asset\"}}},\"title\":\"PoolLens\",\"version\":1},\"userdoc\":{\"errors\":{\"InvalidBlocksPerYear()\":[{\"notice\":\"Thrown when blocks per year is invalid\"}],\"InvalidTimeBasedConfiguration()\":[{\"notice\":\"Thrown when time based but blocks per year is provided\"}]},\"kind\":\"user\",\"methods\":{\"blocksOrSecondsPerYear()\":{\"notice\":\"Stores blocksPerYear if isTimeBased is true else secondsPerYear is stored\"},\"getAllPools(address)\":{\"notice\":\"Queries all pools with addtional details for each of them\"},\"getPendingRewards(address,address)\":{\"notice\":\"Returns the pending rewards for a user for a given pool.\"},\"getPoolBadDebt(address)\":{\"notice\":\"Returns a summary of a pool's bad debt broken down by market\"},\"getPoolByComptroller(address,address)\":{\"notice\":\"Queries the details of a pool identified by Comptroller address\"},\"getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))\":{\"notice\":\"Queries additional information for the pool\"},\"getPoolsSupportedByAsset(address,address)\":{\"notice\":\"Returns all pools that support the specified underlying asset\"},\"getVTokenForAsset(address,address,address)\":{\"notice\":\"Returns vToken holding the specified underlying asset in the specified pool\"},\"isTimeBased()\":{\"notice\":\"Acknowledges if a contract is time based or not\"},\"vTokenBalances(address,address)\":{\"notice\":\"Queries the user's supply/borrow balances in the specified vToken\"},\"vTokenBalancesAll(address[],address)\":{\"notice\":\"Queries the user's supply/borrow balances in vTokens\"},\"vTokenMetadata(address)\":{\"notice\":\"Returns the metadata of VToken\"},\"vTokenMetadataAll(address[])\":{\"notice\":\"Returns the metadata of all VTokens\"},\"vTokenUnderlyingPrice(address)\":{\"notice\":\"Returns the price data for the underlying asset of the specified vToken\"},\"vTokenUnderlyingPriceAll(address[])\":{\"notice\":\"Returns the price data for the underlying assets of the specified vTokens\"}},\"notice\":\"The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be looked up for specific pools and markets: - the vToken balance of a given user; - the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address; - the vToken address in a pool for a given asset; - a list of all pools that support an asset; - the underlying asset price of a vToken; - the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Lens/PoolLens.sol\":\"PoolLens\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"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\",\"keccak256\":\"0x9140dabc466abab21b48b72dbda26736b1183a310d0e677d3719d201df026510\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x359a1ab89b46b9aba7bcad3fb651924baf4893d15153049b9976b0fc9be1358e\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x07e881de3b9f6d2c07909f193f24b96c7fe4ea60013260f3f25aecd8bab3c2f8\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x75097e35253e7fb282ee4d7f27a80eaacfa759923185bf17302a89cbc059c5ef\",\"license\":\"MIT\"},\"@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\"},\"@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 private _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\",\"keccak256\":\"0x0dcf283925f4dddc23ca0ee71d2cb96a9dd6e4cf08061b69fde1697ea39dc514\",\"license\":\"BSD-3-Clause\"},\"@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/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface IProtocolShareReserve {\\n /// @notice it represents the type of vToken income\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION\\n }\\n\\n function updateAssetsState(\\n address comptroller,\\n address asset,\\n IncomeType incomeType\\n ) external;\\n}\\n\",\"keccak256\":\"0x5fddc5b63fdd850b3b5c83576cda50dcb27a205dbb1a23af17d9da0d9f04fa0a\",\"license\":\"BSD-3-Clause\"},\"@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\",\"keccak256\":\"0x57a2bbb9b8e02b1c0a5c0e305fef1328a22db56c3d4b148c362010a6e767243c\",\"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\"},\"@venusprotocol/venus-protocol/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\",\"keccak256\":\"0xd112f60183416ad796093b4a83a80ddc1b8b655965f02ae55ca82e2a0c68f97d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/venus-protocol/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\",\"keccak256\":\"0x5285c875114db2ea2be0b81b65722d5761806217022db733323c4e03365a95e7\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IPrime } from \\\"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\\\";\\n\\nimport { ComptrollerInterface, Action } from \\\"./ComptrollerInterface.sol\\\";\\nimport { ComptrollerStorage } from \\\"./ComptrollerStorage.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"./MaxLoopsLimitHelper.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title Comptroller\\n * @author Venus\\n * @notice The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating,\\n * and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts\\n * with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows\\n * or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing\\n * liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow,\\n * as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the\\n * markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market\\u2019s corresponding liquidation threshold,\\n * the borrow is eligible for liquidation.\\n *\\n * The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed\\n * the `minLiquidatableCollateral` for the `Comptroller`:\\n *\\n * - `healAccount()`: This function is called to seize all of a given user\\u2019s collateral, requiring the `msg.sender` repay a certain percentage\\n * of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed\\n * 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt\\n * and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool.\\n * - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation\\n * incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic\\n * verifying that the repay amount does not exceed the close factor.\\n */\\ncontract Comptroller is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n ComptrollerStorage,\\n ComptrollerInterface,\\n ExponentialNoError,\\n MaxLoopsLimitHelper\\n{\\n // PoolRegistry, immutable to save on gas\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable poolRegistry;\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(VToken indexed vToken, address indexed account);\\n\\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(VToken vToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa);\\n\\n /// @notice Emitted when liquidation threshold is changed by admin\\n event NewLiquidationThreshold(\\n VToken vToken,\\n uint256 oldLiquidationThresholdMantissa,\\n uint256 newLiquidationThresholdMantissa\\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 an action is paused on a market\\n event ActionPausedMarket(VToken vToken, Action action, bool pauseState);\\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 the collateral threshold (in USD) for non-batch liquidations is changed\\n event NewMinLiquidatableCollateral(uint256 oldMinLiquidatableCollateral, uint256 newMinLiquidatableCollateral);\\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 a rewards distributor is added\\n event NewRewardsDistributor(address indexed rewardsDistributor, address indexed rewardToken);\\n\\n /// @notice Emitted when a market is supported\\n event MarketSupported(VToken vToken);\\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 a market\\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\\n\\n /// @notice Emitted when a market is unlisted\\n event MarketUnlisted(address indexed vToken);\\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 Thrown when collateral factor exceeds the upper bound\\n error InvalidCollateralFactor();\\n\\n /// @notice Thrown when liquidation threshold exceeds the collateral factor\\n error InvalidLiquidationThreshold();\\n\\n /// @notice Thrown when the action is only available to specific sender, but the real sender was different\\n error UnexpectedSender(address expectedSender, address actualSender);\\n\\n /// @notice Thrown when the oracle returns an invalid price for some asset\\n error PriceError(address vToken);\\n\\n /// @notice Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\\n error SnapshotError(address vToken, address user);\\n\\n /// @notice Thrown when the market is not listed\\n error MarketNotListed(address market);\\n\\n /// @notice Thrown when a market has an unexpected comptroller\\n error ComptrollerMismatch();\\n\\n /// @notice Thrown when user is not member of market\\n error MarketNotCollateral(address vToken, address user);\\n\\n /// @notice Thrown when borrow action is not paused\\n error BorrowActionNotPaused();\\n\\n /// @notice Thrown when mint action is not paused\\n error MintActionNotPaused();\\n\\n /// @notice Thrown when redeem action is not paused\\n error RedeemActionNotPaused();\\n\\n /// @notice Thrown when repay action is not paused\\n error RepayActionNotPaused();\\n\\n /// @notice Thrown when seize action is not paused\\n error SeizeActionNotPaused();\\n\\n /// @notice Thrown when exit market action is not paused\\n error ExitMarketActionNotPaused();\\n\\n /// @notice Thrown when transfer action is not paused\\n error TransferActionNotPaused();\\n\\n /// @notice Thrown when enter market action is not paused\\n error EnterMarketActionNotPaused();\\n\\n /// @notice Thrown when liquidate action is not paused\\n error LiquidateActionNotPaused();\\n\\n /// @notice Thrown when borrow cap is not zero\\n error BorrowCapIsNotZero();\\n\\n /// @notice Thrown when supply cap is not zero\\n error SupplyCapIsNotZero();\\n\\n /// @notice Thrown when collateral factor is not zero\\n error CollateralFactorIsNotZero();\\n\\n /**\\n * @notice Thrown during the liquidation if user's total collateral amount is lower than\\n * a predefined threshold. In this case only batch liquidations (either liquidateAccount\\n * or healAccount) are available.\\n */\\n error MinimalCollateralViolated(uint256 expectedGreaterThan, uint256 actual);\\n error CollateralExceedsThreshold(uint256 expectedLessThanOrEqualTo, uint256 actual);\\n error InsufficientCollateral(uint256 collateralToSeize, uint256 availableCollateral);\\n\\n /// @notice Thrown when the account doesn't have enough liquidity to redeem or borrow\\n error InsufficientLiquidity();\\n\\n /// @notice Thrown when trying to liquidate a healthy account\\n error InsufficientShortfall();\\n\\n /// @notice Thrown when trying to repay more than allowed by close factor\\n error TooMuchRepay();\\n\\n /// @notice Thrown if the user is trying to exit a market in which they have an outstanding debt\\n error NonzeroBorrowBalance();\\n\\n /// @notice Thrown when trying to perform an action that is paused\\n error ActionPaused(address market, Action action);\\n\\n /// @notice Thrown when trying to add a market that is already listed\\n error MarketAlreadyListed(address market);\\n\\n /// @notice Thrown if the supply cap is exceeded\\n error SupplyCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if the borrow cap is exceeded\\n error BorrowCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if delegate approval status is already set to the requested value\\n error DelegationStatusUnchanged();\\n\\n /// @param poolRegistry_ Pool registry address\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n constructor(address poolRegistry_) {\\n ensureNonzeroAddress(poolRegistry_);\\n\\n poolRegistry = poolRegistry_;\\n _disableInitializers();\\n }\\n\\n /**\\n * @param loopLimit Limit for the loops can iterate to avoid the DOS\\n * @param accessControlManager Access control manager contract address\\n */\\n function initialize(uint256 loopLimit, address accessControlManager) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager);\\n\\n _setMaxLoopsLimit(loopLimit);\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation; enabling them to be used as collateral\\n * @param vTokens The list of addresses of the vToken markets to be enabled\\n * @return errors An array of NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketEntered is emitted for each market on success\\n * @custom:error ActionPaused error is thrown if entering any of the markets is paused\\n * @custom:error MarketNotListed error is thrown if any of the markets is not listed\\n * @custom:access Not restricted\\n */\\n function enterMarkets(address[] memory vTokens) external override returns (uint256[] memory) {\\n uint256 len = vTokens.length;\\n\\n uint256[] memory results = new uint256[](len);\\n for (uint256 i; i < len; ++i) {\\n VToken vToken = VToken(vTokens[i]);\\n\\n _addToMarket(vToken, msg.sender);\\n results[i] = NO_ERROR;\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Unlist a market by setting isListed to false\\n * @dev Checks if all actions are paused, borrow/supply caps is set to 0 and collateral factor is to 0.\\n * @param market The address of the market (token) to unlist\\n * @return uint256 Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketUnlisted is emitted on success\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error BorrowActionNotPaused error is thrown if borrow action is not paused\\n * @custom:error MintActionNotPaused error is thrown if mint action is not paused\\n * @custom:error RedeemActionNotPaused error is thrown if redeem action is not paused\\n * @custom:error RepayActionNotPaused error is thrown if repay action is not paused\\n * @custom:error EnterMarketActionNotPaused error is thrown if enter market action is not paused\\n * @custom:error LiquidateActionNotPaused error is thrown if liquidate action is not paused\\n * @custom:error BorrowCapIsNotZero error is thrown if borrow cap is not zero\\n * @custom:error SupplyCapIsNotZero error is thrown if supply cap is not zero\\n * @custom:error CollateralFactorIsNotZero error is thrown if collateral factor is not zero\\n */\\n function unlistMarket(address market) external returns (uint256) {\\n _checkAccessAllowed(\\\"unlistMarket(address)\\\");\\n\\n Market storage _market = markets[market];\\n\\n if (!_market.isListed) {\\n revert MarketNotListed(market);\\n }\\n\\n if (!actionPaused(market, Action.BORROW)) {\\n revert BorrowActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.MINT)) {\\n revert MintActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.REDEEM)) {\\n revert RedeemActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.REPAY)) {\\n revert RepayActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.SEIZE)) {\\n revert SeizeActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.ENTER_MARKET)) {\\n revert EnterMarketActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.LIQUIDATE)) {\\n revert LiquidateActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.TRANSFER)) {\\n revert TransferActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.EXIT_MARKET)) {\\n revert ExitMarketActionNotPaused();\\n }\\n\\n if (borrowCaps[market] != 0) {\\n revert BorrowCapIsNotZero();\\n }\\n\\n if (supplyCaps[market] != 0) {\\n revert SupplyCapIsNotZero();\\n }\\n\\n if (_market.collateralFactorMantissa != 0) {\\n revert CollateralFactorIsNotZero();\\n }\\n\\n _market.isListed = false;\\n emit MarketUnlisted(market);\\n\\n return NO_ERROR;\\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 * @custom:event DelegateUpdated emits on success\\n * @custom:error ZeroAddressNotAllowed is thrown when delegate address is zero\\n * @custom:error DelegationStatusUnchanged is thrown if approval status is already set to the requested value\\n * @custom:access Not restricted\\n */\\n function updateDelegate(address delegate, bool approved) external {\\n ensureNonzeroAddress(delegate);\\n if (approvedDelegates[msg.sender][delegate] == approved) {\\n revert DelegationStatusUnchanged();\\n }\\n\\n approvedDelegates[msg.sender][delegate] = approved;\\n emit DelegateUpdated(msg.sender, delegate, approved);\\n }\\n\\n /**\\n * @notice Removes asset from sender's account liquidity calculation; disabling them as collateral\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketExited is emitted on success\\n * @custom:error ActionPaused error is thrown if exiting the market is paused\\n * @custom:error NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function exitMarket(address vTokenAddress) external override returns (uint256) {\\n _checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\\n VToken vToken = VToken(vTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\\n (uint256 tokensHeld, uint256 amountOwed, ) = _safeGetAccountSnapshot(vToken, msg.sender);\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n revert NonzeroBorrowBalance();\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n _checkRedeemAllowed(vTokenAddress, msg.sender, tokensHeld);\\n\\n Market storage marketToExit = markets[address(vToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return 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 // load into memory for faster iteration\\n VToken[] memory userAssetList = accountAssets[msg.sender];\\n uint256 len = userAssetList.length;\\n\\n uint256 assetIndex = len;\\n for (uint256 i; i < len; ++i) {\\n if (userAssetList[i] == vToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n VToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.pop();\\n\\n emit MarketExited(vToken, msg.sender);\\n\\n return NO_ERROR;\\n }\\n\\n /*** Policy Hooks ***/\\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 * @custom:error ActionPaused error is thrown if supplying to this market is paused\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\\n * @custom:access Not restricted\\n */\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external override {\\n _checkActionPauseState(vToken, Action.MINT);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n uint256 supplyCap = supplyCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (supplyCap != type(uint256).max) {\\n uint256 vTokenSupply = VToken(vToken).totalSupply();\\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\\n if (nextTotalSupply > supplyCap) {\\n revert SupplyCapExceeded(vToken, supplyCap);\\n }\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, minter);\\n }\\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external override {\\n _checkActionPauseState(vToken, Action.REDEEM);\\n\\n _checkRedeemAllowed(vToken, redeemer, redeemTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, redeemer);\\n }\\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 if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(redeemer, vToken);\\n }\\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 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 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 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 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 * @custom:error ActionPaused error is thrown if borrowing is paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if there is not enough collateral to borrow\\n * @custom:error BorrowCapExceeded is thrown if the borrow cap will be exceeded should this borrow succeed\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted if vToken is enabled as collateral, otherwise only vToken\\n */\\n /// disable-eslint\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external override {\\n _checkActionPauseState(vToken, Action.BORROW);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (!markets[vToken].accountMembership[borrower]) {\\n // only vTokens may call borrowAllowed if borrower not in market\\n _checkSenderIs(vToken);\\n\\n // attempt to add borrower to the market or revert\\n _addToMarket(VToken(msg.sender), borrower);\\n }\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (oracle.getUnderlyingPrice(vToken) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 borrowCap = borrowCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (borrowCap != type(uint256).max) {\\n uint256 totalBorrows = VToken(vToken).totalBorrows();\\n uint256 badDebt = VToken(vToken).badDebt();\\n uint256 nextTotalBorrows = totalBorrows + borrowAmount + badDebt;\\n if (nextTotalBorrows > borrowCap) {\\n revert BorrowCapExceeded(vToken, borrowCap);\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n borrower,\\n VToken(vToken),\\n 0,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\n }\\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 borrower The account which would borrowed the asset\\n * @custom:error ActionPaused error is thrown if repayments are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:access Not restricted\\n */\\n function preRepayHook(address vToken, address borrower) external override {\\n _checkActionPauseState(vToken, Action.REPAY);\\n\\n oracle.updatePrice(vToken);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\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 borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n * @param skipLiquidityCheck Allows the borrow to be liquidated regardless of the account liquidity\\n * @custom:error ActionPaused error is thrown if liquidations are paused in this market\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor\\n * @custom:error MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations\\n * @custom:error InsufficientShortfall is thrown when trying to liquidate a healthy account\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n */\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external override {\\n // Pause Action.LIQUIDATE on BORROWED TOKEN to prevent liquidating it.\\n // If we want to pause liquidating to vTokenCollateral, we should pause\\n // Action.SEIZE on it\\n _checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(address(vTokenBorrowed));\\n }\\n if (!markets[vTokenCollateral].isListed) {\\n revert MarketNotListed(address(vTokenCollateral));\\n }\\n\\n uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\\n\\n /* Allow accounts to be liquidated if it is a forced liquidation */\\n if (skipLiquidityCheck || isForcedLiquidationEnabled[vTokenBorrowed]) {\\n if (repayAmount > borrowBalance) {\\n revert TooMuchRepay();\\n }\\n return;\\n }\\n\\n /* The borrower must have shortfall and collateral > threshold in order to be liquidatable */\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral <= minLiquidatableCollateral) {\\n /* The liquidator should use either liquidateAccount or healAccount */\\n revert MinimalCollateralViolated(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint256 maxClose = mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance);\\n if (repayAmount > maxClose) {\\n revert TooMuchRepay();\\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 seizerContract Contract that tries to seize the asset (either borrowed vToken or Comptroller)\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @custom:error ActionPaused error is thrown if seizing this type of collateral is paused\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error ComptrollerMismatch error is when seizer contract or seized asset belong to different pools\\n * @custom:access Not restricted\\n */\\n function preSeizeHook(\\n address vTokenCollateral,\\n address seizerContract,\\n address liquidator,\\n address borrower\\n ) external override {\\n // Pause Action.SEIZE on COLLATERAL to prevent seizing it.\\n // If we want to pause liquidating vTokenBorrowed, we should pause\\n // Action.LIQUIDATE on it\\n _checkActionPauseState(vTokenCollateral, Action.SEIZE);\\n\\n Market storage market = markets[vTokenCollateral];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(vTokenCollateral);\\n }\\n\\n if (seizerContract == address(this)) {\\n // If Comptroller is the seizer, just check if collateral's comptroller\\n // is equal to the current address\\n if (address(VToken(vTokenCollateral).comptroller()) != address(this)) {\\n revert ComptrollerMismatch();\\n }\\n } else {\\n // If the seizer is not the Comptroller, check that the seizer is a\\n // listed market, and that the markets' comptrollers match\\n if (!markets[seizerContract].isListed) {\\n revert MarketNotListed(seizerContract);\\n }\\n if (VToken(vTokenCollateral).comptroller() != VToken(seizerContract).comptroller()) {\\n revert ComptrollerMismatch();\\n }\\n }\\n\\n if (!market.accountMembership[borrower]) {\\n revert MarketNotCollateral(vTokenCollateral, borrower);\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vTokenCollateral);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, borrower);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, liquidator);\\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external override {\\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 _checkRedeemAllowed(vToken, src, transferTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, src);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, dst);\\n }\\n }\\n\\n /*** Pool-level operations ***/\\n\\n /**\\n * @notice Seizes all the remaining collateral, makes msg.sender repay the existing\\n * borrows, and treats the rest of the debt as bad debt (for each market).\\n * The sender has to repay a certain percentage of the debt, computed as\\n * collateral / (borrows * liquidationIncentive).\\n * @param user account to heal\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for healing\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function healAccount(address user) external {\\n VToken[] memory userAssets = getAssetsIn(user);\\n uint256 userAssetsCount = userAssets.length;\\n\\n address liquidator = msg.sender;\\n {\\n ResilientOracleInterface oracle_ = oracle;\\n // We need all user's markets to be fresh for the computations to be correct\\n for (uint256 i; i < userAssetsCount; ++i) {\\n userAssets[i].accrueInterest();\\n oracle_.updatePrice(address(userAssets[i]));\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(user, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n // percentage = collateral / (borrows * liquidation incentive)\\n Exp memory collateral = Exp({ mantissa: snapshot.totalCollateral });\\n Exp memory scaledBorrows = mul_(\\n Exp({ mantissa: snapshot.borrows }),\\n Exp({ mantissa: liquidationIncentiveMantissa })\\n );\\n\\n Exp memory percentage = div_(collateral, scaledBorrows);\\n if (lessThanExp(Exp({ mantissa: MANTISSA_ONE }), percentage)) {\\n revert CollateralExceedsThreshold(scaledBorrows.mantissa, collateral.mantissa);\\n }\\n\\n for (uint256 i; i < userAssetsCount; ++i) {\\n VToken market = userAssets[i];\\n\\n (uint256 tokens, uint256 borrowBalance, ) = _safeGetAccountSnapshot(market, user);\\n uint256 repaymentAmount = mul_ScalarTruncate(percentage, borrowBalance);\\n\\n // Seize the entire collateral\\n if (tokens != 0) {\\n market.seize(liquidator, user, tokens);\\n }\\n // Repay a certain percentage of the borrow, forgive the rest\\n if (borrowBalance != 0) {\\n market.healBorrow(liquidator, user, repaymentAmount);\\n }\\n }\\n }\\n\\n /**\\n * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than\\n * a predefined threshold, and the account collateral can be seized to cover all borrows. If\\n * the collateral is higher than the threshold, use regular liquidations. If the collateral is\\n * below the threshold, and the account is insolvent, use healAccount.\\n * @param borrower the borrower address\\n * @param orders an array of liquidation orders\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation\\n * @custom:error InsufficientCollateral error is thrown when there is not enough collateral to cover the debt\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function liquidateAccount(address borrower, LiquidationOrder[] calldata orders) external {\\n // We will accrue interest and update the oracle prices later during the liquidation\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n // You should use the regular vToken.liquidateBorrow(...) call\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n uint256 collateralToSeize = mul_ScalarTruncate(\\n Exp({ mantissa: liquidationIncentiveMantissa }),\\n snapshot.borrows\\n );\\n if (collateralToSeize >= snapshot.totalCollateral) {\\n // There is not enough collateral to seize. Use healBorrow to repay some part of the borrow\\n // and record bad debt.\\n revert InsufficientCollateral(collateralToSeize, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n uint256 ordersCount = orders.length;\\n\\n _ensureMaxLoops(ordersCount / 2);\\n\\n for (uint256 i; i < ordersCount; ++i) {\\n if (!markets[address(orders[i].vTokenBorrowed)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenBorrowed));\\n }\\n if (!markets[address(orders[i].vTokenCollateral)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenCollateral));\\n }\\n\\n LiquidationOrder calldata order = orders[i];\\n order.vTokenBorrowed.forceLiquidateBorrow(\\n msg.sender,\\n borrower,\\n order.repayAmount,\\n order.vTokenCollateral,\\n true\\n );\\n }\\n\\n VToken[] memory borrowMarkets = getAssetsIn(borrower);\\n uint256 marketsCount = borrowMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower);\\n require(borrowBalance == 0, \\\"Nonzero borrow balance after liquidation\\\");\\n }\\n }\\n\\n /**\\n * @notice Sets the closeFactor to use when liquidating borrows\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @custom:event Emits NewCloseFactor on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCloseFactor(uint256 newCloseFactorMantissa) external {\\n _checkAccessAllowed(\\\"setCloseFactor(uint256)\\\");\\n require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, \\\"Close factor greater than maximum close factor\\\");\\n require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, \\\"Close factor smaller than minimum close factor\\\");\\n\\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev This function is restricted by the AccessControlManager\\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 * @custom:event Emits NewCollateralFactor when collateral factor is updated\\n * and NewLiquidationThreshold when liquidation threshold is updated\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InvalidCollateralFactor error is thrown when collateral factor is too high\\n * @custom:error InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor\\n * @custom:error PriceError is thrown when the oracle returns an invalid price for the asset\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCollateralFactor(\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external {\\n _checkAccessAllowed(\\\"setCollateralFactor(address,uint256,uint256)\\\");\\n\\n // Verify market is listed\\n Market storage market = markets[address(vToken)];\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Check collateral factor <= 0.9\\n if (newCollateralFactorMantissa > MAX_COLLATERAL_FACTOR_MANTISSA) {\\n revert InvalidCollateralFactor();\\n }\\n\\n // Ensure that liquidation threshold <= 1\\n if (newLiquidationThresholdMantissa > MANTISSA_ONE) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // Ensure that liquidation threshold >= CF\\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n }\\n\\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\\n emit NewLiquidationThreshold(vToken, oldLiquidationThresholdMantissa, newLiquidationThresholdMantissa);\\n }\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev This function is restricted by the AccessControlManager\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @custom:event Emits NewLiquidationIncentive on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external {\\n require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, \\\"liquidation incentive should be greater than 1e18\\\");\\n\\n _checkAccessAllowed(\\\"setLiquidationIncentive(uint256)\\\");\\n\\n // Save current value for use in log\\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\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\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Only callable by the PoolRegistry\\n * @param vToken The address of the market (token) to list\\n * @custom:error MarketAlreadyListed is thrown if the market is already listed in this pool\\n * @custom:access Only PoolRegistry\\n */\\n function supportMarket(VToken vToken) external {\\n _checkSenderIs(poolRegistry);\\n\\n if (markets[address(vToken)].isListed) {\\n revert MarketAlreadyListed(address(vToken));\\n }\\n\\n require(vToken.isVToken(), \\\"Comptroller: Invalid vToken\\\"); // Sanity check to make sure its really a VToken\\n\\n Market storage newMarket = markets[address(vToken)];\\n newMarket.isListed = true;\\n newMarket.collateralFactorMantissa = 0;\\n newMarket.liquidationThresholdMantissa = 0;\\n\\n _addMarket(address(vToken));\\n\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n rewardsDistributors[i].initializeMarket(address(vToken));\\n }\\n\\n emit MarketSupported(vToken);\\n }\\n\\n /**\\n * @notice Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A borrow cap of type(uint256).max corresponds to unlimited borrowing.\\n * @dev Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed\\n until the total borrows amount goes below the new borrow cap\\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 type(uint256).max corresponds to unlimited borrowing.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\\n _checkAccessAllowed(\\\"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 _ensureMaxLoops(numMarkets);\\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 * @notice Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A supply cap of type(uint256).max corresponds to unlimited supply.\\n * @dev Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed\\n until the total supplies amount goes below the new supply cap\\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 type(uint256).max corresponds to unlimited supply.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\\n _checkAccessAllowed(\\\"setMarketSupplyCaps(address[],uint256[])\\\");\\n uint256 vTokensCount = vTokens.length;\\n\\n require(vTokensCount != 0, \\\"invalid number of markets\\\");\\n require(vTokensCount == newSupplyCaps.length, \\\"invalid number of markets\\\");\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Pause/unpause specified actions\\n * @dev This function is restricted by the AccessControlManager\\n * @param marketsList Markets to pause/unpause the actions on\\n * @param actionsList List of action ids to pause/unpause\\n * @param paused The new paused state (true=paused, false=unpaused)\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setActionsPaused(VToken[] calldata marketsList, Action[] calldata actionsList, bool paused) external {\\n _checkAccessAllowed(\\\"setActionsPaused(address[],uint256[],bool)\\\");\\n\\n uint256 marketsCount = marketsList.length;\\n uint256 actionsCount = actionsList.length;\\n\\n _ensureMaxLoops(marketsCount * actionsCount);\\n\\n for (uint256 marketIdx; marketIdx < marketsCount; ++marketIdx) {\\n for (uint256 actionIdx; actionIdx < actionsCount; ++actionIdx) {\\n _setActionPaused(address(marketsList[marketIdx]), actionsList[actionIdx], paused);\\n }\\n }\\n }\\n\\n /**\\n * @notice Set the given collateral threshold for non-batch liquidations. Regular liquidations\\n * will fail if the collateral amount is less than this threshold. Liquidators should use batch\\n * operations like liquidateAccount or healAccount.\\n * @dev This function is restricted by the AccessControlManager\\n * @param newMinLiquidatableCollateral The new min liquidatable collateral (in USD).\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external {\\n _checkAccessAllowed(\\\"setMinLiquidatableCollateral(uint256)\\\");\\n\\n uint256 oldMinLiquidatableCollateral = minLiquidatableCollateral;\\n minLiquidatableCollateral = newMinLiquidatableCollateral;\\n emit NewMinLiquidatableCollateral(oldMinLiquidatableCollateral, newMinLiquidatableCollateral);\\n }\\n\\n /**\\n * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor\\n * contracts with the same rewardToken, and there could be overlaping among them considering the last reward slot (block or second)\\n * @dev Only callable by the admin\\n * @param _rewardsDistributor Address of the RewardDistributor contract to add\\n * @custom:access Only Governance\\n * @custom:event Emits NewRewardsDistributor with distributor address\\n */\\n function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner {\\n require(!rewardsDistributorExists[address(_rewardsDistributor)], \\\"already exists\\\");\\n\\n uint256 rewardsDistributorsLen = rewardsDistributors.length;\\n _ensureMaxLoops(rewardsDistributorsLen + 1);\\n\\n rewardsDistributors.push(_rewardsDistributor);\\n rewardsDistributorExists[address(_rewardsDistributor)] = true;\\n\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n _rewardsDistributor.initializeMarket(address(allMarkets[i]));\\n }\\n\\n emit NewRewardsDistributor(address(_rewardsDistributor), address(_rewardsDistributor.rewardToken()));\\n }\\n\\n /**\\n * @notice Sets a new price oracle for the Comptroller\\n * @dev Only callable by the admin\\n * @param newOracle Address of the new price oracle to set\\n * @custom:event Emits NewPriceOracle on success\\n * @custom:error ZeroAddressNotAllowed is thrown when the new oracle address is zero\\n */\\n function setPriceOracle(ResilientOracleInterface newOracle) external onlyOwner {\\n ensureNonzeroAddress(address(newOracle));\\n\\n ResilientOracleInterface oldOracle = oracle;\\n oracle = newOracle;\\n emit NewPriceOracle(oldOracle, newOracle);\\n }\\n\\n /**\\n * @notice Set the for loop iteration limit to avoid DOS\\n * @param limit Limit for the max loops can execute at a time\\n */\\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Sets the prime token contract for the comptroller\\n * @param _prime Address of the Prime contract\\n */\\n function setPrimeToken(IPrime _prime) external onlyOwner {\\n ensureNonzeroAddress(address(_prime));\\n\\n emit NewPrimeToken(prime, _prime);\\n prime = _prime;\\n }\\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 * @param vTokenBorrowed Borrowed vToken\\n * @param enable Whether to enable forced liquidations\\n */\\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\\n _checkAccessAllowed(\\\"setForcedLiquidation(address,bool)\\\");\\n ensureNonzeroAddress(vTokenBorrowed);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(vTokenBorrowed);\\n }\\n\\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to liquidation threshold requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of liquidation threshold requirements,\\n * @return shortfall Account shortfall below liquidation threshold requirements\\n */\\n function getAccountLiquidity(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getLiquidationThreshold);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to collateral requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of collateral requirements,\\n * @return shortfall Account shortfall below collateral requirements\\n */\\n function getBorrowingPower(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getCollateralFactor);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Hypothetical account liquidity in excess of collateral requirements,\\n * @return shortfall 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 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n account,\\n VToken(vTokenModify),\\n redeemTokens,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\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 markets The list of market addresses\\n */\\n function getAllMarkets() external view override returns (VToken[] memory) {\\n return allMarkets;\\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 /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns whether the given account is entered in a given market\\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 market specified, 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 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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return tokensToSeize Number of vTokenCollateral tokens to be seized in a liquidation\\n * @custom:error PriceError if the oracle returns an invalid price\\n */\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view override returns (uint256 error, uint256 tokensToSeize) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint256 priceBorrowedMantissa = _safeGetUnderlyingPrice(VToken(vTokenBorrowed));\\n uint256 priceCollateralMantissa = _safeGetUnderlyingPrice(VToken(vTokenCollateral));\\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 uint256 exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint256 seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n\\n numerator = mul_(Exp({ mantissa: liquidationIncentiveMantissa }), Exp({ mantissa: priceBorrowedMantissa }));\\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\\n ratio = div_(numerator, denominator);\\n\\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\\n\\n return (NO_ERROR, seizeTokens);\\n }\\n\\n /**\\n * @notice Returns reward speed given a vToken\\n * @param vToken The vToken to get the reward speeds for\\n * @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors\\n */\\n function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {\\n uint256 rewardsDistributorsLength = rewardsDistributors.length;\\n rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);\\n for (uint256 i; i < rewardsDistributorsLength; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n address rewardToken = address(rewardsDistributor.rewardToken());\\n rewardSpeeds[i] = RewardSpeeds({\\n rewardToken: rewardToken,\\n supplySpeed: rewardsDistributor.rewardTokenSupplySpeeds(vToken),\\n borrowSpeed: rewardsDistributor.rewardTokenBorrowSpeeds(vToken)\\n });\\n }\\n return rewardSpeeds;\\n }\\n\\n /**\\n * @notice Return all reward distributors for this pool\\n * @return Array of RewardDistributor addresses\\n */\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory) {\\n return rewardsDistributors;\\n }\\n\\n /**\\n * @notice A marker method that returns true for a valid Comptroller contract\\n * @return Always true\\n */\\n function isComptroller() external pure override returns (bool) {\\n return true;\\n }\\n\\n /**\\n * @notice Update the prices of all the tokens associated with the provided account\\n * @param account Address of the account to get associated tokens with\\n */\\n function updatePrices(address account) public {\\n VToken[] memory vTokens = getAssetsIn(account);\\n uint256 vTokensCount = vTokens.length;\\n\\n ResilientOracleInterface oracle_ = oracle;\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n oracle_.updatePrice(address(vTokens[i]));\\n }\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param market vToken address\\n * @param action Action to check\\n * @return paused True if the action is paused otherwise false\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][action];\\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 list with the assets the account has entered\\n */\\n function getAssetsIn(address account) public 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 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 */\\n function _addToMarket(VToken vToken, address borrower) internal {\\n _checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = markets[address(vToken)];\\n\\n if (!marketToJoin.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return;\\n }\\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\\n /**\\n * @notice Internal function to validate that a market hasn't already been added\\n * and if it hasn't adds it\\n * @param vToken The market to support\\n */\\n function _addMarket(address vToken) internal {\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n if (allMarkets[i] == VToken(vToken)) {\\n revert MarketAlreadyListed(vToken);\\n }\\n }\\n allMarkets.push(VToken(vToken));\\n marketsCount = allMarkets.length;\\n _ensureMaxLoops(marketsCount);\\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 _setActionPaused(address market, Action action, bool paused) internal {\\n require(markets[market].isListed, \\\"cannot pause a market that is not listed\\\");\\n _actionPaused[market][action] = paused;\\n emit ActionPausedMarket(VToken(market), action, paused);\\n }\\n\\n /**\\n * @dev Internal function to check that vTokens can be safely redeemed for the underlying asset.\\n * @param vToken Address of the vTokens to redeem\\n * @param redeemer Account redeeming the tokens\\n * @param redeemTokens The number of tokens to redeem\\n */\\n function _checkRedeemAllowed(address vToken, address redeemer, uint256 redeemTokens) internal {\\n Market storage market = markets[vToken];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!market.accountMembership[redeemer]) {\\n return;\\n }\\n\\n // Update the prices of tokens\\n updatePrices(redeemer);\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n _getCollateralFactor\\n );\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n }\\n\\n /**\\n * @notice Get the total collateral, weighted collateral, borrow balance, liquidity, shortfall\\n * @param account The account to get the snapshot for\\n * @param weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n * liquidation threshold. Accepts the address of the vToken and returns the weight as Exp.\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getCurrentLiquiditySnapshot(\\n address account,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n return _getHypotheticalLiquiditySnapshot(account, VToken(address(0)), 0, 0, weight);\\n }\\n\\n /**\\n * @notice Determine what the supply/borrow balances 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 weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n liquidation threshold. Accepts the address of the VToken and returns the weight\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getHypotheticalLiquiditySnapshot(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n // For each asset the account is in\\n VToken[] memory assets = getAssetsIn(account);\\n uint256 assetsCount = assets.length;\\n\\n for (uint256 i; i < assetsCount; ++i) {\\n VToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the vToken\\n (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) = _safeGetAccountSnapshot(\\n asset,\\n account\\n );\\n\\n // Get the normalized price of the asset\\n Exp memory oraclePrice = Exp({ mantissa: _safeGetUnderlyingPrice(asset) });\\n\\n // Pre-compute conversion factors from vTokens -> usd\\n Exp memory vTokenPrice = mul_(Exp({ mantissa: exchangeRateMantissa }), oraclePrice);\\n Exp memory weightedVTokenPrice = mul_(weight(asset), vTokenPrice);\\n\\n // weightedCollateral += weightedVTokenPrice * vTokenBalance\\n snapshot.weightedCollateral = mul_ScalarTruncateAddUInt(\\n weightedVTokenPrice,\\n vTokenBalance,\\n snapshot.weightedCollateral\\n );\\n\\n // totalCollateral += vTokenPrice * vTokenBalance\\n snapshot.totalCollateral = mul_ScalarTruncateAddUInt(vTokenPrice, vTokenBalance, snapshot.totalCollateral);\\n\\n // borrows += oraclePrice * borrowBalance\\n snapshot.borrows = mul_ScalarTruncateAddUInt(oraclePrice, borrowBalance, snapshot.borrows);\\n\\n // Calculate effects of interacting with vTokenModify\\n if (asset == vTokenModify) {\\n // redeem effect\\n // effects += tokensToDenom * redeemTokens\\n snapshot.effects = mul_ScalarTruncateAddUInt(weightedVTokenPrice, redeemTokens, snapshot.effects);\\n\\n // borrow effect\\n // effects += oraclePrice * borrowAmount\\n snapshot.effects = mul_ScalarTruncateAddUInt(oraclePrice, borrowAmount, snapshot.effects);\\n }\\n }\\n\\n uint256 borrowPlusEffects = snapshot.borrows + snapshot.effects;\\n // These are safe, as the underflow condition is checked first\\n unchecked {\\n if (snapshot.weightedCollateral > borrowPlusEffects) {\\n snapshot.liquidity = snapshot.weightedCollateral - borrowPlusEffects;\\n snapshot.shortfall = 0;\\n } else {\\n snapshot.liquidity = 0;\\n snapshot.shortfall = borrowPlusEffects - snapshot.weightedCollateral;\\n }\\n }\\n\\n return snapshot;\\n }\\n\\n /**\\n * @dev Retrieves price from oracle for an asset and checks it is nonzero\\n * @param asset Address for asset to query price\\n * @return Underlying price\\n */\\n function _safeGetUnderlyingPrice(VToken asset) internal view returns (uint256) {\\n uint256 oraclePriceMantissa = oracle.getUnderlyingPrice(address(asset));\\n if (oraclePriceMantissa == 0) {\\n revert PriceError(address(asset));\\n }\\n return oraclePriceMantissa;\\n }\\n\\n /**\\n * @dev Return collateral factor for a market\\n * @param asset Address for asset\\n * @return Collateral factor as exponential\\n */\\n function _getCollateralFactor(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].collateralFactorMantissa });\\n }\\n\\n /**\\n * @dev Retrieves liquidation threshold for a market as an exponential\\n * @param asset Address for asset to liquidation threshold\\n * @return Liquidation threshold as exponential\\n */\\n function _getLiquidationThreshold(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].liquidationThresholdMantissa });\\n }\\n\\n /**\\n * @dev Returns supply and borrow balances of user in vToken, reverts on failure\\n * @param vToken Market to query\\n * @param user Account address\\n * @return vTokenBalance Balance of vTokens, the same as vToken.balanceOf(user)\\n * @return borrowBalance Borrowed amount, including the interest\\n * @return exchangeRateMantissa Stored exchange rate\\n */\\n function _safeGetAccountSnapshot(\\n VToken vToken,\\n address user\\n ) internal view returns (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) {\\n uint256 err;\\n (err, vTokenBalance, borrowBalance, exchangeRateMantissa) = vToken.getAccountSnapshot(user);\\n if (err != 0) {\\n revert SnapshotError(address(vToken), user);\\n }\\n return (vTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /// @notice Reverts if the call is not from expectedSender\\n /// @param expectedSender Expected transaction sender\\n function _checkSenderIs(address expectedSender) internal view {\\n if (msg.sender != expectedSender) {\\n revert UnexpectedSender(expectedSender, msg.sender);\\n }\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n /// @param market Market to check\\n /// @param action Action to check\\n function _checkActionPauseState(address market, Action action) private view {\\n if (actionPaused(market, action)) {\\n revert ActionPaused(market, action);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7c6e1c6264e4681f82a9ac1bcd9155197a930033291ee5561ad97a56006f5e9c\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.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\\n/**\\n * @title ComptrollerInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract.\\n */\\ninterface ComptrollerInterface {\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\\n\\n function exitMarket(address vToken) external returns (uint256);\\n\\n /*** Policy Hooks ***/\\n\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external;\\n\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external;\\n\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external;\\n\\n function preRepayHook(address vToken, address borrower) external;\\n\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external;\\n\\n function preSeizeHook(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower\\n ) external;\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\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 seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external;\\n\\n function isComptroller() external view returns (bool);\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 repayAmount\\n ) external view returns (uint256, uint256);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n}\\n\\n/**\\n * @title ComptrollerViewInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract, including only some util view functions.\\n */\\ninterface ComptrollerViewInterface {\\n function markets(address) external view returns (bool, uint256);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function closeFactorMantissa() external view returns (uint256);\\n\\n function liquidationIncentiveMantissa() external view returns (uint256);\\n\\n function minLiquidatableCollateral() external view returns (uint256);\\n\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function borrowCaps(address) external view returns (uint256);\\n\\n function supplyCaps(address) external view returns (uint256);\\n\\n function approvedDelegates(address user, address delegate) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xcbf7f9977472650c61345b7cbde23e81f626e1f8863bab4c6ce3dacfc7604919\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { IPrime } from \\\"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\\\";\\nimport { Action } from \\\"./ComptrollerInterface.sol\\\";\\n\\n/**\\n * @title ComptrollerStorage\\n * @author Venus\\n * @notice Storage layout for the `Comptroller` contract.\\n */\\ncontract ComptrollerStorage {\\n struct LiquidationOrder {\\n VToken vTokenCollateral;\\n VToken vTokenBorrowed;\\n uint256 repayAmount;\\n }\\n\\n struct AccountLiquiditySnapshot {\\n uint256 totalCollateral;\\n uint256 weightedCollateral;\\n uint256 borrows;\\n uint256 effects;\\n uint256 liquidity;\\n uint256 shortfall;\\n }\\n\\n struct RewardSpeeds {\\n address rewardToken;\\n uint256 supplySpeed;\\n uint256 borrowSpeed;\\n }\\n\\n struct Market {\\n // Whether or not this market is listed\\n bool isListed;\\n // 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 uint256 collateralFactorMantissa;\\n // 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 uint256 liquidationThresholdMantissa;\\n // Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n }\\n\\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 Per-account mapping of \\\"assets you are in\\\"\\n */\\n mapping(address => VToken[]) public accountAssets;\\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 /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\\n mapping(address => uint256) public borrowCaps;\\n\\n /// @notice Minimal collateral required for regular (non-batch) liquidations\\n uint256 public minLiquidatableCollateral;\\n\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\\n mapping(address => uint256) public supplyCaps;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(Action => bool)) internal _actionPaused;\\n\\n // List of Reward Distributors added\\n RewardsDistributor[] internal rewardsDistributors;\\n\\n // Used to check if rewards distributor is added\\n mapping(address => bool) internal rewardsDistributorExists;\\n\\n /// @notice Flag indicating whether forced liquidation enabled for a market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n\\n uint256 internal constant NO_ERROR = 0;\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant MIN_CLOSE_FACTOR_MANTISSA = 0.05e18; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant MAX_CLOSE_FACTOR_MANTISSA = 0.9e18; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.95e18; // 0.95\\n\\n /// Prime token address\\n IPrime public prime;\\n\\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 /**\\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[47] private __gap;\\n}\\n\",\"keccak256\":\"0x4df44cb65ac152bac2be4b4545430e703005a74a55b72e144100b16421bd8bfd\",\"license\":\"BSD-3-Clause\"},\"contracts/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title TokenErrorReporter\\n * @author Venus\\n * @notice Errors that can be thrown by the `VToken` contract.\\n */\\ncontract TokenErrorReporter {\\n uint256 public constant NO_ERROR = 0; // support legacy return codes\\n\\n error TransferNotAllowed();\\n\\n error MintFreshnessCheck();\\n\\n error RedeemFreshnessCheck();\\n error RedeemTransferOutNotPossible();\\n\\n error BorrowFreshnessCheck();\\n error BorrowCashNotAvailable();\\n error DelegateNotApproved();\\n\\n error RepayBorrowFreshnessCheck();\\n\\n error HealBorrowUnauthorized();\\n error ForceLiquidateBorrowUnauthorized();\\n\\n error LiquidateFreshnessCheck();\\n error LiquidateCollateralFreshnessCheck();\\n error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\\n error LiquidateLiquidatorIsBorrower();\\n error LiquidateCloseAmountIsZero();\\n error LiquidateCloseAmountIsUintMax();\\n\\n error LiquidateSeizeLiquidatorIsBorrower();\\n\\n error ProtocolSeizeShareTooBig();\\n\\n error SetReserveFactorFreshCheck();\\n error SetReserveFactorBoundsCheck();\\n\\n error AddReservesFactorFreshCheck(uint256 actualAddAmount);\\n\\n error ReduceReservesFreshCheck();\\n error ReduceReservesCashNotAvailable();\\n error ReduceReservesCashValidation();\\n\\n error SetInterestRateModelFreshCheck();\\n}\\n\",\"keccak256\":\"0x7a7ced1caaac2d9242659ebd50b99f308c725ce958ac9e11f7ada404b1d97a7b\",\"license\":\"BSD-3-Clause\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from \\\"./lib/constants.sol\\\";\\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 struct Exp {\\n uint256 mantissa;\\n }\\n\\n struct Double {\\n uint256 mantissa;\\n }\\n\\n uint256 internal constant EXP_SCALE = EXP_SCALE_;\\n uint256 internal constant DOUBLE_SCALE = 1e36;\\n uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;\\n uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint256) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / EXP_SCALE;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\\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 // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint256 scalar, uint256 addend) internal pure returns (uint256) {\\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 function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\\n require(n <= type(uint224).max, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\\n require(n <= type(uint32).max, 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_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a + b;\\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_(uint256 a, uint256 b) internal pure returns (uint256) {\\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) / EXP_SCALE });\\n }\\n\\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / EXP_SCALE;\\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) / DOUBLE_SCALE });\\n }\\n\\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / DOUBLE_SCALE;\\n }\\n\\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a * b;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return div_(mul_(a, EXP_SCALE), 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, DOUBLE_SCALE), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return div_(mul_(a, DOUBLE_SCALE), b.mantissa);\\n }\\n\\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a / b;\\n }\\n\\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });\\n }\\n}\\n\",\"keccak256\":\"0x8afbe8a24fe3539c124e718681ed3dcebd24c40dd53095786c0155998213b9b0\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModel.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\nabstract contract InterestRateModel {\\n /**\\n * @notice Calculates the current borrow interest rate per slot (block or second)\\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 amount of reserves the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per slot (block or second)\\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 amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\\n * @return Always true\\n */\\n function isInterestRateModel() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xc4fda1ab75ebe4b187b707c4f10c58780f343cf343c537f641dc75d3cd28ab51\",\"license\":\"BSD-3-Clause\"},\"contracts/Lens/PoolLens.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { IERC20Metadata } from \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Action, ComptrollerInterface, ComptrollerViewInterface } from \\\"../ComptrollerInterface.sol\\\";\\nimport { PoolRegistryInterface } from \\\"../Pool/PoolRegistryInterface.sol\\\";\\nimport { PoolRegistry } from \\\"../Pool/PoolRegistry.sol\\\";\\nimport { RewardsDistributor } from \\\"../Rewards/RewardsDistributor.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\n\\n/**\\n * @title PoolLens\\n * @author Venus\\n * @notice The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information\\n * for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be\\n * looked up for specific pools and markets:\\n- the vToken balance of a given user;\\n- the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address;\\n- the vToken address in a pool for a given asset;\\n- a list of all pools that support an asset;\\n- the underlying asset price of a vToken;\\n- the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\\n */\\ncontract PoolLens is ExponentialNoError, TimeManagerV8 {\\n /**\\n * @dev Struct for PoolDetails.\\n */\\n struct PoolData {\\n string name;\\n address creator;\\n address comptroller;\\n uint256 blockPosted;\\n uint256 timestampPosted;\\n string category;\\n string logoURL;\\n string description;\\n address priceOracle;\\n uint256 closeFactor;\\n uint256 liquidationIncentive;\\n uint256 minLiquidatableCollateral;\\n VTokenMetadata[] vTokens;\\n }\\n\\n /**\\n * @dev Struct for VToken.\\n */\\n struct VTokenMetadata {\\n address vToken;\\n uint256 exchangeRateCurrent;\\n uint256 supplyRatePerBlockOrTimestamp;\\n uint256 borrowRatePerBlockOrTimestamp;\\n uint256 reserveFactorMantissa;\\n uint256 supplyCaps;\\n uint256 borrowCaps;\\n uint256 totalBorrows;\\n uint256 totalReserves;\\n uint256 totalSupply;\\n uint256 totalCash;\\n bool isListed;\\n uint256 collateralFactorMantissa;\\n address underlyingAssetAddress;\\n uint256 vTokenDecimals;\\n uint256 underlyingDecimals;\\n uint256 pausedActions;\\n }\\n\\n /**\\n * @dev Struct for VTokenBalance.\\n */\\n struct VTokenBalances {\\n address vToken;\\n uint256 balanceOf;\\n uint256 borrowBalanceCurrent;\\n uint256 balanceOfUnderlying;\\n uint256 tokenBalance;\\n uint256 tokenAllowance;\\n }\\n\\n /**\\n * @dev Struct for underlyingPrice of VToken.\\n */\\n struct VTokenUnderlyingPrice {\\n address vToken;\\n uint256 underlyingPrice;\\n }\\n\\n /**\\n * @dev Struct with pending reward info for a market.\\n */\\n struct PendingReward {\\n address vTokenAddress;\\n uint256 amount;\\n }\\n\\n /**\\n * @dev Struct with reward distribution totals for a single reward token and distributor.\\n */\\n struct RewardSummary {\\n address distributorAddress;\\n address rewardTokenAddress;\\n uint256 totalRewards;\\n PendingReward[] pendingRewards;\\n }\\n\\n /**\\n * @dev Struct used in RewardDistributor to save last updated market state.\\n */\\n struct RewardTokenState {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number or timestamp the index was last updated at\\n uint256 blockOrTimestamp;\\n // The block number or timestamp at which to stop rewards\\n uint256 lastRewardingBlockOrTimestamp;\\n }\\n\\n /**\\n * @dev Struct with bad debt of a market denominated\\n */\\n struct BadDebt {\\n address vTokenAddress;\\n uint256 badDebtUsd;\\n }\\n\\n /**\\n * @dev Struct with bad debt total denominated in usd for a pool and an array of BadDebt structs for each market\\n */\\n struct BadDebtSummary {\\n address comptroller;\\n uint256 totalBadDebtUsd;\\n BadDebt[] badDebts;\\n }\\n\\n /**\\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) {}\\n\\n /**\\n * @notice Queries the user's supply/borrow balances in vTokens\\n * @param vTokens The list of vToken addresses\\n * @param account The user Account\\n * @return A list of structs containing balances data\\n */\\n function vTokenBalancesAll(VToken[] calldata vTokens, address account) external returns (VTokenBalances[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenBalances[] memory res = new VTokenBalances[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenBalances(vTokens[i], account);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Queries all pools with addtional details for each of them\\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @return Arrays of all Venus pools' data\\n */\\n function getAllPools(address poolRegistryAddress) external view returns (PoolData[] memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n PoolRegistry.VenusPool[] memory venusPools = poolRegistryInterface.getAllPools();\\n uint256 poolLength = venusPools.length;\\n\\n PoolData[] memory poolDataItems = new PoolData[](poolLength);\\n\\n for (uint256 i; i < poolLength; ++i) {\\n PoolRegistry.VenusPool memory venusPool = venusPools[i];\\n PoolData memory poolData = getPoolDataFromVenusPool(poolRegistryAddress, venusPool);\\n poolDataItems[i] = poolData;\\n }\\n\\n return poolDataItems;\\n }\\n\\n /**\\n * @notice Queries the details of a pool identified by Comptroller address\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param comptroller The Comptroller implementation address\\n * @return PoolData structure containing the details of the pool\\n */\\n function getPoolByComptroller(\\n address poolRegistryAddress,\\n address comptroller\\n ) external view returns (PoolData memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return getPoolDataFromVenusPool(poolRegistryAddress, poolRegistryInterface.getPoolByComptroller(comptroller));\\n }\\n\\n /**\\n * @notice Returns vToken holding the specified underlying asset in the specified pool\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param comptroller The pool comptroller\\n * @param asset The underlyingAsset of VToken\\n * @return Address of the vToken\\n */\\n function getVTokenForAsset(\\n address poolRegistryAddress,\\n address comptroller,\\n address asset\\n ) external view returns (address) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return poolRegistryInterface.getVTokenForAsset(comptroller, asset);\\n }\\n\\n /**\\n * @notice Returns all pools that support the specified underlying asset\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param asset The underlying asset of vToken\\n * @return A list of Comptroller contracts\\n */\\n function getPoolsSupportedByAsset(\\n address poolRegistryAddress,\\n address asset\\n ) external view returns (address[] memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return poolRegistryInterface.getPoolsSupportedByAsset(asset);\\n }\\n\\n /**\\n * @notice Returns the price data for the underlying assets of the specified vTokens\\n * @param vTokens The list of vToken addresses\\n * @return An array containing the price data for each asset\\n */\\n function vTokenUnderlyingPriceAll(\\n VToken[] calldata vTokens\\n ) external view returns (VTokenUnderlyingPrice[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenUnderlyingPrice[] memory res = new VTokenUnderlyingPrice[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenUnderlyingPrice(vTokens[i]);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Returns the pending rewards for a user for a given pool.\\n * @param account The user account.\\n * @param comptrollerAddress address\\n * @return Pending rewards array\\n */\\n function getPendingRewards(\\n address account,\\n address comptrollerAddress\\n ) external view returns (RewardSummary[] memory) {\\n VToken[] memory markets = ComptrollerInterface(comptrollerAddress).getAllMarkets();\\n RewardsDistributor[] memory rewardsDistributors = ComptrollerViewInterface(comptrollerAddress)\\n .getRewardDistributors();\\n RewardSummary[] memory rewardSummary = new RewardSummary[](rewardsDistributors.length);\\n for (uint256 i; i < rewardsDistributors.length; ++i) {\\n RewardSummary memory reward;\\n reward.distributorAddress = address(rewardsDistributors[i]);\\n reward.rewardTokenAddress = address(rewardsDistributors[i].rewardToken());\\n reward.totalRewards = rewardsDistributors[i].rewardTokenAccrued(account);\\n reward.pendingRewards = _calculateNotDistributedAwards(account, markets, rewardsDistributors[i]);\\n rewardSummary[i] = reward;\\n }\\n return rewardSummary;\\n }\\n\\n /**\\n * @notice Returns a summary of a pool's bad debt broken down by market\\n *\\n * @param comptrollerAddress Address of the comptroller\\n *\\n * @return badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and\\n * a break down of bad debt by market\\n */\\n function getPoolBadDebt(address comptrollerAddress) external view returns (BadDebtSummary memory) {\\n uint256 totalBadDebtUsd;\\n\\n // Get every market in the pool\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\\n VToken[] memory markets = comptroller.getAllMarkets();\\n ResilientOracleInterface priceOracle = comptroller.oracle();\\n\\n BadDebt[] memory badDebts = new BadDebt[](markets.length);\\n\\n BadDebtSummary memory badDebtSummary;\\n badDebtSummary.comptroller = comptrollerAddress;\\n badDebtSummary.badDebts = badDebts;\\n\\n // // Calculate the bad debt is USD per market\\n for (uint256 i; i < markets.length; ++i) {\\n BadDebt memory badDebt;\\n badDebt.vTokenAddress = address(markets[i]);\\n badDebt.badDebtUsd =\\n (VToken(address(markets[i])).badDebt() * priceOracle.getUnderlyingPrice(address(markets[i]))) /\\n EXP_SCALE;\\n badDebtSummary.badDebts[i] = badDebt;\\n totalBadDebtUsd = totalBadDebtUsd + badDebt.badDebtUsd;\\n }\\n\\n badDebtSummary.totalBadDebtUsd = totalBadDebtUsd;\\n\\n return badDebtSummary;\\n }\\n\\n /**\\n * @notice Queries the user's supply/borrow balances in the specified vToken\\n * @param vToken vToken address\\n * @param account The user Account\\n * @return A struct containing the balances data\\n */\\n function vTokenBalances(VToken vToken, address account) public returns (VTokenBalances memory) {\\n uint256 balanceOf = vToken.balanceOf(account);\\n uint256 borrowBalanceCurrent = vToken.borrowBalanceCurrent(account);\\n uint256 balanceOfUnderlying = vToken.balanceOfUnderlying(account);\\n uint256 tokenBalance;\\n uint256 tokenAllowance;\\n\\n IERC20 underlying = IERC20(vToken.underlying());\\n tokenBalance = underlying.balanceOf(account);\\n tokenAllowance = underlying.allowance(account, address(vToken));\\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 Queries additional information for the pool\\n * @param poolRegistryAddress Address of the PoolRegistry\\n * @param venusPool The VenusPool Object from PoolRegistry\\n * @return Enriched PoolData\\n */\\n function getPoolDataFromVenusPool(\\n address poolRegistryAddress,\\n PoolRegistry.VenusPool memory venusPool\\n ) public view returns (PoolData memory) {\\n // Get tokens in the Pool\\n ComptrollerInterface comptrollerInstance = ComptrollerInterface(venusPool.comptroller);\\n\\n VToken[] memory vTokens = comptrollerInstance.getAllMarkets();\\n\\n VTokenMetadata[] memory vTokenMetadataItems = vTokenMetadataAll(vTokens);\\n\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n\\n PoolRegistry.VenusPoolMetaData memory venusPoolMetaData = poolRegistryInterface.getVenusPoolMetadata(\\n venusPool.comptroller\\n );\\n\\n ComptrollerViewInterface comptrollerViewInstance = ComptrollerViewInterface(venusPool.comptroller);\\n\\n PoolData memory poolData = PoolData({\\n name: venusPool.name,\\n creator: venusPool.creator,\\n comptroller: venusPool.comptroller,\\n blockPosted: venusPool.blockPosted,\\n timestampPosted: venusPool.timestampPosted,\\n category: venusPoolMetaData.category,\\n logoURL: venusPoolMetaData.logoURL,\\n description: venusPoolMetaData.description,\\n vTokens: vTokenMetadataItems,\\n priceOracle: address(comptrollerViewInstance.oracle()),\\n closeFactor: comptrollerViewInstance.closeFactorMantissa(),\\n liquidationIncentive: comptrollerViewInstance.liquidationIncentiveMantissa(),\\n minLiquidatableCollateral: comptrollerViewInstance.minLiquidatableCollateral()\\n });\\n\\n return poolData;\\n }\\n\\n /**\\n * @notice Returns the metadata of VToken\\n * @param vToken The address of vToken\\n * @return VTokenMetadata struct\\n */\\n function vTokenMetadata(VToken vToken) public view returns (VTokenMetadata memory) {\\n uint256 exchangeRateCurrent = vToken.exchangeRateStored();\\n address comptrollerAddress = address(vToken.comptroller());\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\\n (bool isListed, uint256 collateralFactorMantissa) = comptroller.markets(address(vToken));\\n\\n address underlyingAssetAddress = vToken.underlying();\\n uint256 underlyingDecimals = IERC20Metadata(underlyingAssetAddress).decimals();\\n\\n uint256 pausedActions;\\n for (uint8 i; i <= uint8(type(Action).max); ++i) {\\n uint256 paused = ComptrollerInterface(comptrollerAddress).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 supplyRatePerBlockOrTimestamp: vToken.supplyRatePerBlock(),\\n borrowRatePerBlockOrTimestamp: vToken.borrowRatePerBlock(),\\n reserveFactorMantissa: vToken.reserveFactorMantissa(),\\n supplyCaps: comptroller.supplyCaps(address(vToken)),\\n borrowCaps: comptroller.borrowCaps(address(vToken)),\\n totalBorrows: vToken.totalBorrows(),\\n totalReserves: vToken.totalReserves(),\\n totalSupply: vToken.totalSupply(),\\n totalCash: vToken.getCash(),\\n isListed: isListed,\\n collateralFactorMantissa: collateralFactorMantissa,\\n underlyingAssetAddress: underlyingAssetAddress,\\n vTokenDecimals: vToken.decimals(),\\n underlyingDecimals: underlyingDecimals,\\n pausedActions: pausedActions\\n });\\n }\\n\\n /**\\n * @notice Returns the metadata of all VTokens\\n * @param vTokens The list of vToken addresses\\n * @return An array of VTokenMetadata structs\\n */\\n function vTokenMetadataAll(VToken[] memory vTokens) public view returns (VTokenMetadata[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenMetadata[] memory res = new VTokenMetadata[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenMetadata(vTokens[i]);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Returns the price data for the underlying asset of the specified vToken\\n * @param vToken vToken address\\n * @return The price data for each asset\\n */\\n function vTokenUnderlyingPrice(VToken vToken) public view returns (VTokenUnderlyingPrice memory) {\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(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 function _calculateNotDistributedAwards(\\n address account,\\n VToken[] memory markets,\\n RewardsDistributor rewardsDistributor\\n ) internal view returns (PendingReward[] memory) {\\n PendingReward[] memory pendingRewards = new PendingReward[](markets.length);\\n\\n for (uint256 i; i < markets.length; ++i) {\\n // Market borrow and supply state we will modify update in-memory, in order to not modify storage\\n RewardTokenState memory borrowState;\\n RewardTokenState memory supplyState;\\n\\n if (isTimeBased) {\\n (\\n borrowState.index,\\n borrowState.blockOrTimestamp,\\n borrowState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenBorrowStateTimeBased(address(markets[i]));\\n (\\n supplyState.index,\\n supplyState.blockOrTimestamp,\\n supplyState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenSupplyStateTimeBased(address(markets[i]));\\n } else {\\n (\\n borrowState.index,\\n borrowState.blockOrTimestamp,\\n borrowState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenBorrowState(address(markets[i]));\\n (\\n supplyState.index,\\n supplyState.blockOrTimestamp,\\n supplyState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenSupplyState(address(markets[i]));\\n }\\n\\n Exp memory marketBorrowIndex = Exp({ mantissa: markets[i].borrowIndex() });\\n\\n // Update market supply and borrow index in-memory\\n updateMarketBorrowIndex(address(markets[i]), rewardsDistributor, borrowState, marketBorrowIndex);\\n updateMarketSupplyIndex(address(markets[i]), rewardsDistributor, supplyState);\\n\\n // Calculate pending rewards\\n uint256 borrowReward = calculateBorrowerReward(\\n address(markets[i]),\\n rewardsDistributor,\\n account,\\n borrowState,\\n marketBorrowIndex\\n );\\n uint256 supplyReward = calculateSupplierReward(\\n address(markets[i]),\\n rewardsDistributor,\\n account,\\n supplyState\\n );\\n\\n PendingReward memory pendingReward;\\n pendingReward.vTokenAddress = address(markets[i]);\\n pendingReward.amount = borrowReward + supplyReward;\\n pendingRewards[i] = pendingReward;\\n }\\n return pendingRewards;\\n }\\n\\n function updateMarketBorrowIndex(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n RewardTokenState memory borrowState,\\n Exp memory marketBorrowIndex\\n ) internal view {\\n uint256 borrowSpeed = rewardsDistributor.rewardTokenBorrowSpeeds(vToken);\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (\\n borrowState.lastRewardingBlockOrTimestamp > 0 &&\\n blockNumberOrTimestamp > borrowState.lastRewardingBlockOrTimestamp\\n ) {\\n blockNumberOrTimestamp = borrowState.lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, borrowState.blockOrTimestamp);\\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\\n // Remove the total earned interest rate since the opening of the market from total borrows\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, borrowSpeed);\\n Double memory ratio = borrowAmount > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\\n } else if (deltaBlocksOrTimestamp > 0) {\\n borrowState.blockOrTimestamp = blockNumberOrTimestamp;\\n }\\n }\\n\\n function updateMarketSupplyIndex(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n RewardTokenState memory supplyState\\n ) internal view {\\n uint256 supplySpeed = rewardsDistributor.rewardTokenSupplySpeeds(vToken);\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (\\n supplyState.lastRewardingBlockOrTimestamp > 0 &&\\n blockNumberOrTimestamp > supplyState.lastRewardingBlockOrTimestamp\\n ) {\\n blockNumberOrTimestamp = supplyState.lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, supplyState.blockOrTimestamp);\\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, supplySpeed);\\n Double memory ratio = supplyTokens > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\\n } else if (deltaBlocksOrTimestamp > 0) {\\n supplyState.blockOrTimestamp = blockNumberOrTimestamp;\\n }\\n }\\n\\n function calculateBorrowerReward(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n address borrower,\\n RewardTokenState memory borrowState,\\n Exp memory marketBorrowIndex\\n ) internal view returns (uint256) {\\n Double memory borrowIndex = Double({ mantissa: borrowState.index });\\n Double memory borrowerIndex = Double({\\n mantissa: rewardsDistributor.rewardTokenBorrowerIndex(vToken, borrower)\\n });\\n if (borrowerIndex.mantissa == 0 && borrowIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set\\n borrowerIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\\n }\\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n return borrowerDelta;\\n }\\n\\n function calculateSupplierReward(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n address supplier,\\n RewardTokenState memory supplyState\\n ) internal view returns (uint256) {\\n Double memory supplyIndex = Double({ mantissa: supplyState.index });\\n Double memory supplierIndex = Double({\\n mantissa: rewardsDistributor.rewardTokenSupplierIndex(vToken, supplier)\\n });\\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\\n // Covers the case where users supplied tokens before the market's supply state index was set\\n supplierIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\\n }\\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n return supplierDelta;\\n }\\n}\\n\",\"keccak256\":\"0xab04eb777ddc89a994e38e10ef0e776d165f1b7d98a4cf7715464366f931007a\",\"license\":\"BSD-3-Clause\"},\"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\",\"keccak256\":\"0x4c25e30635485d162177effa384eee51768b0141a567a0da16ff6ad673274166\",\"license\":\"BSD-3-Clause\"},\"contracts/Pool/PoolRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\nimport { PoolRegistryInterface } from \\\"./PoolRegistryInterface.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"../lib/validators.sol\\\";\\n\\n/**\\n * @title PoolRegistry\\n * @author Venus\\n * @notice The Isolated Pools architecture centers around the `PoolRegistry` contract. The `PoolRegistry` maintains a directory of isolated lending\\n * pools and can perform actions like creating and registering new pools, adding new markets to existing pools, setting and updating the pool's required\\n * metadata, and providing the getter methods to get information on the pools.\\n *\\n * Isolated lending has three main components: PoolRegistry, pools, and markets. The PoolRegistry is responsible for managing pools.\\n * It can create new pools, update pool metadata and manage markets within pools. PoolRegistry contains getter methods to get the details of\\n * any existing pool like `getVTokenForAsset` and `getPoolsSupportedByAsset`. It also contains methods for updating pool metadata (`updatePoolMetadata`)\\n * and setting pool name (`setPoolName`).\\n *\\n * The directory of pools is managed through two mappings: `_poolByComptroller` which is a hashmap with the comptroller address as the key and `VenusPool` as\\n * the value and `_poolsByID` which is an array of comptroller addresses. Individual pools can be accessed by calling `getPoolByComptroller` with the pool's\\n * comptroller address. `_poolsByID` is used to iterate through all of the pools.\\n *\\n * PoolRegistry also contains a map of asset addresses called `_supportedPools` that maps to an array of assets suppored by each pool. This array of pools by\\n * asset is retrieved by calling `getPoolsSupportedByAsset`.\\n *\\n * PoolRegistry registers new isolated pools in the directory with the `createRegistryPool` method. Isolated pools are composed of independent markets with\\n * specific assets and custom risk management configurations according to their markets.\\n */\\ncontract PoolRegistry is Ownable2StepUpgradeable, AccessControlledV8, PoolRegistryInterface {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n struct AddMarketInput {\\n VToken vToken;\\n uint256 collateralFactor;\\n uint256 liquidationThreshold;\\n uint256 initialSupply;\\n address vTokenReceiver;\\n uint256 supplyCap;\\n uint256 borrowCap;\\n }\\n\\n uint256 internal constant MAX_POOL_NAME_LENGTH = 100;\\n\\n /**\\n * @notice Maps pool's comptroller address to metadata.\\n */\\n mapping(address => VenusPoolMetaData) public metadata;\\n\\n /**\\n * @dev Maps pool ID to pool's comptroller address\\n */\\n mapping(uint256 => address) private _poolsByID;\\n\\n /**\\n * @dev Total number of pools created.\\n */\\n uint256 private _numberOfPools;\\n\\n /**\\n * @dev Maps comptroller address to Venus pool Index.\\n */\\n mapping(address => VenusPool) private _poolByComptroller;\\n\\n /**\\n * @dev Maps pool's comptroller address to asset to vToken.\\n */\\n mapping(address => mapping(address => address)) private _vTokens;\\n\\n /**\\n * @dev Maps asset to list of supported pools.\\n */\\n mapping(address => address[]) private _supportedPools;\\n\\n /**\\n * @notice Emitted when a new Venus pool is added to the directory.\\n */\\n event PoolRegistered(address indexed comptroller, VenusPool pool);\\n\\n /**\\n * @notice Emitted when a pool name is set.\\n */\\n event PoolNameSet(address indexed comptroller, string oldName, string newName);\\n\\n /**\\n * @notice Emitted when a pool metadata is updated.\\n */\\n event PoolMetadataUpdated(\\n address indexed comptroller,\\n VenusPoolMetaData oldMetadata,\\n VenusPoolMetaData newMetadata\\n );\\n\\n /**\\n * @notice Emitted when a Market is added to the pool.\\n */\\n event MarketAdded(address indexed comptroller, address indexed vTokenAddress);\\n\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor() {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializes the deployer to owner\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(address accessControlManager_) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n /**\\n * @notice Adds a new Venus pool to the directory\\n * @dev Price oracle must be configured before adding a pool\\n * @param name The name of the pool\\n * @param comptroller Pool's Comptroller contract\\n * @param closeFactor The pool's close factor (scaled by 1e18)\\n * @param liquidationIncentive The pool's liquidation incentive (scaled by 1e18)\\n * @param minLiquidatableCollateral Minimal collateral for regular (non-batch) liquidations flow\\n * @return index The index of the registered Venus pool\\n * @custom:error ZeroAddressNotAllowed is thrown when Comptroller address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\\n */\\n function addPool(\\n string calldata name,\\n Comptroller comptroller,\\n uint256 closeFactor,\\n uint256 liquidationIncentive,\\n uint256 minLiquidatableCollateral\\n ) external virtual returns (uint256 index) {\\n _checkAccessAllowed(\\\"addPool(string,address,uint256,uint256,uint256)\\\");\\n // Input validation\\n ensureNonzeroAddress(address(comptroller));\\n ensureNonzeroAddress(address(comptroller.oracle()));\\n\\n uint256 poolId = _registerPool(name, address(comptroller));\\n\\n // Set Venus pool parameters\\n comptroller.setCloseFactor(closeFactor);\\n comptroller.setLiquidationIncentive(liquidationIncentive);\\n comptroller.setMinLiquidatableCollateral(minLiquidatableCollateral);\\n\\n return poolId;\\n }\\n\\n /**\\n * @notice Add a market to an existing pool and then mint to provide initial supply\\n * @param input The structure describing the parameters for adding a market to a pool\\n * @custom:error ZeroAddressNotAllowed is thrown when vToken address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when vTokenReceiver address is zero\\n */\\n function addMarket(AddMarketInput memory input) external {\\n _checkAccessAllowed(\\\"addMarket(AddMarketInput)\\\");\\n ensureNonzeroAddress(address(input.vToken));\\n ensureNonzeroAddress(input.vTokenReceiver);\\n require(input.initialSupply > 0, \\\"PoolRegistry: initialSupply is zero\\\");\\n\\n VToken vToken = input.vToken;\\n address vTokenAddress = address(vToken);\\n address comptrollerAddress = address(vToken.comptroller());\\n Comptroller comptroller = Comptroller(comptrollerAddress);\\n address underlyingAddress = vToken.underlying();\\n IERC20Upgradeable underlying = IERC20Upgradeable(underlyingAddress);\\n\\n require(_poolByComptroller[comptrollerAddress].creator != address(0), \\\"PoolRegistry: Pool not registered\\\");\\n // solhint-disable-next-line reason-string\\n require(\\n _vTokens[comptrollerAddress][underlyingAddress] == address(0),\\n \\\"PoolRegistry: Market already added for asset comptroller combination\\\"\\n );\\n\\n comptroller.supportMarket(vToken);\\n comptroller.setCollateralFactor(vToken, input.collateralFactor, input.liquidationThreshold);\\n\\n uint256[] memory newSupplyCaps = new uint256[](1);\\n uint256[] memory newBorrowCaps = new uint256[](1);\\n VToken[] memory vTokens = new VToken[](1);\\n\\n newSupplyCaps[0] = input.supplyCap;\\n newBorrowCaps[0] = input.borrowCap;\\n vTokens[0] = vToken;\\n\\n comptroller.setMarketSupplyCaps(vTokens, newSupplyCaps);\\n comptroller.setMarketBorrowCaps(vTokens, newBorrowCaps);\\n\\n _vTokens[comptrollerAddress][underlyingAddress] = vTokenAddress;\\n _supportedPools[underlyingAddress].push(comptrollerAddress);\\n\\n uint256 amountToSupply = _transferIn(underlying, msg.sender, input.initialSupply);\\n underlying.forceApprove(vTokenAddress, 0);\\n underlying.forceApprove(vTokenAddress, amountToSupply);\\n vToken.mintBehalf(input.vTokenReceiver, amountToSupply);\\n\\n emit MarketAdded(comptrollerAddress, vTokenAddress);\\n }\\n\\n /**\\n * @notice Modify existing Venus pool name\\n * @param comptroller Pool's Comptroller\\n * @param name New pool name\\n */\\n function setPoolName(address comptroller, string calldata name) external {\\n _checkAccessAllowed(\\\"setPoolName(address,string)\\\");\\n _ensureValidName(name);\\n VenusPool storage pool = _poolByComptroller[comptroller];\\n string memory oldName = pool.name;\\n pool.name = name;\\n emit PoolNameSet(comptroller, oldName, name);\\n }\\n\\n /**\\n * @notice Update metadata of an existing pool\\n * @param comptroller Pool's Comptroller\\n * @param metadata_ New pool metadata\\n */\\n function updatePoolMetadata(address comptroller, VenusPoolMetaData calldata metadata_) external {\\n _checkAccessAllowed(\\\"updatePoolMetadata(address,VenusPoolMetaData)\\\");\\n VenusPoolMetaData memory oldMetadata = metadata[comptroller];\\n metadata[comptroller] = metadata_;\\n emit PoolMetadataUpdated(comptroller, oldMetadata, metadata_);\\n }\\n\\n /**\\n * @notice Returns arrays of all Venus pools' data\\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\\n * @return A list of all pools within PoolRegistry, with details for each pool\\n */\\n function getAllPools() external view override returns (VenusPool[] memory) {\\n uint256 numberOfPools_ = _numberOfPools; // storage load to save gas\\n VenusPool[] memory _pools = new VenusPool[](numberOfPools_);\\n for (uint256 i = 1; i <= numberOfPools_; ++i) {\\n address comptroller = _poolsByID[i];\\n _pools[i - 1] = (_poolByComptroller[comptroller]);\\n }\\n return _pools;\\n }\\n\\n /**\\n * @param comptroller The comptroller proxy address associated to the pool\\n * @return Returns Venus pool\\n */\\n function getPoolByComptroller(address comptroller) external view override returns (VenusPool memory) {\\n return _poolByComptroller[comptroller];\\n }\\n\\n /**\\n * @param comptroller comptroller of Venus pool\\n * @return Returns Metadata of Venus pool\\n */\\n function getVenusPoolMetadata(address comptroller) external view override returns (VenusPoolMetaData memory) {\\n return metadata[comptroller];\\n }\\n\\n function getVTokenForAsset(address comptroller, address asset) external view override returns (address) {\\n return _vTokens[comptroller][asset];\\n }\\n\\n function getPoolsSupportedByAsset(address asset) external view override returns (address[] memory) {\\n return _supportedPools[asset];\\n }\\n\\n /**\\n * @dev Adds a new Venus pool to the directory (without checking msg.sender).\\n * @param name The name of the pool\\n * @param comptroller The pool's Comptroller proxy contract address\\n * @return The index of the registered Venus pool\\n */\\n function _registerPool(string calldata name, address comptroller) internal returns (uint256) {\\n VenusPool storage storedPool = _poolByComptroller[comptroller];\\n\\n require(storedPool.creator == address(0), \\\"PoolRegistry: Pool already exists in the directory.\\\");\\n _ensureValidName(name);\\n\\n ++_numberOfPools;\\n uint256 numberOfPools_ = _numberOfPools; // cache on stack to save storage read gas\\n\\n VenusPool memory pool = VenusPool(name, msg.sender, comptroller, block.number, block.timestamp);\\n\\n _poolsByID[numberOfPools_] = comptroller;\\n _poolByComptroller[comptroller] = pool;\\n\\n emit PoolRegistered(comptroller, pool);\\n return numberOfPools_;\\n }\\n\\n function _transferIn(IERC20Upgradeable token, address from, uint256 amount) internal returns (uint256) {\\n uint256 balanceBefore = token.balanceOf(address(this));\\n token.safeTransferFrom(from, address(this), amount);\\n uint256 balanceAfter = token.balanceOf(address(this));\\n return balanceAfter - balanceBefore;\\n }\\n\\n function _ensureValidName(string calldata name) internal pure {\\n require(bytes(name).length <= MAX_POOL_NAME_LENGTH, \\\"Pool's name is too large\\\");\\n }\\n}\\n\",\"keccak256\":\"0xafbb871f7b4db3ef439d846baa5f18a136192f9b43ea695c81262a77b06c4b25\",\"license\":\"BSD-3-Clause\"},\"contracts/Pool/PoolRegistryInterface.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 /**\\n * @notice Struct for a Venus interest rate pool metadata.\\n */\\n struct VenusPoolMetaData {\\n string category;\\n string logoURL;\\n string description;\\n }\\n\\n /// @notice Get all pools in PoolRegistry\\n function getAllPools() external view returns (VenusPool[] memory);\\n\\n /// @notice Get a pool by comptroller address\\n function getPoolByComptroller(address comptroller) external view returns (VenusPool memory);\\n\\n /// @notice Get the address of the VToken contract in the Pool where the underlying token is the provided 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 /// @notice Get the metadata of a Pool by comptroller address\\n function getVenusPoolMetadata(address comptroller) external view returns (VenusPoolMetaData memory);\\n}\\n\",\"keccak256\":\"0x7b39cda3b372a686501ce3c2aad288c6af410148110318249d75d4516729c92c\",\"license\":\"BSD-3-Clause\"},\"contracts/Rewards/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\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 { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"../MaxLoopsLimitHelper.sol\\\";\\nimport { RewardsDistributorStorage } from \\\"./RewardsDistributorStorage.sol\\\";\\n\\n/**\\n * @title `RewardsDistributor`\\n * @author Venus\\n * @notice Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol.\\n * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward\\n * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool.\\n * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward\\n * token to be released each slot (block or second) for borrowers and suppliers, which is distributed based on a user\\u2019s percentage of the borrows or supplies\\n * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting\\n * their contributor reward token speed, which similarly allocates a fixed amount of reward token per slot (block or second).\\n *\\n * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed\\n * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized\\n * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\\n */\\ncontract RewardsDistributor is\\n ExponentialNoError,\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n MaxLoopsLimitHelper,\\n RewardsDistributorStorage,\\n TimeManagerV8\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice The initial REWARD TOKEN index for a market\\n uint224 public constant INITIAL_INDEX = 1e36;\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a supplier\\n event DistributedSupplierRewardToken(\\n VToken indexed vToken,\\n address indexed supplier,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenSupplyIndex\\n );\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a borrower\\n event DistributedBorrowerRewardToken(\\n VToken indexed vToken,\\n address indexed borrower,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenBorrowIndex\\n );\\n\\n /// @notice Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when REWARD TOKEN is granted by admin\\n event RewardTokenGranted(address indexed recipient, uint256 amount);\\n\\n /// @notice Emitted when a new REWARD TOKEN speed is set for a contributor\\n event ContributorRewardTokenSpeedUpdated(address indexed contributor, uint256 newSpeed);\\n\\n /// @notice Emitted when a market is initialized\\n event MarketInitialized(address indexed vToken);\\n\\n /// @notice Emitted when a reward token supply index is updated\\n event RewardTokenSupplyIndexUpdated(address indexed vToken);\\n\\n /// @notice Emitted when a reward token borrow index is updated\\n event RewardTokenBorrowIndexUpdated(address indexed vToken, Exp marketBorrowIndex);\\n\\n /// @notice Emitted when a reward for contributor is updated\\n event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued);\\n\\n /// @notice Emitted when a reward token last rewarding block for supply is updated\\n event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding block for borrow is updated\\n event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding timestamp for supply is updated\\n event SupplyLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\\n\\n /// @notice Emitted when a reward token last rewarding timestamp for borrow is updated\\n event BorrowLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\\n\\n modifier onlyComptroller() {\\n require(address(comptroller) == msg.sender, \\\"Only comptroller can call this function\\\");\\n _;\\n }\\n\\n /**\\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice RewardsDistributor initializer\\n * @dev Initializes the deployer to owner\\n * @param comptroller_ Comptroller to attach the reward distributor to\\n * @param rewardToken_ Reward token to distribute\\n * @param loopsLimit_ Maximum number of iterations for the loops in this contract\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(\\n Comptroller comptroller_,\\n IERC20Upgradeable rewardToken_,\\n uint256 loopsLimit_,\\n address accessControlManager_\\n ) external initializer {\\n comptroller = comptroller_;\\n rewardToken = rewardToken_;\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n\\n _setMaxLoopsLimit(loopsLimit_);\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken\\n * @param vToken The address of the vToken to be initialized\\n * @custom:event MarketInitialized emits on success\\n * @custom:access Only Comptroller\\n */\\n function initializeMarket(address vToken) external onlyComptroller {\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n isTimeBased\\n ? _initializeMarketTimestampBased(vToken, blockNumberOrTimestamp)\\n : _initializeMarketBlockBased(vToken, safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\"));\\n\\n emit MarketInitialized(vToken);\\n }\\n\\n /*** Reward Token Distribution ***/\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them\\n * Borrowers will begin to accrue after the first interaction with the protocol.\\n * @dev This function should only be called when the user has a borrow position in the market\\n * (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook)\\n * We avoid an external call to check if they are in the market to save gas because this function is called in many places\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function distributeBorrowerRewardToken(\\n address vToken,\\n address borrower,\\n Exp memory marketBorrowIndex\\n ) external onlyComptroller {\\n _distributeBorrowerRewardToken(vToken, borrower, marketBorrowIndex);\\n }\\n\\n function updateRewardTokenSupplyIndex(address vToken) external onlyComptroller {\\n _updateRewardTokenSupplyIndex(vToken);\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the recipient\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\\n * @param recipient The address of the recipient to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n */\\n function grantRewardToken(address recipient, uint256 amount) external onlyOwner {\\n uint256 amountLeft = _grantRewardToken(recipient, amount);\\n require(amountLeft == 0, \\\"insufficient rewardToken for grant\\\");\\n emit RewardTokenGranted(recipient, amount);\\n }\\n\\n function updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) external onlyComptroller {\\n _updateRewardTokenBorrowIndex(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN borrow and supply speeds for the specified markets\\n * @param vTokens The markets whose REWARD TOKEN speed to update\\n * @param supplySpeeds New supply-side REWARD TOKEN speed for the corresponding market\\n * @param borrowSpeeds New borrow-side REWARD TOKEN speed for the corresponding market\\n */\\n function setRewardTokenSpeeds(\\n VToken[] memory vTokens,\\n uint256[] memory supplySpeeds,\\n uint256[] memory borrowSpeeds\\n ) external {\\n _checkAccessAllowed(\\\"setRewardTokenSpeeds(address[],uint256[],uint256[])\\\");\\n uint256 numTokens = vTokens.length;\\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \\\"invalid setRewardTokenSpeeds\\\");\\n\\n for (uint256 i; i < numTokens; ++i) {\\n _setRewardTokenSpeed(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for the specified markets, used when contract is block based\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market\\n * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market\\n */\\n function setLastRewardingBlocks(\\n VToken[] calldata vTokens,\\n uint32[] calldata supplyLastRewardingBlocks,\\n uint32[] calldata borrowLastRewardingBlocks\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlocks(address[],uint32[],uint32[])\\\");\\n require(!isTimeBased, \\\"Block-based operation only\\\");\\n\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length,\\n \\\"RewardsDistributor::setLastRewardingBlocks invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlock(vTokens[i], supplyLastRewardingBlocks[i], borrowLastRewardingBlocks[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block timestamp for the specified markets, used when contract is time based\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlockTimestamps New supply-side REWARD TOKEN last rewarding block timestamp for the corresponding market\\n * @param borrowLastRewardingBlockTimestamps New borrow-side REWARD TOKEN last rewarding block timestamp for the corresponding market\\n */\\n function setLastRewardingBlockTimestamps(\\n VToken[] calldata vTokens,\\n uint256[] calldata supplyLastRewardingBlockTimestamps,\\n uint256[] calldata borrowLastRewardingBlockTimestamps\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlockTimestamps(address[],uint256[],uint256[])\\\");\\n require(isTimeBased, \\\"Time-based operation only\\\");\\n\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlockTimestamps.length &&\\n numTokens == borrowLastRewardingBlockTimestamps.length,\\n \\\"RewardsDistributor::setLastRewardingBlockTimestamps invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlockTimestamp(\\n vTokens[i],\\n supplyLastRewardingBlockTimestamps[i],\\n borrowLastRewardingBlockTimestamps[i]\\n );\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single contributor\\n * @param contributor The contributor whose REWARD TOKEN speed to update\\n * @param rewardTokenSpeed New REWARD TOKEN speed for contributor\\n */\\n function setContributorRewardTokenSpeed(address contributor, uint256 rewardTokenSpeed) external onlyOwner {\\n // note that REWARD TOKEN speed could be set to 0 to halt liquidity rewards for a contributor\\n updateContributorRewards(contributor);\\n if (rewardTokenSpeed == 0) {\\n // release storage\\n delete lastContributorBlock[contributor];\\n } else {\\n lastContributorBlock[contributor] = getBlockNumberOrTimestamp();\\n }\\n rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed;\\n\\n emit ContributorRewardTokenSpeedUpdated(contributor, rewardTokenSpeed);\\n }\\n\\n function distributeSupplierRewardToken(address vToken, address supplier) external onlyComptroller {\\n _distributeSupplierRewardToken(vToken, supplier);\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in all markets\\n * @param holder The address to claim REWARD TOKEN for\\n */\\n function claimRewardToken(address holder) external {\\n return claimRewardToken(holder, comptroller.getAllMarkets());\\n }\\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) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Calculate additional accrued REWARD TOKEN for a contributor since last accrual\\n * @param contributor The address to calculate contributor rewards for\\n */\\n function updateContributorRewards(address contributor) public {\\n uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, lastContributorBlock[contributor]);\\n if (deltaBlocksOrTimestamp > 0 && rewardTokenSpeed > 0) {\\n uint256 newAccrued = mul_(deltaBlocksOrTimestamp, rewardTokenSpeed);\\n uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued);\\n\\n rewardTokenAccrued[contributor] = contributorAccrued;\\n lastContributorBlock[contributor] = blockNumberOrTimestamp;\\n\\n emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]);\\n }\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in the specified markets\\n * @param holder The address to claim REWARD TOKEN for\\n * @param vTokens The list of markets to claim REWARD TOKEN in\\n */\\n function claimRewardToken(address holder, VToken[] memory vTokens) public {\\n uint256 vTokensCount = vTokens.length;\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n VToken vToken = vTokens[i];\\n require(comptroller.isMarketListed(vToken), \\\"market must be listed\\\");\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n _distributeBorrowerRewardToken(address(vToken), holder, borrowIndex);\\n _updateRewardTokenSupplyIndex(address(vToken));\\n _distributeSupplierRewardToken(address(vToken), holder);\\n }\\n rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for a single market.\\n * @param vToken market's whose reward token last rewarding block to be updated\\n * @param supplyLastRewardingBlock New supply-side REWARD TOKEN last rewarding block for market\\n * @param borrowLastRewardingBlock New borrow-side REWARD TOKEN last rewarding block for market\\n */\\n function _setLastRewardingBlock(\\n VToken vToken,\\n uint32 supplyLastRewardingBlock,\\n uint32 borrowLastRewardingBlock\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockNumber = getBlockNumberOrTimestamp();\\n\\n require(supplyLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n require(borrowLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n\\n uint32 currentSupplyLastRewardingBlock = rewardTokenSupplyState[address(vToken)].lastRewardingBlock;\\n uint32 currentBorrowLastRewardingBlock = rewardTokenBorrowState[address(vToken)].lastRewardingBlock;\\n\\n require(\\n currentSupplyLastRewardingBlock == 0 || currentSupplyLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlock == 0 || currentBorrowLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlock != supplyLastRewardingBlock) {\\n rewardTokenSupplyState[address(vToken)].lastRewardingBlock = supplyLastRewardingBlock;\\n emit SupplyLastRewardingBlockUpdated(address(vToken), supplyLastRewardingBlock);\\n }\\n\\n if (currentBorrowLastRewardingBlock != borrowLastRewardingBlock) {\\n rewardTokenBorrowState[address(vToken)].lastRewardingBlock = borrowLastRewardingBlock;\\n emit BorrowLastRewardingBlockUpdated(address(vToken), borrowLastRewardingBlock);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding timestamp for a single market.\\n * @param vToken market's whose reward token last rewarding timestamp to be updated\\n * @param supplyLastRewardingBlockTimestamp New supply-side REWARD TOKEN last rewarding timestamp for market\\n * @param borrowLastRewardingBlockTimestamp New borrow-side REWARD TOKEN last rewarding timestamp for market\\n */\\n function _setLastRewardingBlockTimestamp(\\n VToken vToken,\\n uint256 supplyLastRewardingBlockTimestamp,\\n uint256 borrowLastRewardingBlockTimestamp\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockTimestamp = getBlockNumberOrTimestamp();\\n\\n require(\\n supplyLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"setting last rewarding timestamp in the past is not allowed\\\"\\n );\\n require(\\n borrowLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"setting last rewarding timestamp in the past is not allowed\\\"\\n );\\n\\n uint256 currentSupplyLastRewardingBlockTimestamp = rewardTokenSupplyStateTimeBased[address(vToken)]\\n .lastRewardingTimestamp;\\n uint256 currentBorrowLastRewardingBlockTimestamp = rewardTokenBorrowStateTimeBased[address(vToken)]\\n .lastRewardingTimestamp;\\n\\n require(\\n currentSupplyLastRewardingBlockTimestamp == 0 || currentSupplyLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlockTimestamp == 0 || currentBorrowLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlockTimestamp != supplyLastRewardingBlockTimestamp) {\\n rewardTokenSupplyStateTimeBased[address(vToken)].lastRewardingTimestamp = supplyLastRewardingBlockTimestamp;\\n emit SupplyLastRewardingBlockTimestampUpdated(address(vToken), supplyLastRewardingBlockTimestamp);\\n }\\n\\n if (currentBorrowLastRewardingBlockTimestamp != borrowLastRewardingBlockTimestamp) {\\n rewardTokenBorrowStateTimeBased[address(vToken)].lastRewardingTimestamp = borrowLastRewardingBlockTimestamp;\\n emit BorrowLastRewardingBlockTimestampUpdated(address(vToken), borrowLastRewardingBlockTimestamp);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single market.\\n * @param vToken market's whose reward token rate to be updated\\n * @param supplySpeed New supply-side REWARD TOKEN speed for market\\n * @param borrowSpeed New borrow-side REWARD TOKEN speed for market\\n */\\n function _setRewardTokenSpeed(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n if (rewardTokenSupplySpeeds[address(vToken)] != supplySpeed) {\\n // Supply speed updated so let's update supply state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n _updateRewardTokenSupplyIndex(address(vToken));\\n\\n // Update speed and emit event\\n rewardTokenSupplySpeeds[address(vToken)] = supplySpeed;\\n emit RewardTokenSupplySpeedUpdated(vToken, supplySpeed);\\n }\\n\\n if (rewardTokenBorrowSpeeds[address(vToken)] != borrowSpeed) {\\n // Borrow speed updated so let's update borrow state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n\\n // Update speed and emit event\\n rewardTokenBorrowSpeeds[address(vToken)] = borrowSpeed;\\n emit RewardTokenBorrowSpeedUpdated(vToken, borrowSpeed);\\n }\\n }\\n\\n /**\\n * @notice Calculate REWARD TOKEN 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 REWARD TOKEN to\\n */\\n function _distributeSupplierRewardToken(address vToken, address supplier) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\\n\\n uint256 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\\n uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier];\\n\\n // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenSupplierIndex[vToken][supplier] = supplyIndex;\\n\\n if (supplierIndex == 0 && supplyIndex >= INITIAL_INDEX) {\\n // Covers the case where users supplied tokens before the market's supply state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when supplier rewards were first\\n // set for the market.\\n supplierIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per vToken accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\\n\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerVToken\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n\\n uint256 supplierAccrued = add_(rewardTokenAccrued[supplier], supplierDelta);\\n rewardTokenAccrued[supplier] = supplierAccrued;\\n\\n emit DistributedSupplierRewardToken(VToken(vToken), supplier, supplierDelta, supplierAccrued, supplyIndex);\\n }\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them.\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function _distributeBorrowerRewardToken(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\\n\\n uint256 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\\n uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower];\\n\\n // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenBorrowerIndex[vToken][borrower] = borrowIndex;\\n\\n if (borrowerIndex == 0 && borrowIndex >= INITIAL_INDEX) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when borrower rewards were first\\n // set for the market.\\n borrowerIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per borrowed unit accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\\n\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerBorrowedUnit\\n if (borrowerAmount != 0) {\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n\\n uint256 borrowerAccrued = add_(rewardTokenAccrued[borrower], borrowerDelta);\\n rewardTokenAccrued[borrower] = borrowerAccrued;\\n\\n emit DistributedBorrowerRewardToken(VToken(vToken), borrower, borrowerDelta, borrowerAccrued, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the user.\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all.\\n * @param user The address of the user to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n * @return The amount of REWARD TOKEN which was NOT transferred to the user\\n */\\n function _grantRewardToken(address user, uint256 amount) internal returns (uint256) {\\n uint256 rewardTokenRemaining = rewardToken.balanceOf(address(this));\\n if (amount > 0 && amount <= rewardTokenRemaining) {\\n rewardToken.safeTransfer(user, amount);\\n return 0;\\n }\\n return amount;\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the supply index\\n * @param vToken The market whose supply index to update\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenSupplyIndex(address vToken) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\\n\\n uint256 supplySpeed = rewardTokenSupplySpeeds[vToken];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (!isTimeBased) {\\n safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\");\\n }\\n\\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\\n ? supplyStateTimeBased.lastRewardingTimestamp\\n : uint256(supplyState.lastRewardingBlock);\\n\\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(\\n blockNumberOrTimestamp,\\n (isTimeBased ? supplyStateTimeBased.timestamp : uint256(supplyState.block))\\n );\\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, supplySpeed);\\n Double memory ratio = supplyTokens > 0\\n ? fraction(accruedSinceUpdate, supplyTokens)\\n : Double({ mantissa: 0 });\\n uint224 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\\n uint224 index = safe224(\\n add_(Double({ mantissa: supplyIndex }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n\\n if (isTimeBased) {\\n supplyStateTimeBased.index = index;\\n supplyStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n supplyState.index = index;\\n supplyState.block = uint32(blockNumberOrTimestamp);\\n }\\n } else if (deltaBlocksOrTimestamp > 0) {\\n isTimeBased ? supplyStateTimeBased.timestamp = blockNumberOrTimestamp : supplyState.block = uint32(\\n blockNumberOrTimestamp\\n );\\n }\\n\\n emit RewardTokenSupplyIndexUpdated(vToken);\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the borrow index\\n * @param vToken The market whose borrow index to update\\n * @param marketBorrowIndex The current global borrow index of vToken\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\\n\\n uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (!isTimeBased) {\\n safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\");\\n }\\n\\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\\n ? borrowStateTimeBased.lastRewardingTimestamp\\n : uint256(borrowState.lastRewardingBlock);\\n\\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(\\n blockNumberOrTimestamp,\\n (isTimeBased ? borrowStateTimeBased.timestamp : uint256(borrowState.block))\\n );\\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, borrowSpeed);\\n Double memory ratio = borrowAmount > 0\\n ? fraction(accruedSinceUpdate, borrowAmount)\\n : Double({ mantissa: 0 });\\n uint224 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\\n uint224 index = safe224(\\n add_(Double({ mantissa: borrowIndex }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n\\n if (isTimeBased) {\\n borrowStateTimeBased.index = index;\\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n borrowState.index = index;\\n borrowState.block = uint32(blockNumberOrTimestamp);\\n }\\n } else if (deltaBlocksOrTimestamp > 0) {\\n if (isTimeBased) {\\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n borrowState.block = uint32(blockNumberOrTimestamp);\\n }\\n }\\n\\n emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken called when contract is block-based\\n * @param vToken The address of the vToken to be initialized\\n * @param blockNumber current block number\\n */\\n function _initializeMarketBlockBased(address vToken, uint32 blockNumber) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n RewardToken storage borrowState = rewardTokenBorrowState[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 = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block numbers\\n */\\n supplyState.block = borrowState.block = blockNumber;\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken called when contract is time-based\\n * @param vToken The address of the vToken to be initialized\\n * @param blockTimestamp current block timestamp\\n */\\n function _initializeMarketTimestampBased(address vToken, uint256 blockTimestamp) internal {\\n TimeBasedRewardToken storage supplyState = rewardTokenSupplyStateTimeBased[vToken];\\n TimeBasedRewardToken storage borrowState = rewardTokenBorrowStateTimeBased[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 = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block timestamp\\n */\\n supplyState.timestamp = borrowState.timestamp = blockTimestamp;\\n }\\n}\\n\",\"keccak256\":\"0x3cc824e59c923cfe25c4f1a875959b7e9410cde8e73cd405de13f301298c697f\",\"license\":\"BSD-3-Clause\"},\"contracts/Rewards/RewardsDistributorStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\n\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\n\\n/**\\n * @title RewardsDistributorStorage\\n * @author Venus\\n * @dev Storage for RewardsDistributor\\n */\\ncontract RewardsDistributorStorage {\\n struct RewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number the index was last updated at\\n uint32 block;\\n // The block number at which to stop rewards\\n uint32 lastRewardingBlock;\\n }\\n\\n struct TimeBasedRewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block timestamp the index was last updated at\\n uint256 timestamp;\\n // The block timestamp at which to stop rewards\\n uint256 lastRewardingTimestamp;\\n }\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => RewardToken) public rewardTokenSupplyState;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex;\\n\\n /// @notice The REWARD TOKEN accrued but not yet transferred to each user\\n mapping(address => uint256) public rewardTokenAccrued;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding borrow market per slot (block or second)\\n mapping(address => uint256) public rewardTokenBorrowSpeeds;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding supply market per slot (block or second)\\n mapping(address => uint256) public rewardTokenSupplySpeeds;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => RewardToken) public rewardTokenBorrowState;\\n\\n /// @notice The portion of REWARD TOKEN that each contributor receives per slot (block or second)\\n mapping(address => uint256) public rewardTokenContributorSpeeds;\\n\\n /// @notice Last slot (block or second) at which a contributor's REWARD TOKEN rewards have been allocated\\n mapping(address => uint256) public lastContributorBlock;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex;\\n\\n Comptroller internal comptroller;\\n\\n IERC20Upgradeable public rewardToken;\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => TimeBasedRewardToken) public rewardTokenSupplyStateTimeBased;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => TimeBasedRewardToken) public rewardTokenBorrowStateTimeBased;\\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[37] private __gap;\\n}\\n\",\"keccak256\":\"0x70e5015a78a2acf95277949c8b4796e10b9ac194130be006d5e5217e158070c0\",\"license\":\"BSD-3-Clause\"},\"contracts/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\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 { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"@venusprotocol/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\\\";\\n\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { ComptrollerInterface, ComptrollerViewInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"./ErrorReporter.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title VToken\\n * @author Venus\\n * @notice Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview,\\n * each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of\\n * the pool. The main actions a user regularly interacts with in a market are:\\n\\n- mint/redeem of vTokens;\\n- transfer of vTokens;\\n- borrow/repay a loan on an underlying asset;\\n- liquidate a borrow or liquidate/heal an account.\\n\\n * A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`.\\n * The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted\\n * `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken`\\n * as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that\\n * a user may borrow up to a portion of their collateral determined by the market\\u2019s collateral factor. However, if their borrowed amount exceeds an amount\\n * calculated using the market\\u2019s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also\\n * pay off interest accrued on the borrow.\\n * \\n * The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller`\\n * and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a\\n * total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`.\\n * Both functions settle all of an account\\u2019s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of\\n * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\\n */\\ncontract VToken is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n VTokenInterface,\\n ExponentialNoError,\\n TokenErrorReporter,\\n TimeManagerV8\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5%\\n\\n // Maximum fraction of interest that can be set aside for reserves\\n uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18;\\n\\n // Maximum borrow rate that can ever be applied per slot(block or second)\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n uint256 internal immutable MAX_BORROW_RATE_MANTISSA;\\n\\n /**\\n * Reentrancy Guard **\\n */\\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 * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @param maxBorrowRateMantissa_ The maximum value of borrowing rate mantissa\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(\\n bool timeBased_,\\n uint256 blocksPerYear_,\\n uint256 maxBorrowRateMantissa_\\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n require(maxBorrowRateMantissa_ <= 1e18, \\\"Max borrow rate must be <= 1e18\\\");\\n\\n MAX_BORROW_RATE_MANTISSA = maxBorrowRateMantissa_;\\n _disableInitializers();\\n }\\n\\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_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n */\\n function initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) external initializer {\\n ensureNonzeroAddress(admin_);\\n\\n // Initialize the market\\n _initialize(\\n underlying_,\\n comptroller_,\\n interestRateModel_,\\n initialExchangeRateMantissa_,\\n name_,\\n symbol_,\\n decimals_,\\n admin_,\\n accessControlManager_,\\n riskManagement,\\n reserveFactorMantissa_\\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 * @return success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, msg.sender, dst, amount);\\n return true;\\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 success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, src, dst, amount);\\n return true;\\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 (uint256.max means infinite)\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Increase approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param addedValue The number of additional tokens spender can transfer\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function increaseAllowance(address spender, uint256 addedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 newAllowance = transferAllowances[src][spender];\\n newAllowance += addedValue;\\n transferAllowances[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n return true;\\n }\\n\\n /**\\n * @notice Decreases approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param subtractedValue The number of tokens to remove from total approval\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 currentAllowance = transferAllowances[src][spender];\\n require(currentAllowance >= subtractedValue, \\\"decreased allowance below zero\\\");\\n unchecked {\\n currentAllowance -= subtractedValue;\\n }\\n\\n transferAllowances[src][spender] = currentAllowance;\\n\\n emit Approval(src, spender, currentAllowance);\\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 amount The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint256) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return totalBorrows The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\\n accrueInterest();\\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 borrowBalance The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n return _borrowBalanceStored(account);\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function mint(uint256 mintAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _mintFresh(msg.sender, msg.sender, mintAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param minter User whom the supply will be attributed to\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when minter address is zero\\n */\\n function mintBehalf(address minter, uint256 mintAmount) external override nonReentrant returns (uint256) {\\n ensureNonzeroAddress(minter);\\n\\n accrueInterest();\\n\\n _mintFresh(msg.sender, minter, mintAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function redeem(uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _redeemFresh(msg.sender, msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function redeemBehalf(address redeemer, uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n _ensureSenderIsDelegateOf(redeemer);\\n\\n accrueInterest();\\n\\n _redeemFresh(redeemer, msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\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 receive from redeeming vTokens\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n */\\n function redeemUnderlying(uint256 redeemAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _redeemFresh(msg.sender, msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function redeemUnderlyingBehalf(\\n address redeemer,\\n uint256 redeemAmount\\n ) external override nonReentrant returns (uint256) {\\n _ensureSenderIsDelegateOf(redeemer);\\n\\n accrueInterest();\\n\\n _redeemFresh(redeemer, msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function borrow(uint256 borrowAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _borrowFresh(msg.sender, msg.sender, borrowAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error DelegateNotApproved is thrown if caller is not approved delegate\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function borrowBehalf(address borrower, uint256 borrowAmount) external override returns (uint256) {\\n _ensureSenderIsDelegateOf(borrower);\\n accrueInterest();\\n\\n _borrowFresh(borrower, msg.sender, borrowAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrow(uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n return NO_ERROR;\\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, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _repayBorrowFresh(msg.sender, borrower, repayAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Not restricted\\n */\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external override returns (uint256) {\\n _liquidateBorrow(msg.sender, borrower, repayAmount, vTokenCollateral, false);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice sets protocol share accumulated from liquidations\\n * @dev must be equal or less than liquidation incentive - 1\\n * @param newProtocolSeizeShareMantissa_ new protocol share mantissa\\n * @custom:event Emits NewProtocolSeizeShare event on success\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error ProtocolSeizeShareTooBig is thrown when the new seize share is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa_) external {\\n _checkAccessAllowed(\\\"setProtocolSeizeShare(uint256)\\\");\\n uint256 liquidationIncentive = ComptrollerViewInterface(address(comptroller)).liquidationIncentiveMantissa();\\n if (newProtocolSeizeShareMantissa_ + MANTISSA_ONE > liquidationIncentive) {\\n revert ProtocolSeizeShareTooBig();\\n }\\n\\n uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\\n protocolSeizeShareMantissa = newProtocolSeizeShareMantissa_;\\n emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa_);\\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 * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n * @custom:event Emits NewReserveFactor event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant {\\n _checkAccessAllowed(\\\"setReserveFactor(uint256)\\\");\\n\\n accrueInterest();\\n _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to the protocol reserve contract\\n * @dev Gracefully return if reserves already reduced in accrueInterest\\n * @param reduceAmount Amount of reduction to reserves\\n * @custom:event Emits ReservesReduced event; may emit AccrueInterest\\n * @custom:error ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash\\n * @custom:error ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\\n * @custom:access Not restricted\\n */\\n function reduceReserves(uint256 reduceAmount) external override nonReentrant {\\n accrueInterest();\\n if (reduceReservesBlockNumber == getBlockNumberOrTimestamp()) return;\\n _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice The sender adds to reserves.\\n * @param addAmount The amount of underlying token to add as reserves\\n * @custom:event Emits ReservesAdded event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function addReserves(uint256 addAmount) external override nonReentrant {\\n accrueInterest();\\n _addReservesFresh(addAmount);\\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 * @custom:event Emits NewMarketInterestRateModel event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external override {\\n _checkAccessAllowed(\\\"setInterestRateModel(address)\\\");\\n\\n accrueInterest();\\n _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially\\n * \\\"forgiving\\\" the borrower. Healing is a situation that should rarely happen. However, some pools\\n * may list risky assets or be configured improperly \\u2013 we want to still handle such cases gracefully.\\n * We assume that Comptroller does the seizing, so this function is only available to Comptroller.\\n * @dev This function does not call any Comptroller hooks (like \\\"healAllowed\\\"), because we assume\\n * the Comptroller does all the necessary checks before calling this function.\\n * @param payer account who repays the debt\\n * @param borrower account to heal\\n * @param repayAmount amount to repay\\n * @custom:event Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\\n * @custom:error HealBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:access Only Comptroller\\n */\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external override nonReentrant {\\n if (repayAmount != 0) {\\n comptroller.preRepayHook(address(this), borrower);\\n }\\n\\n if (msg.sender != address(comptroller)) {\\n revert HealBorrowUnauthorized();\\n }\\n\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 totalBorrowsNew = totalBorrows;\\n\\n uint256 actualRepayAmount;\\n if (repayAmount != 0) {\\n // _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // We violate checks-effects-interactions here to account for tokens that take transfer fees\\n actualRepayAmount = _doTransferIn(payer, repayAmount);\\n totalBorrowsNew = totalBorrowsNew - actualRepayAmount;\\n emit RepayBorrow(\\n payer,\\n borrower,\\n actualRepayAmount,\\n accountBorrowsPrev - actualRepayAmount,\\n totalBorrowsNew\\n );\\n }\\n\\n // The transaction will fail if trying to repay too much\\n uint256 badDebtDelta = accountBorrowsPrev - actualRepayAmount;\\n if (badDebtDelta != 0) {\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld + badDebtDelta;\\n totalBorrowsNew = totalBorrowsNew - badDebtDelta;\\n badDebt = badDebtNew;\\n\\n // We treat healing as \\\"repayment\\\", where vToken is the payer\\n emit RepayBorrow(address(this), borrower, badDebtDelta, 0, totalBorrowsNew);\\n emit BadDebtIncreased(borrower, badDebtDelta, badDebtOld, badDebtNew);\\n }\\n\\n accountBorrows[borrower].principal = 0;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n emit HealBorrow(payer, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice The extended version of liquidations, callable only by Comptroller. May skip\\n * the close factor check. The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Only Comptroller\\n */\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) external override {\\n if (msg.sender != address(comptroller)) {\\n revert ForceLiquidateBorrowUnauthorized();\\n }\\n _liquidateBorrow(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\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 * @custom:event Emits Transfer, ReservesAdded events\\n * @custom:error LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:access Not restricted\\n */\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external override nonReentrant {\\n _seize(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Updates bad debt\\n * @dev Called only when bad debt is recovered from auction\\n * @param recoveredAmount_ The amount of bad debt recovered\\n * @custom:event Emits BadDebtRecovered event\\n * @custom:access Only Shortfall contract\\n */\\n function badDebtRecovered(uint256 recoveredAmount_) external {\\n require(msg.sender == shortfall, \\\"only shortfall contract can update bad debt\\\");\\n require(recoveredAmount_ <= badDebt, \\\"more than bad debt recovered from auction\\\");\\n\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld - recoveredAmount_;\\n badDebt = badDebtNew;\\n\\n emit BadDebtRecovered(badDebtOld, badDebtNew);\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protocolShareReserve_ The address of the protocol share reserve contract\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n * @custom:access Only Governance\\n */\\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\\n _setProtocolShareReserve(protocolShareReserve_);\\n }\\n\\n /**\\n * @notice Sets shortfall contract address\\n * @param shortfall_ The address of the shortfall contract\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:access Only Governance\\n */\\n function setShortfallContract(address shortfall_) external onlyOwner {\\n _setShortfallContract(shortfall_);\\n }\\n\\n /**\\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\\n * @param token The address of the ERC-20 token to sweep\\n * @custom:access Only Governance\\n */\\n function sweepToken(IERC20Upgradeable token) external override {\\n require(msg.sender == owner(), \\\"VToken::sweepToken: only admin can sweep tokens\\\");\\n require(address(token) != underlying, \\\"VToken::sweepToken: can not sweep underlying token\\\");\\n uint256 balance = token.balanceOf(address(this));\\n token.safeTransfer(owner(), balance);\\n\\n emit SweepToken(address(token));\\n }\\n\\n /**\\n * @notice A public function to set new threshold of slot(block or second) difference after which funds will be sent to the protocol share reserve\\n * @param _newReduceReservesBlockOrTimestampDelta slot(block or second) difference value\\n * @custom:access Only Governance\\n */\\n function setReduceReservesBlockDelta(uint256 _newReduceReservesBlockOrTimestampDelta) external {\\n _checkAccessAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n require(_newReduceReservesBlockOrTimestampDelta > 0, \\\"Invalid Input\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, _newReduceReservesBlockOrTimestampDelta);\\n reduceReservesBlockDelta = _newReduceReservesBlockOrTimestampDelta;\\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 amount 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 amount 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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return vTokenBalance User's balance of vTokens\\n * @return borrowBalance Amount owed in terms of underlying\\n * @return exchangeRate Stored exchange rate\\n */\\n function getAccountSnapshot(\\n address account\\n )\\n external\\n view\\n override\\n returns (uint256 error, uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRate)\\n {\\n return (NO_ERROR, accountTokens[account], _borrowBalanceStored(account), _exchangeRateStored());\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return cash The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint256) {\\n return _getCashPrior();\\n }\\n\\n /**\\n * @notice Returns the current per slot(block or second) borrow interest rate for this vToken\\n * @return rate The borrow interest rate per slot(block or second), scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint256) {\\n return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt);\\n }\\n\\n /**\\n * @notice Returns the current per-slot(block or second) supply interest rate for this v\\n * @return rate The supply interest rate per slot(block or second), scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint256) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPrior(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa,\\n badDebt\\n );\\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 borrowBalance The calculated balance\\n */\\n function borrowBalanceStored(address account) external view override returns (uint256) {\\n return _borrowBalanceStored(account);\\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 exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() external view override returns (uint256) {\\n return _exchangeRateStored();\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\\n accrueInterest();\\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 slot(block or second)\\n * up to the current slot(block or second) and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentSlot - reduceReservesBlockNumber >= slotDelta\\n * @return Always NO_ERROR\\n * @custom:event Emits AccrueInterest event on success\\n * @custom:access Not restricted\\n */\\n function accrueInterest() public virtual override returns (uint256) {\\n /* Remember the initial block number or timestamp */\\n uint256 currentSlotNumber = getBlockNumberOrTimestamp();\\n uint256 accrualSlotNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualSlotNumberPrior == currentSlotNumber) {\\n return NO_ERROR;\\n }\\n\\n /* Read the previous values out of storage */\\n uint256 cashPrior = _getCashPrior();\\n uint256 borrowsPrior = totalBorrows;\\n uint256 reservesPrior = totalReserves;\\n uint256 borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt);\\n require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of slots elapsed since the last accrual */\\n uint256 slotDelta = currentSlotNumber - accrualSlotNumberPrior;\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * slotDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), slotDelta);\\n uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\\n uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;\\n uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentSlotNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n if (currentSlotNumber - reduceReservesBlockNumber >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentSlotNumber;\\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 NO_ERROR;\\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 or timestamp\\n * @param payer The address of the account which is sending the assets for supply\\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 */\\n function _mintFresh(address payer, address minter, uint256 mintAmount) internal {\\n /* Fail if mint not allowed */\\n comptroller.preMintHook(address(this), minter, mintAmount);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert MintFreshnessCheck();\\n }\\n\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\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 * `_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 uint256 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 uint256 mintTokens = div_(actualMintAmount, exchangeRate);\\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 * And write them into storage\\n */\\n totalSupply = totalSupply + mintTokens;\\n uint256 balanceAfter = accountTokens[minter] + mintTokens;\\n accountTokens[minter] = balanceAfter;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, actualMintAmount, mintTokens, balanceAfter);\\n emit Transfer(address(0), minter, mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, actualMintAmount, mintTokens);\\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 Comptroller.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current slot(block or second)\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the underlying 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 */\\n function _redeemFresh(address redeemer, address receiver, uint256 redeemTokensIn, uint256 redeemAmountIn) internal {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert RedeemFreshnessCheck();\\n }\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n\\n uint256 redeemTokens;\\n uint256 redeemAmount;\\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 */\\n redeemTokens = redeemTokensIn;\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n */\\n redeemTokens = div_(redeemAmountIn, exchangeRate);\\n\\n uint256 _redeemAmount = mul_(redeemTokens, exchangeRate);\\n if (_redeemAmount != 0 && _redeemAmount != redeemAmountIn) redeemTokens++; // round up\\n }\\n\\n // redeemAmount = exchangeRate * redeemTokens\\n redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokens);\\n\\n // Revert if amount is zero\\n if (redeemAmount == 0) {\\n revert(\\\"redeemAmount is zero\\\");\\n }\\n\\n /* Fail if redeem not allowed */\\n comptroller.preRedeemHook(address(this), redeemer, redeemTokens);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (_getCashPrior() - totalReserves < redeemAmount) {\\n revert RedeemTransferOutNotPossible();\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\\n */\\n totalSupply = totalSupply - redeemTokens;\\n uint256 balanceAfter = accountTokens[redeemer] - redeemTokens;\\n accountTokens[redeemer] = balanceAfter;\\n\\n /*\\n * We invoke _doTransferOut for the receiver and the redeemAmount.\\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 _doTransferOut(receiver, redeemAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), redeemTokens);\\n emit Redeem(redeemer, redeemAmount, redeemTokens, balanceAfter);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, redeemAmount, redeemTokens);\\n }\\n\\n /**\\n * @notice Users or their delegates borrow assets from the protocol\\n * @param borrower User who borrows the assets\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param borrowAmount The amount of the underlying asset to borrow\\n */\\n function _borrowFresh(address borrower, address receiver, uint256 borrowAmount) internal {\\n /* Fail if borrow not allowed */\\n comptroller.preBorrowHook(address(this), borrower, borrowAmount);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert BorrowFreshnessCheck();\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (_getCashPrior() - totalReserves < borrowAmount) {\\n revert BorrowCashNotAvailable();\\n }\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowNew = accountBorrow + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;\\n uint256 totalBorrowsNew = totalBorrows + borrowAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\\n `*/\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /*\\n * We invoke _doTransferOut for the receiver and the borrowAmount.\\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, accountBorrowsNew, totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\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 underlying tokens being returned, or type(uint256).max for the full outstanding amount\\n * @return (uint) the actual repayment amount.\\n */\\n function _repayBorrowFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256) {\\n /* Fail if repayBorrow not allowed */\\n comptroller.preRepayHook(address(this), borrower);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert RepayBorrowFreshnessCheck();\\n }\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n\\n uint256 repayAmountFinal = repayAmount >= accountBorrowsPrev ? accountBorrowsPrev : 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 * 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 uint256 actualRepayAmount = _doTransferIn(payer, repayAmountFinal);\\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 uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\\n uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, actualRepayAmount, borrowIndex);\\n\\n return actualRepayAmount;\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal nonReentrant {\\n accrueInterest();\\n\\n uint256 error = vTokenCollateral.accrueInterest();\\n if (error != NO_ERROR) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n revert LiquidateAccrueCollateralInterestFailed(error);\\n }\\n\\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal {\\n /* Fail if liquidate not allowed */\\n comptroller.preLiquidateHook(\\n address(this),\\n address(vTokenCollateral),\\n borrower,\\n repayAmount,\\n skipLiquidityCheck\\n );\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert LiquidateFreshnessCheck();\\n }\\n\\n /* Verify vTokenCollateral market's slot(block or second) number equals current slot(block or second) number */\\n if (vTokenCollateral.accrualBlockNumber() != getBlockNumberOrTimestamp()) {\\n revert LiquidateCollateralFreshnessCheck();\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateLiquidatorIsBorrower();\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n revert LiquidateCloseAmountIsZero();\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n revert LiquidateCloseAmountIsUintMax();\\n }\\n\\n /* Fail if repayBorrow fails */\\n uint256 actualRepayAmount = _repayBorrowFresh(liquidator, borrower, repayAmount);\\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.liquidateCalculateSeizeTokens(\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n require(amountSeizeError == 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, call _seize internally to avoid re-entrancy, otherwise make an external call\\n if (address(vTokenCollateral) == address(this)) {\\n _seize(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\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\\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 * It's absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerContract The contract seizing the collateral (either borrowed vToken or Comptroller)\\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 */\\n function _seize(address seizerContract, address liquidator, address borrower, uint256 seizeTokens) internal {\\n /* Fail if seize not allowed */\\n comptroller.preSeizeHook(address(this), seizerContract, liquidator, borrower);\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateSeizeLiquidatorIsBorrower();\\n }\\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 uint256 liquidationIncentiveMantissa = ComptrollerViewInterface(address(comptroller))\\n .liquidationIncentiveMantissa();\\n uint256 numerator = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));\\n uint256 protocolSeizeTokens = div_(numerator, Exp({ mantissa: liquidationIncentiveMantissa }));\\n uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n uint256 protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the calculated values into storage */\\n totalSupply = totalSupply - protocolSeizeTokens;\\n accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\\n accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\\n\\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, protocolSeizeAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.LIQUIDATION\\n );\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\\n emit ProtocolSeize(borrower, protocolShareReserve, protocolSeizeAmount);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerContract, liquidator, borrower, seizeTokens);\\n }\\n\\n function _setComptroller(ComptrollerInterface newComptroller) internal {\\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\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n */\\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal {\\n // Verify market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert SetReserveFactorFreshCheck();\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > MAX_RESERVE_FACTOR_MANTISSA) {\\n revert SetReserveFactorBoundsCheck();\\n }\\n\\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\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 actualAddAmount The actual amount added, excluding the potential token fees\\n */\\n function _addReservesFresh(uint256 addAmount) internal returns (uint256) {\\n // totalReserves + actualAddAmount\\n uint256 totalReservesNew;\\n uint256 actualAddAmount;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert AddReservesFactorFreshCheck(actualAddAmount);\\n }\\n\\n actualAddAmount = _doTransferIn(msg.sender, addAmount);\\n totalReservesNew = totalReserves + actualAddAmount;\\n totalReserves = totalReservesNew;\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n return actualAddAmount;\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to the protocol reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n */\\n function _reduceReservesFresh(uint256 reduceAmount) internal {\\n if (reduceAmount == 0) {\\n return;\\n }\\n // totalReserves - reduceAmount\\n uint256 totalReservesNew;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert ReduceReservesFreshCheck();\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (_getCashPrior() < reduceAmount) {\\n revert ReduceReservesCashNotAvailable();\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n revert ReduceReservesCashValidation();\\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 // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, reduceAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit SpreadReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal {\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert SetInterestRateModelFreshCheck();\\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\\n /**\\n * Safe Token **\\n */\\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 returns (uint256) {\\n IERC20Upgradeable token = IERC20Upgradeable(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 to, uint256 amount) internal virtual {\\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\\n token.safeTransfer(to, amount);\\n }\\n\\n /**\\n * @notice Transfer `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 */\\n function _transferTokens(address spender, address src, address dst, uint256 tokens) internal {\\n /* Fail if transfer not allowed */\\n comptroller.preTransferHook(address(this), src, dst, tokens);\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n revert TransferNotAllowed();\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint256 startingAllowance;\\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 uint256 allowanceNew = startingAllowance - tokens;\\n uint256 srcTokensNew = accountTokens[src] - tokens;\\n uint256 dstTokensNew = accountTokens[dst] + tokens;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n\\n accountTokens[src] = srcTokensNew;\\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\\n /**\\n * @notice Initialize the 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_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n */\\n function _initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\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 _setComptroller(comptroller_);\\n\\n // Initialize slot(block or second) number and borrow index (slot(block or second) number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumberOrTimestamp();\\n borrowIndex = MANTISSA_ONE;\\n\\n // Set the interest rate model (depends on slot(block or second) number / borrow index)\\n _setInterestRateModelFresh(interestRateModel_);\\n\\n _setReserveFactorFresh(reserveFactorMantissa_);\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n _setShortfallContract(riskManagement.shortfall);\\n _setProtocolShareReserve(riskManagement.protocolShareReserve);\\n protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA;\\n\\n // Set underlying and sanity check it\\n underlying = underlying_;\\n IERC20Upgradeable(underlying).totalSupply();\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n _transferOwnership(admin_);\\n }\\n\\n function _setShortfallContract(address shortfall_) internal {\\n ensureNonzeroAddress(shortfall_);\\n address oldShortfall = shortfall;\\n shortfall = shortfall_;\\n emit NewShortfallContract(oldShortfall, shortfall_);\\n }\\n\\n function _setProtocolShareReserve(address payable protocolShareReserve_) internal {\\n ensureNonzeroAddress(protocolShareReserve_);\\n address oldProtocolShareReserve = address(protocolShareReserve);\\n protocolShareReserve = protocolShareReserve_;\\n emit NewProtocolShareReserve(oldProtocolShareReserve, address(protocolShareReserve_));\\n }\\n\\n function _ensureSenderIsDelegateOf(address user) internal view {\\n if (!ComptrollerViewInterface(address(comptroller)).approvedDelegates(user, msg.sender)) {\\n revert DelegateNotApproved();\\n }\\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 virtual returns (uint256) {\\n return IERC20Upgradeable(underlying).balanceOf(address(this));\\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 borrowBalance the calculated balance\\n */\\n function _borrowBalanceStored(address account) internal view returns (uint256) {\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot memory 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 0;\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;\\n\\n return principalTimesIndex / borrowSnapshot.interestIndex;\\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 exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function _exchangeRateStored() internal view virtual returns (uint256) {\\n uint256 _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return initialExchangeRateMantissa;\\n }\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply\\n */\\n uint256 totalCash = _getCashPrior();\\n uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;\\n uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply;\\n\\n return exchangeRate;\\n }\\n}\\n\",\"keccak256\":\"0xa220ca317fe69b920b86e43f054c43b5f891f12160fd312c9a21668f969ee056\",\"license\":\"BSD-3-Clause\"},\"contracts/VTokenInterfaces.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\\nimport { ComptrollerInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title VTokenStorage\\n * @author Venus\\n * @notice Storage layout used by the `VToken` contract\\n */\\n// solhint-disable-next-line max-states-count\\ncontract VTokenStorage {\\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 uint256 principal;\\n uint256 interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\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 Protocol share Reserve contract address\\n */\\n address payable public protocolShareReserve;\\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 InterestRateModel public interestRateModel;\\n\\n // Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n uint256 internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint256 public reserveFactorMantissa;\\n\\n /**\\n * @notice Slot(block or second) number that interest was last accrued at\\n */\\n uint256 public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint256 public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint256 public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint256 public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint256 public totalSupply;\\n\\n /**\\n * @notice Total bad debt of the market\\n */\\n uint256 public badDebt;\\n\\n // Official record of token balances for each account\\n mapping(address => uint256) internal accountTokens;\\n\\n // Approved token transfer amounts on behalf of others\\n mapping(address => mapping(address => uint256)) internal transferAllowances;\\n\\n // Mapping of account addresses to outstanding borrow balances\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint256 public protocolSeizeShareMantissa;\\n\\n /**\\n * @notice Storage of Shortfall contract address\\n */\\n address public shortfall;\\n\\n /**\\n * @notice delta slot (block or second) after which reserves will be reduced\\n */\\n uint256 public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last slot (block or second) number at which reserves were reduced\\n */\\n uint256 public reduceReservesBlockNumber;\\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\\n/**\\n * @title VTokenInterface\\n * @author Venus\\n * @notice Interface implemented by the `VToken` contract\\n */\\nabstract contract VTokenInterface is VTokenStorage {\\n struct RiskManagementInit {\\n address shortfall;\\n address payable protocolShareReserve;\\n }\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address indexed minter, uint256 mintAmount, uint256 mintTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address indexed borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(\\n address indexed payer,\\n address indexed borrower,\\n uint256 repayAmount,\\n uint256 accountBorrows,\\n uint256 totalBorrows\\n );\\n\\n /**\\n * @notice Event emitted when bad debt is accumulated on a market\\n * @param borrower borrower to \\\"forgive\\\"\\n * @param badDebtDelta amount of new bad debt recorded\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtIncreased(address indexed borrower, uint256 badDebtDelta, uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when bad debt is recovered via an auction\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtRecovered(uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address indexed liquidator,\\n address indexed borrower,\\n uint256 repayAmount,\\n address indexed vTokenCollateral,\\n uint256 seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface indexed oldComptroller, ComptrollerInterface indexed newComptroller);\\n\\n /**\\n * @notice Event emitted when shortfall contract address is changed\\n */\\n event NewShortfallContract(address indexed oldShortfall, address indexed newShortfall);\\n\\n /**\\n * @notice Event emitted when protocol share reserve contract address is changed\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModel indexed oldInterestRateModel,\\n InterestRateModel indexed newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when protocol seize share is changed\\n */\\n event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address indexed benefactor, uint256 addAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the spread reserves are reduced\\n */\\n event SpreadReservesReduced(address indexed protocolShareReserve, uint256 reduceAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /**\\n * @notice Event emitted when healing the borrow\\n */\\n event HealBorrow(address indexed payer, address indexed borrower, uint256 repayAmount);\\n\\n /**\\n * @notice Event emitted when tokens are swept\\n */\\n event SweepToken(address indexed token);\\n\\n /**\\n * @notice Event emitted when reduce reserves slot (block or second) delta is changed\\n */\\n event NewReduceReservesBlockDelta(\\n uint256 oldReduceReservesBlockOrTimestampDelta,\\n uint256 newReduceReservesBlockOrTimestampDelta\\n );\\n\\n /**\\n * @notice Event emitted when liquidation reserves are reduced\\n */\\n event ProtocolSeize(address indexed from, address indexed to, uint256 amount);\\n\\n /*** User Interface ***/\\n\\n function mint(uint256 mintAmount) external virtual returns (uint256);\\n\\n function mintBehalf(address minter, uint256 mintAllowed) external virtual returns (uint256);\\n\\n function redeem(uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemBehalf(address redeemer, uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);\\n\\n function redeemUnderlyingBehalf(address redeemer, uint256 redeemAmount) external virtual returns (uint256);\\n\\n function borrow(uint256 borrowAmount) external virtual returns (uint256);\\n\\n function borrowBehalf(address borrwwer, uint256 borrowAmount) external virtual returns (uint256);\\n\\n function repayBorrow(uint256 repayAmount) external virtual returns (uint256);\\n\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external virtual returns (uint256);\\n\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external virtual;\\n\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipCloseFactorCheck\\n ) external virtual;\\n\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external virtual;\\n\\n function transfer(address dst, uint256 amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint256 amount) external virtual returns (bool);\\n\\n function accrueInterest() external virtual returns (uint256);\\n\\n function sweepToken(IERC20Upgradeable token) external virtual;\\n\\n /*** Admin Functions ***/\\n\\n function setReserveFactor(uint256 newReserveFactorMantissa) external virtual;\\n\\n function reduceReserves(uint256 reduceAmount) external virtual;\\n\\n function exchangeRateCurrent() external virtual returns (uint256);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint256);\\n\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external virtual;\\n\\n function addReserves(uint256 addAmount) external virtual;\\n\\n function totalBorrowsCurrent() external virtual returns (uint256);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint256);\\n\\n function approve(address spender, uint256 amount) external virtual returns (bool);\\n\\n function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool);\\n\\n function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint256);\\n\\n function balanceOf(address owner) external view virtual returns (uint256);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint256, uint256, uint256, uint256);\\n\\n function borrowRatePerBlock() external view virtual returns (uint256);\\n\\n function supplyRatePerBlock() external view virtual returns (uint256);\\n\\n function borrowBalanceStored(address account) external view virtual returns (uint256);\\n\\n function exchangeRateStored() external view virtual returns (uint256);\\n\\n function getCash() external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is a VToken contract (for inspection)\\n * @return Always true\\n */\\n function isVToken() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x7c4cbb879e3a931cfee4fa7a9eb1978eddff18087a1c4f56decedb84c2479f1e\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\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\",\"keccak256\":\"0x54ab3a6f3bc87569ed12370f3470a1ec84cea9796d4d0ccf3d07dd4280c044aa\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/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 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\",\"keccak256\":\"0x93bdd5cfb100f0f9a1d446857e23c3633df6ab12c266333c978428edd96b1367\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x60e060405234801561001057600080fd5b50604051613ffc380380613ffc83398101604081905261002f916100dc565b81818115801561003d575080155b1561005b576040516302723dfb60e21b815260040160405180910390fd5b81801561006757508015155b156100855760405163ae0fcab360e01b815260040160405180910390fd5b81151560a05281610096578061009c565b6301e133805b608052816100b3576100d460201b611d89176100be565b6100d860201b611d8d175b6001600160401b031660c0525061010f92505050565b4390565b4290565b600080604083850312156100ef57600080fd5b825180151581146100ff57600080fd5b6020939093015192949293505050565b60805160a05160c051613eb76101456000396000611d5d0152600081816102a60152611e5e015260006101d10152613eb76000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c80637c51b64211610097578063c7ad089511610066578063c7ad0895146102a1578063d77ebf96146102d8578063e0a67f11146102f8578063e1d146fb1461031857600080fd5b80637c51b642146102215780637c84e3b314610241578063aa5dbd2314610261578063b31242391461028157600080fd5b806347d86a81116100d357806347d86a811461018e57806355dd9515146101a15780636857249c146101cc5780637a27db571461020157600080fd5b80630d3ae318146101055780631f884fdf1461012e578063345954dc1461014e5780633e3e399c1461016e575b600080fd5b610118610113366004612ece565b610320565b604051610125919061323b565b60405180910390f35b61014161013c366004613299565b610655565b60405161012591906132da565b61016161015c36600461333a565b61071d565b6040516101259190613357565b61018161017c36600461333a565b610850565b60405161012591906133bb565b61011861019c366004613445565b610bc2565b6101b46101af36600461347e565b610c49565b6040516001600160a01b039091168152602001610125565b6101f37f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610125565b61021461020f366004613445565b610cc9565b60405161012591906134c9565b61023461022f3660046135a5565b610fd6565b6040516101259190613630565b61025461024f36600461333a565b61108f565b604051610125919061367e565b61027461026f36600461333a565b6111f9565b604051610125919061369e565b61029461028f366004613445565b611947565b60405161012591906136ad565b6102c87f000000000000000000000000000000000000000000000000000000000000000081565b6040519015158152602001610125565b6102eb6102e6366004613445565b611c2e565b60405161012591906136bb565b61030b61030636600461371f565b611ca1565b60405161012591906137b8565b6101f3611d56565b610328612c95565b6000826040015190506000816001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610371573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261039991908101906137fb565b905060006103a682611ca1565b60408681015190516328ebbe8b60e21b81526001600160a01b039182166004820152919250879160009183169063a3aefa2c90602401600060405180830381865afa1580156103f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261042191908101906138ce565b90506000876040015190506000604051806101a001604052808a6000015181526020018a602001516001600160a01b031681526020018a604001516001600160a01b031681526020018a6060015181526020018a608001518152602001846000015181526020018460200151815260200184604001518152602001836001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104fe9190613982565b6001600160a01b03168152602001836001600160a01b031663e87554466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561054a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061056e919061399f565b8152602001836001600160a01b0316634ada90af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d5919061399f565b8152602001836001600160a01b031663db5c65de6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610618573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063c919061399f565b8152602001959095525092955050505050505b92915050565b6060816000816001600160401b0381111561067257610672612e17565b6040519080825280602002602001820160405280156106b757816020015b60408051808201909152600080825260208201528152602001906001900390816106905790505b50905060005b82811015610714576106ef8686838181106106da576106da6139b8565b905060200201602081019061024f919061333a565b828281518110610701576107016139b8565b60209081029190910101526001016106bd565b50949350505050565b606060008290506000816001600160a01b031663d88ff1f46040518163ffffffff1660e01b8152600401600060405180830381865afa158015610764573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261078c9190810190613a51565b80519091506000816001600160401b038111156107ab576107ab612e17565b6040519080825280602002602001820160405280156107e457816020015b6107d1612c95565b8152602001906001900390816107c95790505b50905060005b82811015610846576000848281518110610806576108066139b8565b60200260200101519050600061081c8983610320565b905080848481518110610831576108316139b8565b602090810291909101015250506001016107ea565b5095945050505050565b604080516060808201835260008083526020830152918101919091526000808390506000816001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156108b2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108da91908101906137fb565b90506000826001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561091c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109409190613982565b9050600082516001600160401b0381111561095d5761095d612e17565b6040519080825280602002602001820160405280156109a257816020015b604080518082019091526000808252602082015281526020019060019003908161097b5790505b5090506109d2604051806060016040528060006001600160a01b0316815260200160008152602001606081525090565b6001600160a01b03881681526040810182905260005b8451811015610bae576040805180820190915260008082526020820152858281518110610a1757610a176139b8565b602002602001015181600001906001600160a01b031690816001600160a01b031681525050670de0b6b3a7640000856001600160a01b031663fc57d4df888581518110610a6657610a666139b8565b60200260200101516040518263ffffffff1660e01b8152600401610a9991906001600160a01b0391909116815260200190565b602060405180830381865afa158015610ab6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ada919061399f565b878481518110610aec57610aec6139b8565b60200260200101516001600160a01b031663bbcac5576040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b55919061399f565b610b5f9190613b17565b610b699190613b2e565b60208201526040830151805182919084908110610b8857610b886139b8565b6020026020010181905250806020015188610ba39190613b50565b9750506001016109e8565b506020810195909552509295945050505050565b610bca612c95565b604051637aee632d60e01b81526001600160a01b0383811660048301528491610c4191839190821690637aee632d90602401600060405180830381865afa158015610c19573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526101139190810190613b63565b949350505050565b60405163266e0a7f60e01b81526001600160a01b0383811660048301528281166024830152600091859182169063266e0a7f90604401602060405180830381865afa158015610c9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc09190613982565b95945050505050565b60606000826001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610d0b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d3391908101906137fb565b90506000836001600160a01b03166361252fd16040518163ffffffff1660e01b8152600401600060405180830381865afa158015610d75573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d9d9190810190613b97565b9050600081516001600160401b03811115610dba57610dba612e17565b604051908082528060200260200182016040528015610e0b57816020015b6040805160808101825260008082526020808301829052928201526060808201528252600019909201910181610dd85790505b50905060005b8251811015610846576040805160808101825260008082526020820181905291810191909152606080820152838281518110610e4f57610e4f6139b8565b60209081029190910101516001600160a01b031681528351849083908110610e7957610e796139b8565b60200260200101516001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ebe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee29190613982565b6001600160a01b031660208201528351849083908110610f0457610f046139b8565b6020908102919091010151604051631627ee8960e01b81526001600160a01b038a8116600483015290911690631627ee8990602401602060405180830381865afa158015610f56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7a919061399f565b816040018181525050610fa78886868581518110610f9a57610f9a6139b8565b6020026020010151611d91565b816060018190525080838381518110610fc257610fc26139b8565b602090810291909101015250600101610e11565b6060826000816001600160401b03811115610ff357610ff3612e17565b60405190808252806020026020018201604052801561102c57816020015b611019612d18565b8152602001906001900390816110115790505b50905060005b828110156108465761106a87878381811061104f5761104f6139b8565b9050602002016020810190611064919061333a565b86611947565b82828151811061107c5761107c6139b8565b6020908102919091010152600101611032565b60408051808201909152600080825260208201526000826001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111079190613982565b90506000816001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611149573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116d9190613982565b6040805180820182526001600160a01b03808816808352925163fc57d4df60e01b815260048101939093529293509160208301919084169063fc57d4df90602401602060405180830381865afa1580156111cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ef919061399f565b9052949350505050565b611201612d57565b6000826001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611241573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611265919061399f565b90506000836001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cb9190613982565b604051638e8f294b60e01b81526001600160a01b03868116600483015291925082916000918291841690638e8f294b906024016040805180830381865afa15801561131a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133e9190613c35565b915091506000876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a69190613982565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061140c9190613c61565b60ff1690506000805b600860ff8216116114d2576000886001600160a01b031663e85a29608d8460ff16600881111561144757611447613c84565b6040518363ffffffff1660e01b8152600401611464929190613c9a565b602060405180830381865afa158015611481573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a59190613cd5565b6114b05760006114b3565b60015b60ff9081169083161b9290921791506114cb81613cf0565b9050611415565b506040518061022001604052808b6001600160a01b031681526020018981526020018b6001600160a01b031663ae9d70b06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611532573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611556919061399f565b81526020018b6001600160a01b031663f8f9da286040518163ffffffff1660e01b8152600401602060405180830381865afa158015611599573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115bd919061399f565b81526020018b6001600160a01b031663173b99046040518163ffffffff1660e01b8152600401602060405180830381865afa158015611600573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611624919061399f565b81526040516302c3bcbb60e01b81526001600160a01b038d811660048301526020909201918916906302c3bcbb90602401602060405180830381865afa158015611672573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611696919061399f565b815260405163252c221960e11b81526001600160a01b038d81166004830152602090920191891690634a58443290602401602060405180830381865afa1580156116e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611708919061399f565b81526020018b6001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561174b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176f919061399f565b81526020018b6001600160a01b0316638f840ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117d6919061399f565b81526020018b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611819573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061183d919061399f565b81526020018b6001600160a01b0316633b1d21a26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611880573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118a4919061399f565b81526020018615158152602001858152602001846001600160a01b031681526020018b6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611904573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119289190613c61565b60ff168152602081019390935260409092015298975050505050505050565b61194f612d18565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908516906370a0823190602401602060405180830381865afa158015611999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119bd919061399f565b6040516305eff7ef60e21b81526001600160a01b0385811660048301529192506000918616906317bfdfbc906024016020604051808303816000875af1158015611a0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a2f919061399f565b604051633af9e66960e01b81526001600160a01b038681166004830152919250600091871690633af9e669906024016020604051808303816000875af1158015611a7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa1919061399f565b90506000806000886001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0a9190613982565b6040516370a0823160e01b81526001600160a01b038a81166004830152919250908216906370a0823190602401602060405180830381865afa158015611b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b78919061399f565b604051636eb1769f60e11b81526001600160a01b038a811660048301528b811660248301529194509082169063dd62ed3e90604401602060405180830381865afa158015611bca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bee919061399f565b6040805160c0810182526001600160a01b038c168152602081019890985287019590955250506060840191909152608083015260a0820152905092915050565b604051631e6db74760e31b81526001600160a01b038281166004830152606091849182169063f36dba3890602401600060405180830381865afa158015611c79573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c419190810190613d0f565b80516060906000816001600160401b03811115611cc057611cc0612e17565b604051908082528060200260200182016040528015611cf957816020015b611ce6612d57565b815260200190600190039081611cde5790505b50905060005b82811015611d4e57611d29858281518110611d1c57611d1c6139b8565b60200260200101516111f9565b828281518110611d3b57611d3b6139b8565b6020908102919091010152600101611cff565b509392505050565b6000611d847f000000000000000000000000000000000000000000000000000000000000000063ffffffff16565b905090565b4390565b4290565b6060600083516001600160401b03811115611dae57611dae612e17565b604051908082528060200260200182016040528015611df357816020015b6040805180820190915260008082526020820152815260200190600190039081611dcc5790505b50905060005b845181101561071457611e2f604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b611e5c604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b7f000000000000000000000000000000000000000000000000000000000000000015611fdf57856001600160a01b0316638f693ec7888581518110611ea357611ea36139b8565b60200260200101516040518263ffffffff1660e01b8152600401611ed691906001600160a01b0391909116815260200190565b606060405180830381865afa158015611ef3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f179190613db4565b604085015260208401526001600160e01b0316825286516001600160a01b03871690638181494590899086908110611f5157611f516139b8565b60200260200101516040518263ffffffff1660e01b8152600401611f8491906001600160a01b0391909116815260200190565b606060405180830381865afa158015611fa1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fc59190613db4565b604084015260208301526001600160e01b0316815261214a565b856001600160a01b0316632c427b57888581518110612000576120006139b8565b60200260200101516040518263ffffffff1660e01b815260040161203391906001600160a01b0391909116815260200190565b606060405180830381865afa158015612050573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120749190613dfd565b63ffffffff90811660408601521660208401526001600160e01b0316825286516001600160a01b038716906392a18235908990869081106120b7576120b76139b8565b60200260200101516040518263ffffffff1660e01b81526004016120ea91906001600160a01b0391909116815260200190565b606060405180830381865afa158015612107573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061212b9190613dfd565b63ffffffff90811660408501521660208301526001600160e01b031681525b60006040518060200160405280898681518110612169576121696139b8565b60200260200101516001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121d2919061399f565b81525090506121fc8885815181106121ec576121ec6139b8565b60200260200101518885846122f1565b612220888581518110612211576122116139b8565b602002602001015188846124f2565b6000612248898681518110612237576122376139b8565b6020026020010151898c87866126e9565b905060006122718a8781518110612261576122616139b8565b60200260200101518a8d87612919565b60408051808201909152600080825260208201529091508a878151811061229a5761229a6139b8565b60209081029190910101516001600160a01b031681526122ba8284613b50565b6020820152875181908990899081106122d5576122d56139b8565b6020026020010181905250505050505050806001019050611df9565b604051637c05a7c560e01b81526001600160a01b03858116600483015260009190851690637c05a7c590602401602060405180830381865afa15801561233b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061235f919061399f565b9050600061236b611d56565b9050600084604001511180156123845750836040015181115b15612390575060408301515b60006123a0828660200151612b3d565b90506000811180156123b25750600083115b156124db576000612424886001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061241e919061399f565b86612b50565b905060006124328386612b6e565b90506000808311612452576040518060200160405280600081525061245c565b61245c8284612b7a565b9050600061248560405180602001604052808b600001516001600160e01b031681525083612bbf565b90506124c08160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612beb565b6001600160e01b0316895250505050602085018290526124e9565b80156124e957602085018290525b50505050505050565b604051631d31307360e21b81526001600160a01b038481166004830152600091908416906374c4c1cc90602401602060405180830381865afa15801561253c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612560919061399f565b9050600061256c611d56565b9050600083604001511180156125855750826040015181115b15612591575060408201515b60006125a1828560200151612b3d565b90506000811180156125b35750600083115b156126d3576000866001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156125f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061261c919061399f565b9050600061262a8386612b6e565b9050600080831161264a5760405180602001604052806000815250612654565b6126548284612b7a565b9050600061267d60405180602001604052808a600001516001600160e01b031681525083612bbf565b90506126b88160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612beb565b6001600160e01b0316885250505050602084018290526126e1565b80156126e157602084018290525b505050505050565b604080516020808201835284516001600160e01b031682528251908101928390526336fe846560e11b9092526001600160a01b0387811660248401528581166044840152600092839181908916636dfd08ca60648301602060405180830381865afa15801561275c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612780919061399f565b905280519091501580156128025750866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f19190613e40565b6001600160e01b0316826000015110155b1561287557866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612845573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128699190613e40565b6001600160e01b031681525b60006128818383612c27565b6040516395dd919360e01b81526001600160a01b0389811660048301529192506000916128fc91908c16906395dd919390602401602060405180830381865afa1580156128d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128f6919061399f565b87612b50565b9050600061290a8284612c53565b9b9a5050505050505050505050565b604080516020808201835283516001600160e01b0316825282519081019283905263552c097160e01b9092526001600160a01b038681166024840152848116604484015260009283918190881663552c097160648301602060405180830381865afa15801561298c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129b0919061399f565b90528051909150158015612a325750856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a219190613e40565b6001600160e01b0316826000015110155b15612aa557856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a999190613e40565b6001600160e01b031681525b6000612ab18383612c27565b6040516370a0823160e01b81526001600160a01b0388811660048301529192506000918a16906370a0823190602401602060405180830381865afa158015612afd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b21919061399f565b90506000612b2f8284612c53565b9a9950505050505050505050565b6000612b498284613e5b565b9392505050565b6000612b49612b6784670de0b6b3a7640000612b6e565b8351612c7d565b6000612b498284613b17565b6040805160208101909152600081526040518060200160405280612bb6612bb0866ec097ce7bc90715b34b9f1000000000612b6e565b85612c7d565b90529392505050565b6040805160208101909152600081526040518060200160405280612bb685600001518560000151612c89565b6000816001600160e01b03841115612c1f5760405162461bcd60e51b8152600401612c169190613e6e565b60405180910390fd5b509192915050565b6040805160208101909152600081526040518060200160405280612bb685600001518560000151612b3d565b60006ec097ce7bc90715b34b9f1000000000612c73848460000151612b6e565b612b499190613b2e565b6000612b498284613b2e565b6000612b498284613b50565b604051806101a001604052806060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160608152602001606081526020016060815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001606081525090565b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180610220016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b6001600160a01b0381168114612e0457600080fd5b50565b8035612e1281612def565b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715612e4f57612e4f612e17565b60405290565b604051606081016001600160401b0381118282101715612e4f57612e4f612e17565b604051601f8201601f191681016001600160401b0381118282101715612e9f57612e9f612e17565b604052919050565b60006001600160401b03821115612ec057612ec0612e17565b50601f01601f191660200190565b60008060408385031215612ee157600080fd5b8235612eec81612def565b91506020838101356001600160401b0380821115612f0957600080fd5b9085019060a08288031215612f1d57600080fd5b612f25612e2d565b823582811115612f3457600080fd5b83019150601f82018813612f4757600080fd5b8135612f5a612f5582612ea7565b612e77565b8181528986838601011115612f6e57600080fd5b818685018783013760008683830101528083525050612f8e848401612e07565b84820152612f9e60408401612e07565b60408201526060830135606082015260808301356080820152809450505050509250929050565b60005b83811015612fe0578181015183820152602001612fc8565b50506000910152565b60008151808452613001816020860160208601612fc5565b601f01601f19169290920160200192915050565b80516001600160a01b031682526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e0830152610100808201518184015250610120808201518184015250610140808201518184015250610160808201516130a08285018215159052565b505061018081810151908301526101a0808201516001600160a01b0316908301526101c080820151908301526101e0808201519083015261020090810151910152565b60008151808452602080850194506020840160005b8381101561311f5761310b878351613015565b6102209690960195908201906001016130f8565b509495945050505050565b60006101a0825181855261314082860182612fe9565b915050602083015161315d60208601826001600160a01b03169052565b50604083015161317860408601826001600160a01b03169052565b50606083015160608501526080830151608085015260a083015184820360a08601526131a48282612fe9565b91505060c083015184820360c08601526131be8282612fe9565b91505060e083015184820360e08601526131d88282612fe9565b915050610100808401516131f6828701826001600160a01b03169052565b5050610120838101519085015261014080840151908501526101608084015190850152610180808401518583038287015261323183826130e3565b9695505050505050565b602081526000612b49602083018461312a565b60008083601f84011261326057600080fd5b5081356001600160401b0381111561327757600080fd5b6020830191508360208260051b850101111561329257600080fd5b9250929050565b600080602083850312156132ac57600080fd5b82356001600160401b038111156132c257600080fd5b6132ce8582860161324e565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b8281101561332d5761331d84835180516001600160a01b03168252602090810151910152565b92840192908501906001016132f7565b5091979650505050505050565b60006020828403121561334c57600080fd5b8135612b4981612def565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156133ae57603f1988860301845261339c85835161312a565b94509285019290850190600101613380565b5092979650505050505050565b602080825282516001600160a01b03168282015282810151604080840191909152808401516060808501528051608085018190526000939291830191849160a08701905b808410156134395761342582865180516001600160a01b03168252602090810151910152565b9385019360019390930192908201906133ff565b50979650505050505050565b6000806040838503121561345857600080fd5b823561346381612def565b9150602083013561347381612def565b809150509250929050565b60008060006060848603121561349357600080fd5b833561349e81612def565b925060208401356134ae81612def565b915060408401356134be81612def565b809150509250925092565b600060208083018184528085518083526040925060408601915060408160051b8701018488016000805b8481101561359657898403603f19018652825180516001600160a01b03908116865289820151168986015287810151888601526060908101516080918601829052805191860182905289019060a086019084905b808210156135815761356d83855180516001600160a01b03168252602090810151910152565b928b0192918a019160019190910190613547565b505096890196945050918701916001016134f3565b50919998505050505050505050565b6000806000604084860312156135ba57600080fd5b83356001600160401b038111156135d057600080fd5b6135dc8682870161324e565b90945092505060208401356134be81612def565b80516001600160a01b031682526020808201519083015260408082015190830152606080820151908301526080808201519083015260a090810151910152565b6020808252825182820181905260009190848201906040850190845b818110156136725761365f8385516135f0565b9284019260c0929092019160010161364c565b50909695505050505050565b81516001600160a01b03168152602080830151908201526040810161064f565b610220810161064f8284613015565b60c0810161064f82846135f0565b6020808252825182820181905260009190848201906040850190845b818110156136725783516001600160a01b0316835292840192918401916001016136d7565b60006001600160401b0382111561371557613715612e17565b5060051b60200190565b6000602080838503121561373257600080fd5b82356001600160401b0381111561374857600080fd5b8301601f8101851361375957600080fd5b8035613767612f55826136fc565b81815260059190911b8201830190838101908783111561378657600080fd5b928401925b828410156137ad57833561379e81612def565b8252928401929084019061378b565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b81811015613672576137e7838551613015565b9284019261022092909201916001016137d4565b6000602080838503121561380e57600080fd5b82516001600160401b0381111561382457600080fd5b8301601f8101851361383557600080fd5b8051613843612f55826136fc565b81815260059190911b8201830190838101908783111561386257600080fd5b928401925b828410156137ad57835161387a81612def565b82529284019290840190613867565b600082601f83011261389a57600080fd5b81516138a8612f5582612ea7565b8181528460208386010111156138bd57600080fd5b610c41826020830160208701612fc5565b6000602082840312156138e057600080fd5b81516001600160401b03808211156138f757600080fd5b908301906060828603121561390b57600080fd5b613913612e55565b82518281111561392257600080fd5b61392e87828601613889565b82525060208301518281111561394357600080fd5b61394f87828601613889565b60208301525060408301518281111561396757600080fd5b61397387828601613889565b60408301525095945050505050565b60006020828403121561399457600080fd5b8151612b4981612def565b6000602082840312156139b157600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600060a082840312156139e057600080fd5b6139e8612e2d565b905081516001600160401b03811115613a0057600080fd5b613a0c84828501613889565b8252506020820151613a1d81612def565b60208201526040820151613a3081612def565b80604083015250606082015160608201526080820151608082015292915050565b60006020808385031215613a6457600080fd5b82516001600160401b0380821115613a7b57600080fd5b818501915085601f830112613a8f57600080fd5b8151613a9d612f55826136fc565b81815260059190911b83018401908481019088831115613abc57600080fd5b8585015b83811015613af457805185811115613ad85760008081fd5b613ae68b89838a01016139ce565b845250918601918601613ac0565b5098975050505050505050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761064f5761064f613b01565b600082613b4b57634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561064f5761064f613b01565b600060208284031215613b7557600080fd5b81516001600160401b03811115613b8b57600080fd5b610c41848285016139ce565b60006020808385031215613baa57600080fd5b82516001600160401b03811115613bc057600080fd5b8301601f81018513613bd157600080fd5b8051613bdf612f55826136fc565b81815260059190911b82018301908381019087831115613bfe57600080fd5b928401925b828410156137ad578351613c1681612def565b82529284019290840190613c03565b80518015158114612e1257600080fd5b60008060408385031215613c4857600080fd5b613c5183613c25565b9150602083015190509250929050565b600060208284031215613c7357600080fd5b815160ff81168114612b4957600080fd5b634e487b7160e01b600052602160045260246000fd5b6001600160a01b03831681526040810160098310613cc857634e487b7160e01b600052602160045260246000fd5b8260208301529392505050565b600060208284031215613ce757600080fd5b612b4982613c25565b600060ff821660ff8103613d0657613d06613b01565b60010192915050565b60006020808385031215613d2257600080fd5b82516001600160401b03811115613d3857600080fd5b8301601f81018513613d4957600080fd5b8051613d57612f55826136fc565b81815260059190911b82018301908381019087831115613d7657600080fd5b928401925b828410156137ad578351613d8e81612def565b82529284019290840190613d7b565b80516001600160e01b0381168114612e1257600080fd5b600080600060608486031215613dc957600080fd5b613dd284613d9d565b925060208401519150604084015190509250925092565b805163ffffffff81168114612e1257600080fd5b600080600060608486031215613e1257600080fd5b613e1b84613d9d565b9250613e2960208501613de9565b9150613e3760408501613de9565b90509250925092565b600060208284031215613e5257600080fd5b612b4982613d9d565b8181038181111561064f5761064f613b01565b602081526000612b496020830184612fe956fea2646970667358221220b9946cc7fdc900bd3735319cd04868b3796a2261574b7617c9cbf91cb2f997ca64736f6c63430008190033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101005760003560e01c80637c51b64211610097578063c7ad089511610066578063c7ad0895146102a1578063d77ebf96146102d8578063e0a67f11146102f8578063e1d146fb1461031857600080fd5b80637c51b642146102215780637c84e3b314610241578063aa5dbd2314610261578063b31242391461028157600080fd5b806347d86a81116100d357806347d86a811461018e57806355dd9515146101a15780636857249c146101cc5780637a27db571461020157600080fd5b80630d3ae318146101055780631f884fdf1461012e578063345954dc1461014e5780633e3e399c1461016e575b600080fd5b610118610113366004612ece565b610320565b604051610125919061323b565b60405180910390f35b61014161013c366004613299565b610655565b60405161012591906132da565b61016161015c36600461333a565b61071d565b6040516101259190613357565b61018161017c36600461333a565b610850565b60405161012591906133bb565b61011861019c366004613445565b610bc2565b6101b46101af36600461347e565b610c49565b6040516001600160a01b039091168152602001610125565b6101f37f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610125565b61021461020f366004613445565b610cc9565b60405161012591906134c9565b61023461022f3660046135a5565b610fd6565b6040516101259190613630565b61025461024f36600461333a565b61108f565b604051610125919061367e565b61027461026f36600461333a565b6111f9565b604051610125919061369e565b61029461028f366004613445565b611947565b60405161012591906136ad565b6102c87f000000000000000000000000000000000000000000000000000000000000000081565b6040519015158152602001610125565b6102eb6102e6366004613445565b611c2e565b60405161012591906136bb565b61030b61030636600461371f565b611ca1565b60405161012591906137b8565b6101f3611d56565b610328612c95565b6000826040015190506000816001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610371573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261039991908101906137fb565b905060006103a682611ca1565b60408681015190516328ebbe8b60e21b81526001600160a01b039182166004820152919250879160009183169063a3aefa2c90602401600060405180830381865afa1580156103f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261042191908101906138ce565b90506000876040015190506000604051806101a001604052808a6000015181526020018a602001516001600160a01b031681526020018a604001516001600160a01b031681526020018a6060015181526020018a608001518152602001846000015181526020018460200151815260200184604001518152602001836001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104fe9190613982565b6001600160a01b03168152602001836001600160a01b031663e87554466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561054a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061056e919061399f565b8152602001836001600160a01b0316634ada90af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d5919061399f565b8152602001836001600160a01b031663db5c65de6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610618573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063c919061399f565b8152602001959095525092955050505050505b92915050565b6060816000816001600160401b0381111561067257610672612e17565b6040519080825280602002602001820160405280156106b757816020015b60408051808201909152600080825260208201528152602001906001900390816106905790505b50905060005b82811015610714576106ef8686838181106106da576106da6139b8565b905060200201602081019061024f919061333a565b828281518110610701576107016139b8565b60209081029190910101526001016106bd565b50949350505050565b606060008290506000816001600160a01b031663d88ff1f46040518163ffffffff1660e01b8152600401600060405180830381865afa158015610764573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261078c9190810190613a51565b80519091506000816001600160401b038111156107ab576107ab612e17565b6040519080825280602002602001820160405280156107e457816020015b6107d1612c95565b8152602001906001900390816107c95790505b50905060005b82811015610846576000848281518110610806576108066139b8565b60200260200101519050600061081c8983610320565b905080848481518110610831576108316139b8565b602090810291909101015250506001016107ea565b5095945050505050565b604080516060808201835260008083526020830152918101919091526000808390506000816001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156108b2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108da91908101906137fb565b90506000826001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561091c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109409190613982565b9050600082516001600160401b0381111561095d5761095d612e17565b6040519080825280602002602001820160405280156109a257816020015b604080518082019091526000808252602082015281526020019060019003908161097b5790505b5090506109d2604051806060016040528060006001600160a01b0316815260200160008152602001606081525090565b6001600160a01b03881681526040810182905260005b8451811015610bae576040805180820190915260008082526020820152858281518110610a1757610a176139b8565b602002602001015181600001906001600160a01b031690816001600160a01b031681525050670de0b6b3a7640000856001600160a01b031663fc57d4df888581518110610a6657610a666139b8565b60200260200101516040518263ffffffff1660e01b8152600401610a9991906001600160a01b0391909116815260200190565b602060405180830381865afa158015610ab6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ada919061399f565b878481518110610aec57610aec6139b8565b60200260200101516001600160a01b031663bbcac5576040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b55919061399f565b610b5f9190613b17565b610b699190613b2e565b60208201526040830151805182919084908110610b8857610b886139b8565b6020026020010181905250806020015188610ba39190613b50565b9750506001016109e8565b506020810195909552509295945050505050565b610bca612c95565b604051637aee632d60e01b81526001600160a01b0383811660048301528491610c4191839190821690637aee632d90602401600060405180830381865afa158015610c19573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526101139190810190613b63565b949350505050565b60405163266e0a7f60e01b81526001600160a01b0383811660048301528281166024830152600091859182169063266e0a7f90604401602060405180830381865afa158015610c9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc09190613982565b95945050505050565b60606000826001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610d0b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d3391908101906137fb565b90506000836001600160a01b03166361252fd16040518163ffffffff1660e01b8152600401600060405180830381865afa158015610d75573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d9d9190810190613b97565b9050600081516001600160401b03811115610dba57610dba612e17565b604051908082528060200260200182016040528015610e0b57816020015b6040805160808101825260008082526020808301829052928201526060808201528252600019909201910181610dd85790505b50905060005b8251811015610846576040805160808101825260008082526020820181905291810191909152606080820152838281518110610e4f57610e4f6139b8565b60209081029190910101516001600160a01b031681528351849083908110610e7957610e796139b8565b60200260200101516001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ebe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee29190613982565b6001600160a01b031660208201528351849083908110610f0457610f046139b8565b6020908102919091010151604051631627ee8960e01b81526001600160a01b038a8116600483015290911690631627ee8990602401602060405180830381865afa158015610f56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7a919061399f565b816040018181525050610fa78886868581518110610f9a57610f9a6139b8565b6020026020010151611d91565b816060018190525080838381518110610fc257610fc26139b8565b602090810291909101015250600101610e11565b6060826000816001600160401b03811115610ff357610ff3612e17565b60405190808252806020026020018201604052801561102c57816020015b611019612d18565b8152602001906001900390816110115790505b50905060005b828110156108465761106a87878381811061104f5761104f6139b8565b9050602002016020810190611064919061333a565b86611947565b82828151811061107c5761107c6139b8565b6020908102919091010152600101611032565b60408051808201909152600080825260208201526000826001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111079190613982565b90506000816001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611149573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116d9190613982565b6040805180820182526001600160a01b03808816808352925163fc57d4df60e01b815260048101939093529293509160208301919084169063fc57d4df90602401602060405180830381865afa1580156111cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ef919061399f565b9052949350505050565b611201612d57565b6000826001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611241573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611265919061399f565b90506000836001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cb9190613982565b604051638e8f294b60e01b81526001600160a01b03868116600483015291925082916000918291841690638e8f294b906024016040805180830381865afa15801561131a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133e9190613c35565b915091506000876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a69190613982565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061140c9190613c61565b60ff1690506000805b600860ff8216116114d2576000886001600160a01b031663e85a29608d8460ff16600881111561144757611447613c84565b6040518363ffffffff1660e01b8152600401611464929190613c9a565b602060405180830381865afa158015611481573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a59190613cd5565b6114b05760006114b3565b60015b60ff9081169083161b9290921791506114cb81613cf0565b9050611415565b506040518061022001604052808b6001600160a01b031681526020018981526020018b6001600160a01b031663ae9d70b06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611532573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611556919061399f565b81526020018b6001600160a01b031663f8f9da286040518163ffffffff1660e01b8152600401602060405180830381865afa158015611599573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115bd919061399f565b81526020018b6001600160a01b031663173b99046040518163ffffffff1660e01b8152600401602060405180830381865afa158015611600573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611624919061399f565b81526040516302c3bcbb60e01b81526001600160a01b038d811660048301526020909201918916906302c3bcbb90602401602060405180830381865afa158015611672573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611696919061399f565b815260405163252c221960e11b81526001600160a01b038d81166004830152602090920191891690634a58443290602401602060405180830381865afa1580156116e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611708919061399f565b81526020018b6001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561174b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176f919061399f565b81526020018b6001600160a01b0316638f840ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117d6919061399f565b81526020018b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611819573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061183d919061399f565b81526020018b6001600160a01b0316633b1d21a26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611880573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118a4919061399f565b81526020018615158152602001858152602001846001600160a01b031681526020018b6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611904573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119289190613c61565b60ff168152602081019390935260409092015298975050505050505050565b61194f612d18565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908516906370a0823190602401602060405180830381865afa158015611999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119bd919061399f565b6040516305eff7ef60e21b81526001600160a01b0385811660048301529192506000918616906317bfdfbc906024016020604051808303816000875af1158015611a0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a2f919061399f565b604051633af9e66960e01b81526001600160a01b038681166004830152919250600091871690633af9e669906024016020604051808303816000875af1158015611a7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa1919061399f565b90506000806000886001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0a9190613982565b6040516370a0823160e01b81526001600160a01b038a81166004830152919250908216906370a0823190602401602060405180830381865afa158015611b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b78919061399f565b604051636eb1769f60e11b81526001600160a01b038a811660048301528b811660248301529194509082169063dd62ed3e90604401602060405180830381865afa158015611bca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bee919061399f565b6040805160c0810182526001600160a01b038c168152602081019890985287019590955250506060840191909152608083015260a0820152905092915050565b604051631e6db74760e31b81526001600160a01b038281166004830152606091849182169063f36dba3890602401600060405180830381865afa158015611c79573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c419190810190613d0f565b80516060906000816001600160401b03811115611cc057611cc0612e17565b604051908082528060200260200182016040528015611cf957816020015b611ce6612d57565b815260200190600190039081611cde5790505b50905060005b82811015611d4e57611d29858281518110611d1c57611d1c6139b8565b60200260200101516111f9565b828281518110611d3b57611d3b6139b8565b6020908102919091010152600101611cff565b509392505050565b6000611d847f000000000000000000000000000000000000000000000000000000000000000063ffffffff16565b905090565b4390565b4290565b6060600083516001600160401b03811115611dae57611dae612e17565b604051908082528060200260200182016040528015611df357816020015b6040805180820190915260008082526020820152815260200190600190039081611dcc5790505b50905060005b845181101561071457611e2f604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b611e5c604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b7f000000000000000000000000000000000000000000000000000000000000000015611fdf57856001600160a01b0316638f693ec7888581518110611ea357611ea36139b8565b60200260200101516040518263ffffffff1660e01b8152600401611ed691906001600160a01b0391909116815260200190565b606060405180830381865afa158015611ef3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f179190613db4565b604085015260208401526001600160e01b0316825286516001600160a01b03871690638181494590899086908110611f5157611f516139b8565b60200260200101516040518263ffffffff1660e01b8152600401611f8491906001600160a01b0391909116815260200190565b606060405180830381865afa158015611fa1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fc59190613db4565b604084015260208301526001600160e01b0316815261214a565b856001600160a01b0316632c427b57888581518110612000576120006139b8565b60200260200101516040518263ffffffff1660e01b815260040161203391906001600160a01b0391909116815260200190565b606060405180830381865afa158015612050573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120749190613dfd565b63ffffffff90811660408601521660208401526001600160e01b0316825286516001600160a01b038716906392a18235908990869081106120b7576120b76139b8565b60200260200101516040518263ffffffff1660e01b81526004016120ea91906001600160a01b0391909116815260200190565b606060405180830381865afa158015612107573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061212b9190613dfd565b63ffffffff90811660408501521660208301526001600160e01b031681525b60006040518060200160405280898681518110612169576121696139b8565b60200260200101516001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121d2919061399f565b81525090506121fc8885815181106121ec576121ec6139b8565b60200260200101518885846122f1565b612220888581518110612211576122116139b8565b602002602001015188846124f2565b6000612248898681518110612237576122376139b8565b6020026020010151898c87866126e9565b905060006122718a8781518110612261576122616139b8565b60200260200101518a8d87612919565b60408051808201909152600080825260208201529091508a878151811061229a5761229a6139b8565b60209081029190910101516001600160a01b031681526122ba8284613b50565b6020820152875181908990899081106122d5576122d56139b8565b6020026020010181905250505050505050806001019050611df9565b604051637c05a7c560e01b81526001600160a01b03858116600483015260009190851690637c05a7c590602401602060405180830381865afa15801561233b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061235f919061399f565b9050600061236b611d56565b9050600084604001511180156123845750836040015181115b15612390575060408301515b60006123a0828660200151612b3d565b90506000811180156123b25750600083115b156124db576000612424886001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061241e919061399f565b86612b50565b905060006124328386612b6e565b90506000808311612452576040518060200160405280600081525061245c565b61245c8284612b7a565b9050600061248560405180602001604052808b600001516001600160e01b031681525083612bbf565b90506124c08160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612beb565b6001600160e01b0316895250505050602085018290526124e9565b80156124e957602085018290525b50505050505050565b604051631d31307360e21b81526001600160a01b038481166004830152600091908416906374c4c1cc90602401602060405180830381865afa15801561253c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612560919061399f565b9050600061256c611d56565b9050600083604001511180156125855750826040015181115b15612591575060408201515b60006125a1828560200151612b3d565b90506000811180156125b35750600083115b156126d3576000866001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156125f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061261c919061399f565b9050600061262a8386612b6e565b9050600080831161264a5760405180602001604052806000815250612654565b6126548284612b7a565b9050600061267d60405180602001604052808a600001516001600160e01b031681525083612bbf565b90506126b88160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612beb565b6001600160e01b0316885250505050602084018290526126e1565b80156126e157602084018290525b505050505050565b604080516020808201835284516001600160e01b031682528251908101928390526336fe846560e11b9092526001600160a01b0387811660248401528581166044840152600092839181908916636dfd08ca60648301602060405180830381865afa15801561275c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612780919061399f565b905280519091501580156128025750866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f19190613e40565b6001600160e01b0316826000015110155b1561287557866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612845573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128699190613e40565b6001600160e01b031681525b60006128818383612c27565b6040516395dd919360e01b81526001600160a01b0389811660048301529192506000916128fc91908c16906395dd919390602401602060405180830381865afa1580156128d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128f6919061399f565b87612b50565b9050600061290a8284612c53565b9b9a5050505050505050505050565b604080516020808201835283516001600160e01b0316825282519081019283905263552c097160e01b9092526001600160a01b038681166024840152848116604484015260009283918190881663552c097160648301602060405180830381865afa15801561298c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129b0919061399f565b90528051909150158015612a325750856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a219190613e40565b6001600160e01b0316826000015110155b15612aa557856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a999190613e40565b6001600160e01b031681525b6000612ab18383612c27565b6040516370a0823160e01b81526001600160a01b0388811660048301529192506000918a16906370a0823190602401602060405180830381865afa158015612afd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b21919061399f565b90506000612b2f8284612c53565b9a9950505050505050505050565b6000612b498284613e5b565b9392505050565b6000612b49612b6784670de0b6b3a7640000612b6e565b8351612c7d565b6000612b498284613b17565b6040805160208101909152600081526040518060200160405280612bb6612bb0866ec097ce7bc90715b34b9f1000000000612b6e565b85612c7d565b90529392505050565b6040805160208101909152600081526040518060200160405280612bb685600001518560000151612c89565b6000816001600160e01b03841115612c1f5760405162461bcd60e51b8152600401612c169190613e6e565b60405180910390fd5b509192915050565b6040805160208101909152600081526040518060200160405280612bb685600001518560000151612b3d565b60006ec097ce7bc90715b34b9f1000000000612c73848460000151612b6e565b612b499190613b2e565b6000612b498284613b2e565b6000612b498284613b50565b604051806101a001604052806060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160608152602001606081526020016060815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001606081525090565b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180610220016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b6001600160a01b0381168114612e0457600080fd5b50565b8035612e1281612def565b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715612e4f57612e4f612e17565b60405290565b604051606081016001600160401b0381118282101715612e4f57612e4f612e17565b604051601f8201601f191681016001600160401b0381118282101715612e9f57612e9f612e17565b604052919050565b60006001600160401b03821115612ec057612ec0612e17565b50601f01601f191660200190565b60008060408385031215612ee157600080fd5b8235612eec81612def565b91506020838101356001600160401b0380821115612f0957600080fd5b9085019060a08288031215612f1d57600080fd5b612f25612e2d565b823582811115612f3457600080fd5b83019150601f82018813612f4757600080fd5b8135612f5a612f5582612ea7565b612e77565b8181528986838601011115612f6e57600080fd5b818685018783013760008683830101528083525050612f8e848401612e07565b84820152612f9e60408401612e07565b60408201526060830135606082015260808301356080820152809450505050509250929050565b60005b83811015612fe0578181015183820152602001612fc8565b50506000910152565b60008151808452613001816020860160208601612fc5565b601f01601f19169290920160200192915050565b80516001600160a01b031682526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e0830152610100808201518184015250610120808201518184015250610140808201518184015250610160808201516130a08285018215159052565b505061018081810151908301526101a0808201516001600160a01b0316908301526101c080820151908301526101e0808201519083015261020090810151910152565b60008151808452602080850194506020840160005b8381101561311f5761310b878351613015565b6102209690960195908201906001016130f8565b509495945050505050565b60006101a0825181855261314082860182612fe9565b915050602083015161315d60208601826001600160a01b03169052565b50604083015161317860408601826001600160a01b03169052565b50606083015160608501526080830151608085015260a083015184820360a08601526131a48282612fe9565b91505060c083015184820360c08601526131be8282612fe9565b91505060e083015184820360e08601526131d88282612fe9565b915050610100808401516131f6828701826001600160a01b03169052565b5050610120838101519085015261014080840151908501526101608084015190850152610180808401518583038287015261323183826130e3565b9695505050505050565b602081526000612b49602083018461312a565b60008083601f84011261326057600080fd5b5081356001600160401b0381111561327757600080fd5b6020830191508360208260051b850101111561329257600080fd5b9250929050565b600080602083850312156132ac57600080fd5b82356001600160401b038111156132c257600080fd5b6132ce8582860161324e565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b8281101561332d5761331d84835180516001600160a01b03168252602090810151910152565b92840192908501906001016132f7565b5091979650505050505050565b60006020828403121561334c57600080fd5b8135612b4981612def565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156133ae57603f1988860301845261339c85835161312a565b94509285019290850190600101613380565b5092979650505050505050565b602080825282516001600160a01b03168282015282810151604080840191909152808401516060808501528051608085018190526000939291830191849160a08701905b808410156134395761342582865180516001600160a01b03168252602090810151910152565b9385019360019390930192908201906133ff565b50979650505050505050565b6000806040838503121561345857600080fd5b823561346381612def565b9150602083013561347381612def565b809150509250929050565b60008060006060848603121561349357600080fd5b833561349e81612def565b925060208401356134ae81612def565b915060408401356134be81612def565b809150509250925092565b600060208083018184528085518083526040925060408601915060408160051b8701018488016000805b8481101561359657898403603f19018652825180516001600160a01b03908116865289820151168986015287810151888601526060908101516080918601829052805191860182905289019060a086019084905b808210156135815761356d83855180516001600160a01b03168252602090810151910152565b928b0192918a019160019190910190613547565b505096890196945050918701916001016134f3565b50919998505050505050505050565b6000806000604084860312156135ba57600080fd5b83356001600160401b038111156135d057600080fd5b6135dc8682870161324e565b90945092505060208401356134be81612def565b80516001600160a01b031682526020808201519083015260408082015190830152606080820151908301526080808201519083015260a090810151910152565b6020808252825182820181905260009190848201906040850190845b818110156136725761365f8385516135f0565b9284019260c0929092019160010161364c565b50909695505050505050565b81516001600160a01b03168152602080830151908201526040810161064f565b610220810161064f8284613015565b60c0810161064f82846135f0565b6020808252825182820181905260009190848201906040850190845b818110156136725783516001600160a01b0316835292840192918401916001016136d7565b60006001600160401b0382111561371557613715612e17565b5060051b60200190565b6000602080838503121561373257600080fd5b82356001600160401b0381111561374857600080fd5b8301601f8101851361375957600080fd5b8035613767612f55826136fc565b81815260059190911b8201830190838101908783111561378657600080fd5b928401925b828410156137ad57833561379e81612def565b8252928401929084019061378b565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b81811015613672576137e7838551613015565b9284019261022092909201916001016137d4565b6000602080838503121561380e57600080fd5b82516001600160401b0381111561382457600080fd5b8301601f8101851361383557600080fd5b8051613843612f55826136fc565b81815260059190911b8201830190838101908783111561386257600080fd5b928401925b828410156137ad57835161387a81612def565b82529284019290840190613867565b600082601f83011261389a57600080fd5b81516138a8612f5582612ea7565b8181528460208386010111156138bd57600080fd5b610c41826020830160208701612fc5565b6000602082840312156138e057600080fd5b81516001600160401b03808211156138f757600080fd5b908301906060828603121561390b57600080fd5b613913612e55565b82518281111561392257600080fd5b61392e87828601613889565b82525060208301518281111561394357600080fd5b61394f87828601613889565b60208301525060408301518281111561396757600080fd5b61397387828601613889565b60408301525095945050505050565b60006020828403121561399457600080fd5b8151612b4981612def565b6000602082840312156139b157600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600060a082840312156139e057600080fd5b6139e8612e2d565b905081516001600160401b03811115613a0057600080fd5b613a0c84828501613889565b8252506020820151613a1d81612def565b60208201526040820151613a3081612def565b80604083015250606082015160608201526080820151608082015292915050565b60006020808385031215613a6457600080fd5b82516001600160401b0380821115613a7b57600080fd5b818501915085601f830112613a8f57600080fd5b8151613a9d612f55826136fc565b81815260059190911b83018401908481019088831115613abc57600080fd5b8585015b83811015613af457805185811115613ad85760008081fd5b613ae68b89838a01016139ce565b845250918601918601613ac0565b5098975050505050505050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761064f5761064f613b01565b600082613b4b57634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561064f5761064f613b01565b600060208284031215613b7557600080fd5b81516001600160401b03811115613b8b57600080fd5b610c41848285016139ce565b60006020808385031215613baa57600080fd5b82516001600160401b03811115613bc057600080fd5b8301601f81018513613bd157600080fd5b8051613bdf612f55826136fc565b81815260059190911b82018301908381019087831115613bfe57600080fd5b928401925b828410156137ad578351613c1681612def565b82529284019290840190613c03565b80518015158114612e1257600080fd5b60008060408385031215613c4857600080fd5b613c5183613c25565b9150602083015190509250929050565b600060208284031215613c7357600080fd5b815160ff81168114612b4957600080fd5b634e487b7160e01b600052602160045260246000fd5b6001600160a01b03831681526040810160098310613cc857634e487b7160e01b600052602160045260246000fd5b8260208301529392505050565b600060208284031215613ce757600080fd5b612b4982613c25565b600060ff821660ff8103613d0657613d06613b01565b60010192915050565b60006020808385031215613d2257600080fd5b82516001600160401b03811115613d3857600080fd5b8301601f81018513613d4957600080fd5b8051613d57612f55826136fc565b81815260059190911b82018301908381019087831115613d7657600080fd5b928401925b828410156137ad578351613d8e81612def565b82529284019290840190613d7b565b80516001600160e01b0381168114612e1257600080fd5b600080600060608486031215613dc957600080fd5b613dd284613d9d565b925060208401519150604084015190509250925092565b805163ffffffff81168114612e1257600080fd5b600080600060608486031215613e1257600080fd5b613e1b84613d9d565b9250613e2960208501613de9565b9150613e3760408501613de9565b90509250925092565b600060208284031215613e5257600080fd5b612b4982613d9d565b8181038181111561064f5761064f613b01565b602081526000612b496020830184612fe956fea2646970667358221220b9946cc7fdc900bd3735319cd04868b3796a2261574b7617c9cbf91cb2f997ca64736f6c63430008190033", + "args": [true, 0, "0x5593FF68bE84C966821eEf5F0a988C285D5B7CeC"], + "numDeployments": 2, + "solcInputHash": "09f8b2889a382752688c03578bc27f8d", + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"timeBased_\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"blocksPerYear_\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"corePoolComptroller_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidBlocksPerYear\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTimeBasedConfiguration\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"blocksOrSecondsPerYear\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"corePoolComptroller\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"}],\"name\":\"getAllPools\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockNumberOrTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getPendingRewards\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"distributorAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"rewardTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalRewards\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.PendingReward[]\",\"name\":\"pendingRewards\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.RewardSummary[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getPoolBadDebt\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalBadDebtUsd\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"badDebtUsd\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.BadDebt[]\",\"name\":\"badDebts\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.BadDebtSummary\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolByComptroller\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolRegistryInterface.VenusPool\",\"name\":\"venusPool\",\"type\":\"tuple\"}],\"name\":\"getPoolDataFromVenusPool\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getPoolsSupportedByAsset\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getVTokenForAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isTimeBased\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"vTokenBalances\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalanceCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balanceOfUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenAllowance\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenBalances\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"vTokenBalancesAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalanceCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balanceOfUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenAllowance\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenBalances[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"vTokenMetadata\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"vTokenMetadataAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"vTokenUnderlyingPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"underlyingPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenUnderlyingPrice\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"vTokenUnderlyingPriceAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"underlyingPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenUnderlyingPrice[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"params\":{\"blocksPerYear_\":\"The number of blocks per year\",\"corePoolComptroller_\":\"The address of the core pool comptroller\",\"timeBased_\":\"A boolean indicating whether the contract is based on time or block.\"}},\"getAllPools(address)\":{\"details\":\"This function is not designed to be called in a transaction: it is too gas-intensive\",\"params\":{\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"Arrays of all Venus pools' data\"}},\"getBlockNumberOrTimestamp()\":{\"details\":\"Function to simply retrieve block number or block timestamp\",\"returns\":{\"_0\":\"Current block number or block timestamp\"}},\"getPendingRewards(address,address)\":{\"params\":{\"account\":\"The user account.\",\"comptrollerAddress\":\"address\"},\"returns\":{\"_0\":\"Pending rewards array\"}},\"getPoolBadDebt(address)\":{\"params\":{\"comptrollerAddress\":\"Address of the comptroller\"},\"returns\":{\"_0\":\"badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and a break down of bad debt by market\"}},\"getPoolByComptroller(address,address)\":{\"params\":{\"comptroller\":\"The Comptroller implementation address\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"PoolData structure containing the details of the pool\"}},\"getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))\":{\"params\":{\"poolRegistryAddress\":\"Address of the PoolRegistry\",\"venusPool\":\"The VenusPool Object from PoolRegistry\"},\"returns\":{\"_0\":\"Enriched PoolData\"}},\"getPoolsSupportedByAsset(address,address)\":{\"params\":{\"asset\":\"The underlying asset of vToken\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"A list of Comptroller contracts\"}},\"getVTokenForAsset(address,address,address)\":{\"params\":{\"asset\":\"The underlyingAsset of VToken\",\"comptroller\":\"The pool comptroller\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"Address of the vToken\"}},\"vTokenBalances(address,address)\":{\"params\":{\"account\":\"The user Account\",\"vToken\":\"vToken address\"},\"returns\":{\"_0\":\"A struct containing the balances data\"}},\"vTokenBalancesAll(address[],address)\":{\"params\":{\"account\":\"The user Account\",\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"A list of structs containing balances data\"}},\"vTokenMetadata(address)\":{\"params\":{\"vToken\":\"The address of vToken\"},\"returns\":{\"_0\":\"VTokenMetadata struct\"}},\"vTokenMetadataAll(address[])\":{\"params\":{\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"An array of VTokenMetadata structs\"}},\"vTokenUnderlyingPrice(address)\":{\"params\":{\"vToken\":\"vToken address\"},\"returns\":{\"_0\":\"The price data for each asset\"}},\"vTokenUnderlyingPriceAll(address[])\":{\"params\":{\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"An array containing the price data for each asset\"}}},\"title\":\"PoolLens\",\"version\":1},\"userdoc\":{\"errors\":{\"InvalidBlocksPerYear()\":[{\"notice\":\"Thrown when blocks per year is invalid\"}],\"InvalidTimeBasedConfiguration()\":[{\"notice\":\"Thrown when time based but blocks per year is provided\"}]},\"kind\":\"user\",\"methods\":{\"blocksOrSecondsPerYear()\":{\"notice\":\"Stores blocksPerYear if isTimeBased is true else secondsPerYear is stored\"},\"corePoolComptroller()\":{\"notice\":\"Address of the core pool comptroller (all markets are returned for this pool, including paused ones)\"},\"getAllPools(address)\":{\"notice\":\"Queries all pools with addtional details for each of them\"},\"getPendingRewards(address,address)\":{\"notice\":\"Returns the pending rewards for a user for a given pool.\"},\"getPoolBadDebt(address)\":{\"notice\":\"Returns a summary of a pool's bad debt broken down by market\"},\"getPoolByComptroller(address,address)\":{\"notice\":\"Queries the details of a pool identified by Comptroller address\"},\"getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))\":{\"notice\":\"Queries additional information for the pool\"},\"getPoolsSupportedByAsset(address,address)\":{\"notice\":\"Returns all pools that support the specified underlying asset\"},\"getVTokenForAsset(address,address,address)\":{\"notice\":\"Returns vToken holding the specified underlying asset in the specified pool\"},\"isTimeBased()\":{\"notice\":\"Acknowledges if a contract is time based or not\"},\"vTokenBalances(address,address)\":{\"notice\":\"Queries the user's supply/borrow balances in the specified vToken\"},\"vTokenBalancesAll(address[],address)\":{\"notice\":\"Queries the user's supply/borrow balances in vTokens\"},\"vTokenMetadata(address)\":{\"notice\":\"Returns the metadata of VToken\"},\"vTokenMetadataAll(address[])\":{\"notice\":\"Returns the metadata of all VTokens\"},\"vTokenUnderlyingPrice(address)\":{\"notice\":\"Returns the price data for the underlying asset of the specified vToken\"},\"vTokenUnderlyingPriceAll(address[])\":{\"notice\":\"Returns the price data for the underlying assets of the specified vTokens\"}},\"notice\":\"The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be looked up for specific pools and markets: - the vToken balance of a given user; - the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address; - the vToken address in a pool for a given asset; - a list of all pools that support an asset; - the underlying asset price of a vToken; - the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Lens/PoolLens.sol\":\"PoolLens\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"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\",\"keccak256\":\"0x9140dabc466abab21b48b72dbda26736b1183a310d0e677d3719d201df026510\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x359a1ab89b46b9aba7bcad3fb651924baf4893d15153049b9976b0fc9be1358e\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x07e881de3b9f6d2c07909f193f24b96c7fe4ea60013260f3f25aecd8bab3c2f8\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x75097e35253e7fb282ee4d7f27a80eaacfa759923185bf17302a89cbc059c5ef\",\"license\":\"MIT\"},\"@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\"},\"@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\",\"keccak256\":\"0xfe0fd441c84ac907cabc88db69ef04f6d7532d770c7e6a1dfe6e7d6305debb49\",\"license\":\"BSD-3-Clause\"},\"@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 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/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface IProtocolShareReserve {\\n /// @notice it represents the type of vToken income\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(\\n address comptroller,\\n address asset,\\n IncomeType incomeType\\n ) external;\\n}\\n\",\"keccak256\":\"0x0f341bbef8f12885d79b7acaad7aaf11b84809e8f6b059ef4efc011c8f6c39a5\",\"license\":\"BSD-3-Clause\"},\"@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\",\"keccak256\":\"0x57a2bbb9b8e02b1c0a5c0e305fef1328a22db56c3d4b148c362010a6e767243c\",\"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\"},\"@venusprotocol/venus-protocol/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\",\"keccak256\":\"0xd112f60183416ad796093b4a83a80ddc1b8b655965f02ae55ca82e2a0c68f97d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/venus-protocol/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\",\"keccak256\":\"0x5285c875114db2ea2be0b81b65722d5761806217022db733323c4e03365a95e7\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IPrime } from \\\"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\\\";\\n\\nimport { ComptrollerInterface, Action } from \\\"./ComptrollerInterface.sol\\\";\\nimport { ComptrollerStorage } from \\\"./ComptrollerStorage.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"./MaxLoopsLimitHelper.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title Comptroller\\n * @author Venus\\n * @notice The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating,\\n * and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts\\n * with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows\\n * or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing\\n * liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow,\\n * as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the\\n * markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market\\u2019s corresponding liquidation threshold,\\n * the borrow is eligible for liquidation.\\n *\\n * The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed\\n * the `minLiquidatableCollateral` for the `Comptroller`:\\n *\\n * - `healAccount()`: This function is called to seize all of a given user\\u2019s collateral, requiring the `msg.sender` repay a certain percentage\\n * of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed\\n * 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt\\n * and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool.\\n * - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation\\n * incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic\\n * verifying that the repay amount does not exceed the close factor.\\n */\\ncontract Comptroller is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n ComptrollerStorage,\\n ComptrollerInterface,\\n ExponentialNoError,\\n MaxLoopsLimitHelper\\n{\\n // PoolRegistry, immutable to save on gas\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable poolRegistry;\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(VToken indexed vToken, address indexed account);\\n\\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(VToken vToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa);\\n\\n /// @notice Emitted when liquidation threshold is changed by admin\\n event NewLiquidationThreshold(\\n VToken vToken,\\n uint256 oldLiquidationThresholdMantissa,\\n uint256 newLiquidationThresholdMantissa\\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 an action is paused on a market\\n event ActionPausedMarket(VToken vToken, Action action, bool pauseState);\\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 the collateral threshold (in USD) for non-batch liquidations is changed\\n event NewMinLiquidatableCollateral(uint256 oldMinLiquidatableCollateral, uint256 newMinLiquidatableCollateral);\\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 a rewards distributor is added\\n event NewRewardsDistributor(address indexed rewardsDistributor, address indexed rewardToken);\\n\\n /// @notice Emitted when a market is supported\\n event MarketSupported(VToken vToken);\\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 a market\\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\\n\\n /// @notice Emitted when a market is unlisted\\n event MarketUnlisted(address indexed vToken);\\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 Thrown when collateral factor exceeds the upper bound\\n error InvalidCollateralFactor();\\n\\n /// @notice Thrown when liquidation threshold exceeds the collateral factor\\n error InvalidLiquidationThreshold();\\n\\n /// @notice Thrown when the action is only available to specific sender, but the real sender was different\\n error UnexpectedSender(address expectedSender, address actualSender);\\n\\n /// @notice Thrown when the oracle returns an invalid price for some asset\\n error PriceError(address vToken);\\n\\n /// @notice Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\\n error SnapshotError(address vToken, address user);\\n\\n /// @notice Thrown when the market is not listed\\n error MarketNotListed(address market);\\n\\n /// @notice Thrown when a market has an unexpected comptroller\\n error ComptrollerMismatch();\\n\\n /// @notice Thrown when user is not member of market\\n error MarketNotCollateral(address vToken, address user);\\n\\n /// @notice Thrown when borrow action is not paused\\n error BorrowActionNotPaused();\\n\\n /// @notice Thrown when mint action is not paused\\n error MintActionNotPaused();\\n\\n /// @notice Thrown when redeem action is not paused\\n error RedeemActionNotPaused();\\n\\n /// @notice Thrown when repay action is not paused\\n error RepayActionNotPaused();\\n\\n /// @notice Thrown when seize action is not paused\\n error SeizeActionNotPaused();\\n\\n /// @notice Thrown when exit market action is not paused\\n error ExitMarketActionNotPaused();\\n\\n /// @notice Thrown when transfer action is not paused\\n error TransferActionNotPaused();\\n\\n /// @notice Thrown when enter market action is not paused\\n error EnterMarketActionNotPaused();\\n\\n /// @notice Thrown when liquidate action is not paused\\n error LiquidateActionNotPaused();\\n\\n /// @notice Thrown when borrow cap is not zero\\n error BorrowCapIsNotZero();\\n\\n /// @notice Thrown when supply cap is not zero\\n error SupplyCapIsNotZero();\\n\\n /// @notice Thrown when collateral factor is not zero\\n error CollateralFactorIsNotZero();\\n\\n /**\\n * @notice Thrown during the liquidation if user's total collateral amount is lower than\\n * a predefined threshold. In this case only batch liquidations (either liquidateAccount\\n * or healAccount) are available.\\n */\\n error MinimalCollateralViolated(uint256 expectedGreaterThan, uint256 actual);\\n error CollateralExceedsThreshold(uint256 expectedLessThanOrEqualTo, uint256 actual);\\n error InsufficientCollateral(uint256 collateralToSeize, uint256 availableCollateral);\\n\\n /// @notice Thrown when the account doesn't have enough liquidity to redeem or borrow\\n error InsufficientLiquidity();\\n\\n /// @notice Thrown when trying to liquidate a healthy account\\n error InsufficientShortfall();\\n\\n /// @notice Thrown when trying to repay more than allowed by close factor\\n error TooMuchRepay();\\n\\n /// @notice Thrown if the user is trying to exit a market in which they have an outstanding debt\\n error NonzeroBorrowBalance();\\n\\n /// @notice Thrown when trying to perform an action that is paused\\n error ActionPaused(address market, Action action);\\n\\n /// @notice Thrown when trying to add a market that is already listed\\n error MarketAlreadyListed(address market);\\n\\n /// @notice Thrown if the supply cap is exceeded\\n error SupplyCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if the borrow cap is exceeded\\n error BorrowCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if delegate approval status is already set to the requested value\\n error DelegationStatusUnchanged();\\n\\n /// @param poolRegistry_ Pool registry address\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n constructor(address poolRegistry_) {\\n ensureNonzeroAddress(poolRegistry_);\\n\\n poolRegistry = poolRegistry_;\\n _disableInitializers();\\n }\\n\\n /**\\n * @param loopLimit Limit for the loops can iterate to avoid the DOS\\n * @param accessControlManager Access control manager contract address\\n */\\n function initialize(uint256 loopLimit, address accessControlManager) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager);\\n\\n _setMaxLoopsLimit(loopLimit);\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation; enabling them to be used as collateral\\n * @param vTokens The list of addresses of the vToken markets to be enabled\\n * @return errors An array of NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketEntered is emitted for each market on success\\n * @custom:error ActionPaused error is thrown if entering any of the markets is paused\\n * @custom:error MarketNotListed error is thrown if any of the markets is not listed\\n * @custom:access Not restricted\\n */\\n function enterMarkets(address[] memory vTokens) external override returns (uint256[] memory) {\\n uint256 len = vTokens.length;\\n\\n uint256[] memory results = new uint256[](len);\\n for (uint256 i; i < len; ++i) {\\n VToken vToken = VToken(vTokens[i]);\\n\\n _addToMarket(vToken, msg.sender);\\n results[i] = NO_ERROR;\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Unlist a market by setting isListed to false\\n * @dev Checks if all actions are paused, borrow/supply caps is set to 0 and collateral factor is to 0.\\n * @param market The address of the market (token) to unlist\\n * @return uint256 Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketUnlisted is emitted on success\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error BorrowActionNotPaused error is thrown if borrow action is not paused\\n * @custom:error MintActionNotPaused error is thrown if mint action is not paused\\n * @custom:error RedeemActionNotPaused error is thrown if redeem action is not paused\\n * @custom:error RepayActionNotPaused error is thrown if repay action is not paused\\n * @custom:error EnterMarketActionNotPaused error is thrown if enter market action is not paused\\n * @custom:error LiquidateActionNotPaused error is thrown if liquidate action is not paused\\n * @custom:error BorrowCapIsNotZero error is thrown if borrow cap is not zero\\n * @custom:error SupplyCapIsNotZero error is thrown if supply cap is not zero\\n * @custom:error CollateralFactorIsNotZero error is thrown if collateral factor is not zero\\n */\\n function unlistMarket(address market) external returns (uint256) {\\n _checkAccessAllowed(\\\"unlistMarket(address)\\\");\\n\\n Market storage _market = markets[market];\\n\\n if (!_market.isListed) {\\n revert MarketNotListed(market);\\n }\\n\\n if (!actionPaused(market, Action.BORROW)) {\\n revert BorrowActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.MINT)) {\\n revert MintActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.REDEEM)) {\\n revert RedeemActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.REPAY)) {\\n revert RepayActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.SEIZE)) {\\n revert SeizeActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.ENTER_MARKET)) {\\n revert EnterMarketActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.LIQUIDATE)) {\\n revert LiquidateActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.TRANSFER)) {\\n revert TransferActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.EXIT_MARKET)) {\\n revert ExitMarketActionNotPaused();\\n }\\n\\n if (borrowCaps[market] != 0) {\\n revert BorrowCapIsNotZero();\\n }\\n\\n if (supplyCaps[market] != 0) {\\n revert SupplyCapIsNotZero();\\n }\\n\\n if (_market.collateralFactorMantissa != 0) {\\n revert CollateralFactorIsNotZero();\\n }\\n\\n _market.isListed = false;\\n emit MarketUnlisted(market);\\n\\n return NO_ERROR;\\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 * @custom:event DelegateUpdated emits on success\\n * @custom:error ZeroAddressNotAllowed is thrown when delegate address is zero\\n * @custom:error DelegationStatusUnchanged is thrown if approval status is already set to the requested value\\n * @custom:access Not restricted\\n */\\n function updateDelegate(address delegate, bool approved) external {\\n ensureNonzeroAddress(delegate);\\n if (approvedDelegates[msg.sender][delegate] == approved) {\\n revert DelegationStatusUnchanged();\\n }\\n\\n approvedDelegates[msg.sender][delegate] = approved;\\n emit DelegateUpdated(msg.sender, delegate, approved);\\n }\\n\\n /**\\n * @notice Removes asset from sender's account liquidity calculation; disabling them as collateral\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketExited is emitted on success\\n * @custom:error ActionPaused error is thrown if exiting the market is paused\\n * @custom:error NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function exitMarket(address vTokenAddress) external override returns (uint256) {\\n _checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\\n VToken vToken = VToken(vTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\\n (uint256 tokensHeld, uint256 amountOwed, ) = _safeGetAccountSnapshot(vToken, msg.sender);\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n revert NonzeroBorrowBalance();\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n _checkRedeemAllowed(vTokenAddress, msg.sender, tokensHeld);\\n\\n Market storage marketToExit = markets[address(vToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return 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 // load into memory for faster iteration\\n VToken[] memory userAssetList = accountAssets[msg.sender];\\n uint256 len = userAssetList.length;\\n\\n uint256 assetIndex = len;\\n for (uint256 i; i < len; ++i) {\\n if (userAssetList[i] == vToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n VToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.pop();\\n\\n emit MarketExited(vToken, msg.sender);\\n\\n return NO_ERROR;\\n }\\n\\n /*** Policy Hooks ***/\\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 * @custom:error ActionPaused error is thrown if supplying to this market is paused\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\\n * @custom:access Not restricted\\n */\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external override {\\n _checkActionPauseState(vToken, Action.MINT);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n uint256 supplyCap = supplyCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (supplyCap != type(uint256).max) {\\n uint256 vTokenSupply = VToken(vToken).totalSupply();\\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\\n if (nextTotalSupply > supplyCap) {\\n revert SupplyCapExceeded(vToken, supplyCap);\\n }\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, minter);\\n }\\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external override {\\n _checkActionPauseState(vToken, Action.REDEEM);\\n\\n _checkRedeemAllowed(vToken, redeemer, redeemTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, redeemer);\\n }\\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 if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(redeemer, vToken);\\n }\\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 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 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 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 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 * @custom:error ActionPaused error is thrown if borrowing is paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if there is not enough collateral to borrow\\n * @custom:error BorrowCapExceeded is thrown if the borrow cap will be exceeded should this borrow succeed\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted if vToken is enabled as collateral, otherwise only vToken\\n */\\n /// disable-eslint\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external override {\\n _checkActionPauseState(vToken, Action.BORROW);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (!markets[vToken].accountMembership[borrower]) {\\n // only vTokens may call borrowAllowed if borrower not in market\\n _checkSenderIs(vToken);\\n\\n // attempt to add borrower to the market or revert\\n _addToMarket(VToken(msg.sender), borrower);\\n }\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (oracle.getUnderlyingPrice(vToken) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 borrowCap = borrowCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (borrowCap != type(uint256).max) {\\n uint256 totalBorrows = VToken(vToken).totalBorrows();\\n uint256 badDebt = VToken(vToken).badDebt();\\n uint256 nextTotalBorrows = totalBorrows + borrowAmount + badDebt;\\n if (nextTotalBorrows > borrowCap) {\\n revert BorrowCapExceeded(vToken, borrowCap);\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n borrower,\\n VToken(vToken),\\n 0,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\n }\\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 borrower The account which would borrowed the asset\\n * @custom:error ActionPaused error is thrown if repayments are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:access Not restricted\\n */\\n function preRepayHook(address vToken, address borrower) external override {\\n _checkActionPauseState(vToken, Action.REPAY);\\n\\n oracle.updatePrice(vToken);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\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 borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n * @param skipLiquidityCheck Allows the borrow to be liquidated regardless of the account liquidity\\n * @custom:error ActionPaused error is thrown if liquidations are paused in this market\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor\\n * @custom:error MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations\\n * @custom:error InsufficientShortfall is thrown when trying to liquidate a healthy account\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n */\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external override {\\n // Pause Action.LIQUIDATE on BORROWED TOKEN to prevent liquidating it.\\n // If we want to pause liquidating to vTokenCollateral, we should pause\\n // Action.SEIZE on it\\n _checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(address(vTokenBorrowed));\\n }\\n if (!markets[vTokenCollateral].isListed) {\\n revert MarketNotListed(address(vTokenCollateral));\\n }\\n\\n uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\\n\\n /* Allow accounts to be liquidated if it is a forced liquidation */\\n if (skipLiquidityCheck || isForcedLiquidationEnabled[vTokenBorrowed]) {\\n if (repayAmount > borrowBalance) {\\n revert TooMuchRepay();\\n }\\n return;\\n }\\n\\n /* The borrower must have shortfall and collateral > threshold in order to be liquidatable */\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral <= minLiquidatableCollateral) {\\n /* The liquidator should use either liquidateAccount or healAccount */\\n revert MinimalCollateralViolated(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint256 maxClose = mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance);\\n if (repayAmount > maxClose) {\\n revert TooMuchRepay();\\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 seizerContract Contract that tries to seize the asset (either borrowed vToken or Comptroller)\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @custom:error ActionPaused error is thrown if seizing this type of collateral is paused\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error ComptrollerMismatch error is when seizer contract or seized asset belong to different pools\\n * @custom:access Not restricted\\n */\\n function preSeizeHook(\\n address vTokenCollateral,\\n address seizerContract,\\n address liquidator,\\n address borrower\\n ) external override {\\n // Pause Action.SEIZE on COLLATERAL to prevent seizing it.\\n // If we want to pause liquidating vTokenBorrowed, we should pause\\n // Action.LIQUIDATE on it\\n _checkActionPauseState(vTokenCollateral, Action.SEIZE);\\n\\n Market storage market = markets[vTokenCollateral];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(vTokenCollateral);\\n }\\n\\n if (seizerContract == address(this)) {\\n // If Comptroller is the seizer, just check if collateral's comptroller\\n // is equal to the current address\\n if (address(VToken(vTokenCollateral).comptroller()) != address(this)) {\\n revert ComptrollerMismatch();\\n }\\n } else {\\n // If the seizer is not the Comptroller, check that the seizer is a\\n // listed market, and that the markets' comptrollers match\\n if (!markets[seizerContract].isListed) {\\n revert MarketNotListed(seizerContract);\\n }\\n if (VToken(vTokenCollateral).comptroller() != VToken(seizerContract).comptroller()) {\\n revert ComptrollerMismatch();\\n }\\n }\\n\\n if (!market.accountMembership[borrower]) {\\n revert MarketNotCollateral(vTokenCollateral, borrower);\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vTokenCollateral);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, borrower);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, liquidator);\\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external override {\\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 _checkRedeemAllowed(vToken, src, transferTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, src);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, dst);\\n }\\n }\\n\\n /*** Pool-level operations ***/\\n\\n /**\\n * @notice Seizes all the remaining collateral, makes msg.sender repay the existing\\n * borrows, and treats the rest of the debt as bad debt (for each market).\\n * The sender has to repay a certain percentage of the debt, computed as\\n * collateral / (borrows * liquidationIncentive).\\n * @param user account to heal\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for healing\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function healAccount(address user) external {\\n VToken[] memory userAssets = getAssetsIn(user);\\n uint256 userAssetsCount = userAssets.length;\\n\\n address liquidator = msg.sender;\\n {\\n ResilientOracleInterface oracle_ = oracle;\\n // We need all user's markets to be fresh for the computations to be correct\\n for (uint256 i; i < userAssetsCount; ++i) {\\n userAssets[i].accrueInterest();\\n oracle_.updatePrice(address(userAssets[i]));\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(user, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n // percentage = collateral / (borrows * liquidation incentive)\\n Exp memory collateral = Exp({ mantissa: snapshot.totalCollateral });\\n Exp memory scaledBorrows = mul_(\\n Exp({ mantissa: snapshot.borrows }),\\n Exp({ mantissa: liquidationIncentiveMantissa })\\n );\\n\\n Exp memory percentage = div_(collateral, scaledBorrows);\\n if (lessThanExp(Exp({ mantissa: MANTISSA_ONE }), percentage)) {\\n revert CollateralExceedsThreshold(scaledBorrows.mantissa, collateral.mantissa);\\n }\\n\\n for (uint256 i; i < userAssetsCount; ++i) {\\n VToken market = userAssets[i];\\n\\n (uint256 tokens, uint256 borrowBalance, ) = _safeGetAccountSnapshot(market, user);\\n uint256 repaymentAmount = mul_ScalarTruncate(percentage, borrowBalance);\\n\\n // Seize the entire collateral\\n if (tokens != 0) {\\n market.seize(liquidator, user, tokens);\\n }\\n // Repay a certain percentage of the borrow, forgive the rest\\n if (borrowBalance != 0) {\\n market.healBorrow(liquidator, user, repaymentAmount);\\n }\\n }\\n }\\n\\n /**\\n * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than\\n * a predefined threshold, and the account collateral can be seized to cover all borrows. If\\n * the collateral is higher than the threshold, use regular liquidations. If the collateral is\\n * below the threshold, and the account is insolvent, use healAccount.\\n * @param borrower the borrower address\\n * @param orders an array of liquidation orders\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation\\n * @custom:error InsufficientCollateral error is thrown when there is not enough collateral to cover the debt\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function liquidateAccount(address borrower, LiquidationOrder[] calldata orders) external {\\n // We will accrue interest and update the oracle prices later during the liquidation\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n // You should use the regular vToken.liquidateBorrow(...) call\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n uint256 collateralToSeize = mul_ScalarTruncate(\\n Exp({ mantissa: liquidationIncentiveMantissa }),\\n snapshot.borrows\\n );\\n if (collateralToSeize >= snapshot.totalCollateral) {\\n // There is not enough collateral to seize. Use healBorrow to repay some part of the borrow\\n // and record bad debt.\\n revert InsufficientCollateral(collateralToSeize, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n uint256 ordersCount = orders.length;\\n\\n _ensureMaxLoops(ordersCount / 2);\\n\\n for (uint256 i; i < ordersCount; ++i) {\\n if (!markets[address(orders[i].vTokenBorrowed)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenBorrowed));\\n }\\n if (!markets[address(orders[i].vTokenCollateral)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenCollateral));\\n }\\n\\n LiquidationOrder calldata order = orders[i];\\n order.vTokenBorrowed.forceLiquidateBorrow(\\n msg.sender,\\n borrower,\\n order.repayAmount,\\n order.vTokenCollateral,\\n true\\n );\\n }\\n\\n VToken[] memory borrowMarkets = getAssetsIn(borrower);\\n uint256 marketsCount = borrowMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower);\\n require(borrowBalance == 0, \\\"Nonzero borrow balance after liquidation\\\");\\n }\\n }\\n\\n /**\\n * @notice Sets the closeFactor to use when liquidating borrows\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @custom:event Emits NewCloseFactor on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCloseFactor(uint256 newCloseFactorMantissa) external {\\n _checkAccessAllowed(\\\"setCloseFactor(uint256)\\\");\\n require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, \\\"Close factor greater than maximum close factor\\\");\\n require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, \\\"Close factor smaller than minimum close factor\\\");\\n\\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev This function is restricted by the AccessControlManager\\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 * @custom:event Emits NewCollateralFactor when collateral factor is updated\\n * and NewLiquidationThreshold when liquidation threshold is updated\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InvalidCollateralFactor error is thrown when collateral factor is too high\\n * @custom:error InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor\\n * @custom:error PriceError is thrown when the oracle returns an invalid price for the asset\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCollateralFactor(\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external {\\n _checkAccessAllowed(\\\"setCollateralFactor(address,uint256,uint256)\\\");\\n\\n // Verify market is listed\\n Market storage market = markets[address(vToken)];\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Check collateral factor <= 0.9\\n if (newCollateralFactorMantissa > MAX_COLLATERAL_FACTOR_MANTISSA) {\\n revert InvalidCollateralFactor();\\n }\\n\\n // Ensure that liquidation threshold <= 1\\n if (newLiquidationThresholdMantissa > MANTISSA_ONE) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // Ensure that liquidation threshold >= CF\\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n }\\n\\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\\n emit NewLiquidationThreshold(vToken, oldLiquidationThresholdMantissa, newLiquidationThresholdMantissa);\\n }\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev This function is restricted by the AccessControlManager\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @custom:event Emits NewLiquidationIncentive on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external {\\n require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, \\\"liquidation incentive should be greater than 1e18\\\");\\n\\n _checkAccessAllowed(\\\"setLiquidationIncentive(uint256)\\\");\\n\\n // Save current value for use in log\\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\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\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Only callable by the PoolRegistry\\n * @param vToken The address of the market (token) to list\\n * @custom:error MarketAlreadyListed is thrown if the market is already listed in this pool\\n * @custom:access Only PoolRegistry\\n */\\n function supportMarket(VToken vToken) external {\\n _checkSenderIs(poolRegistry);\\n\\n if (markets[address(vToken)].isListed) {\\n revert MarketAlreadyListed(address(vToken));\\n }\\n\\n require(vToken.isVToken(), \\\"Comptroller: Invalid vToken\\\"); // Sanity check to make sure its really a VToken\\n\\n Market storage newMarket = markets[address(vToken)];\\n newMarket.isListed = true;\\n newMarket.collateralFactorMantissa = 0;\\n newMarket.liquidationThresholdMantissa = 0;\\n\\n _addMarket(address(vToken));\\n\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n rewardsDistributors[i].initializeMarket(address(vToken));\\n }\\n\\n emit MarketSupported(vToken);\\n }\\n\\n /**\\n * @notice Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A borrow cap of type(uint256).max corresponds to unlimited borrowing.\\n * @dev Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed\\n until the total borrows amount goes below the new borrow cap\\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 type(uint256).max corresponds to unlimited borrowing.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\\n _checkAccessAllowed(\\\"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 _ensureMaxLoops(numMarkets);\\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 * @notice Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A supply cap of type(uint256).max corresponds to unlimited supply.\\n * @dev Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed\\n until the total supplies amount goes below the new supply cap\\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 type(uint256).max corresponds to unlimited supply.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\\n _checkAccessAllowed(\\\"setMarketSupplyCaps(address[],uint256[])\\\");\\n uint256 vTokensCount = vTokens.length;\\n\\n require(vTokensCount != 0, \\\"invalid number of markets\\\");\\n require(vTokensCount == newSupplyCaps.length, \\\"invalid number of markets\\\");\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Pause/unpause specified actions\\n * @dev This function is restricted by the AccessControlManager\\n * @param marketsList Markets to pause/unpause the actions on\\n * @param actionsList List of action ids to pause/unpause\\n * @param paused The new paused state (true=paused, false=unpaused)\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setActionsPaused(VToken[] calldata marketsList, Action[] calldata actionsList, bool paused) external {\\n _checkAccessAllowed(\\\"setActionsPaused(address[],uint256[],bool)\\\");\\n\\n uint256 marketsCount = marketsList.length;\\n uint256 actionsCount = actionsList.length;\\n\\n _ensureMaxLoops(marketsCount * actionsCount);\\n\\n for (uint256 marketIdx; marketIdx < marketsCount; ++marketIdx) {\\n for (uint256 actionIdx; actionIdx < actionsCount; ++actionIdx) {\\n _setActionPaused(address(marketsList[marketIdx]), actionsList[actionIdx], paused);\\n }\\n }\\n }\\n\\n /**\\n * @notice Set the given collateral threshold for non-batch liquidations. Regular liquidations\\n * will fail if the collateral amount is less than this threshold. Liquidators should use batch\\n * operations like liquidateAccount or healAccount.\\n * @dev This function is restricted by the AccessControlManager\\n * @param newMinLiquidatableCollateral The new min liquidatable collateral (in USD).\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external {\\n _checkAccessAllowed(\\\"setMinLiquidatableCollateral(uint256)\\\");\\n\\n uint256 oldMinLiquidatableCollateral = minLiquidatableCollateral;\\n minLiquidatableCollateral = newMinLiquidatableCollateral;\\n emit NewMinLiquidatableCollateral(oldMinLiquidatableCollateral, newMinLiquidatableCollateral);\\n }\\n\\n /**\\n * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor\\n * contracts with the same rewardToken, and there could be overlaping among them considering the last reward slot (block or second)\\n * @dev Only callable by the admin\\n * @param _rewardsDistributor Address of the RewardDistributor contract to add\\n * @custom:access Only Governance\\n * @custom:event Emits NewRewardsDistributor with distributor address\\n */\\n function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner {\\n require(!rewardsDistributorExists[address(_rewardsDistributor)], \\\"already exists\\\");\\n\\n uint256 rewardsDistributorsLen = rewardsDistributors.length;\\n _ensureMaxLoops(rewardsDistributorsLen + 1);\\n\\n rewardsDistributors.push(_rewardsDistributor);\\n rewardsDistributorExists[address(_rewardsDistributor)] = true;\\n\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n _rewardsDistributor.initializeMarket(address(allMarkets[i]));\\n }\\n\\n emit NewRewardsDistributor(address(_rewardsDistributor), address(_rewardsDistributor.rewardToken()));\\n }\\n\\n /**\\n * @notice Sets a new price oracle for the Comptroller\\n * @dev Only callable by the admin\\n * @param newOracle Address of the new price oracle to set\\n * @custom:event Emits NewPriceOracle on success\\n * @custom:error ZeroAddressNotAllowed is thrown when the new oracle address is zero\\n */\\n function setPriceOracle(ResilientOracleInterface newOracle) external onlyOwner {\\n ensureNonzeroAddress(address(newOracle));\\n\\n ResilientOracleInterface oldOracle = oracle;\\n oracle = newOracle;\\n emit NewPriceOracle(oldOracle, newOracle);\\n }\\n\\n /**\\n * @notice Set the for loop iteration limit to avoid DOS\\n * @param limit Limit for the max loops can execute at a time\\n */\\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Sets the prime token contract for the comptroller\\n * @param _prime Address of the Prime contract\\n */\\n function setPrimeToken(IPrime _prime) external onlyOwner {\\n ensureNonzeroAddress(address(_prime));\\n\\n emit NewPrimeToken(prime, _prime);\\n prime = _prime;\\n }\\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 * @param vTokenBorrowed Borrowed vToken\\n * @param enable Whether to enable forced liquidations\\n */\\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\\n _checkAccessAllowed(\\\"setForcedLiquidation(address,bool)\\\");\\n ensureNonzeroAddress(vTokenBorrowed);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(vTokenBorrowed);\\n }\\n\\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to liquidation threshold requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of liquidation threshold requirements,\\n * @return shortfall Account shortfall below liquidation threshold requirements\\n */\\n function getAccountLiquidity(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getLiquidationThreshold);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to collateral requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of collateral requirements,\\n * @return shortfall Account shortfall below collateral requirements\\n */\\n function getBorrowingPower(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getCollateralFactor);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Hypothetical account liquidity in excess of collateral requirements,\\n * @return shortfall 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 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n account,\\n VToken(vTokenModify),\\n redeemTokens,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\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 markets The list of market addresses\\n */\\n function getAllMarkets() external view override returns (VToken[] memory) {\\n return allMarkets;\\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 /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns whether the given account is entered in a given market\\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 market specified, 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 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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return tokensToSeize Number of vTokenCollateral tokens to be seized in a liquidation\\n * @custom:error PriceError if the oracle returns an invalid price\\n */\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view override returns (uint256 error, uint256 tokensToSeize) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint256 priceBorrowedMantissa = _safeGetUnderlyingPrice(VToken(vTokenBorrowed));\\n uint256 priceCollateralMantissa = _safeGetUnderlyingPrice(VToken(vTokenCollateral));\\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 uint256 exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint256 seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n\\n numerator = mul_(Exp({ mantissa: liquidationIncentiveMantissa }), Exp({ mantissa: priceBorrowedMantissa }));\\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\\n ratio = div_(numerator, denominator);\\n\\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\\n\\n return (NO_ERROR, seizeTokens);\\n }\\n\\n /**\\n * @notice Returns reward speed given a vToken\\n * @param vToken The vToken to get the reward speeds for\\n * @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors\\n */\\n function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {\\n uint256 rewardsDistributorsLength = rewardsDistributors.length;\\n rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);\\n for (uint256 i; i < rewardsDistributorsLength; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n address rewardToken = address(rewardsDistributor.rewardToken());\\n rewardSpeeds[i] = RewardSpeeds({\\n rewardToken: rewardToken,\\n supplySpeed: rewardsDistributor.rewardTokenSupplySpeeds(vToken),\\n borrowSpeed: rewardsDistributor.rewardTokenBorrowSpeeds(vToken)\\n });\\n }\\n return rewardSpeeds;\\n }\\n\\n /**\\n * @notice Return all reward distributors for this pool\\n * @return Array of RewardDistributor addresses\\n */\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory) {\\n return rewardsDistributors;\\n }\\n\\n /**\\n * @notice A marker method that returns true for a valid Comptroller contract\\n * @return Always true\\n */\\n function isComptroller() external pure override returns (bool) {\\n return true;\\n }\\n\\n /**\\n * @notice Update the prices of all the tokens associated with the provided account\\n * @param account Address of the account to get associated tokens with\\n */\\n function updatePrices(address account) public {\\n VToken[] memory vTokens = getAssetsIn(account);\\n uint256 vTokensCount = vTokens.length;\\n\\n ResilientOracleInterface oracle_ = oracle;\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n oracle_.updatePrice(address(vTokens[i]));\\n }\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param market vToken address\\n * @param action Action to check\\n * @return paused True if the action is paused otherwise false\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][action];\\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 list with the assets the account has entered\\n */\\n function getAssetsIn(address account) public 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 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 */\\n function _addToMarket(VToken vToken, address borrower) internal {\\n _checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = markets[address(vToken)];\\n\\n if (!marketToJoin.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return;\\n }\\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\\n /**\\n * @notice Internal function to validate that a market hasn't already been added\\n * and if it hasn't adds it\\n * @param vToken The market to support\\n */\\n function _addMarket(address vToken) internal {\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n if (allMarkets[i] == VToken(vToken)) {\\n revert MarketAlreadyListed(vToken);\\n }\\n }\\n allMarkets.push(VToken(vToken));\\n marketsCount = allMarkets.length;\\n _ensureMaxLoops(marketsCount);\\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 _setActionPaused(address market, Action action, bool paused) internal {\\n require(markets[market].isListed, \\\"cannot pause a market that is not listed\\\");\\n _actionPaused[market][action] = paused;\\n emit ActionPausedMarket(VToken(market), action, paused);\\n }\\n\\n /**\\n * @dev Internal function to check that vTokens can be safely redeemed for the underlying asset.\\n * @param vToken Address of the vTokens to redeem\\n * @param redeemer Account redeeming the tokens\\n * @param redeemTokens The number of tokens to redeem\\n */\\n function _checkRedeemAllowed(address vToken, address redeemer, uint256 redeemTokens) internal {\\n Market storage market = markets[vToken];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!market.accountMembership[redeemer]) {\\n return;\\n }\\n\\n // Update the prices of tokens\\n updatePrices(redeemer);\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n _getCollateralFactor\\n );\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n }\\n\\n /**\\n * @notice Get the total collateral, weighted collateral, borrow balance, liquidity, shortfall\\n * @param account The account to get the snapshot for\\n * @param weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n * liquidation threshold. Accepts the address of the vToken and returns the weight as Exp.\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getCurrentLiquiditySnapshot(\\n address account,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n return _getHypotheticalLiquiditySnapshot(account, VToken(address(0)), 0, 0, weight);\\n }\\n\\n /**\\n * @notice Determine what the supply/borrow balances 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 weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n liquidation threshold. Accepts the address of the VToken and returns the weight\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getHypotheticalLiquiditySnapshot(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n // For each asset the account is in\\n VToken[] memory assets = getAssetsIn(account);\\n uint256 assetsCount = assets.length;\\n\\n for (uint256 i; i < assetsCount; ++i) {\\n VToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the vToken\\n (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) = _safeGetAccountSnapshot(\\n asset,\\n account\\n );\\n\\n // Get the normalized price of the asset\\n Exp memory oraclePrice = Exp({ mantissa: _safeGetUnderlyingPrice(asset) });\\n\\n // Pre-compute conversion factors from vTokens -> usd\\n Exp memory vTokenPrice = mul_(Exp({ mantissa: exchangeRateMantissa }), oraclePrice);\\n Exp memory weightedVTokenPrice = mul_(weight(asset), vTokenPrice);\\n\\n // weightedCollateral += weightedVTokenPrice * vTokenBalance\\n snapshot.weightedCollateral = mul_ScalarTruncateAddUInt(\\n weightedVTokenPrice,\\n vTokenBalance,\\n snapshot.weightedCollateral\\n );\\n\\n // totalCollateral += vTokenPrice * vTokenBalance\\n snapshot.totalCollateral = mul_ScalarTruncateAddUInt(vTokenPrice, vTokenBalance, snapshot.totalCollateral);\\n\\n // borrows += oraclePrice * borrowBalance\\n snapshot.borrows = mul_ScalarTruncateAddUInt(oraclePrice, borrowBalance, snapshot.borrows);\\n\\n // Calculate effects of interacting with vTokenModify\\n if (asset == vTokenModify) {\\n // redeem effect\\n // effects += tokensToDenom * redeemTokens\\n snapshot.effects = mul_ScalarTruncateAddUInt(weightedVTokenPrice, redeemTokens, snapshot.effects);\\n\\n // borrow effect\\n // effects += oraclePrice * borrowAmount\\n snapshot.effects = mul_ScalarTruncateAddUInt(oraclePrice, borrowAmount, snapshot.effects);\\n }\\n }\\n\\n uint256 borrowPlusEffects = snapshot.borrows + snapshot.effects;\\n // These are safe, as the underflow condition is checked first\\n unchecked {\\n if (snapshot.weightedCollateral > borrowPlusEffects) {\\n snapshot.liquidity = snapshot.weightedCollateral - borrowPlusEffects;\\n snapshot.shortfall = 0;\\n } else {\\n snapshot.liquidity = 0;\\n snapshot.shortfall = borrowPlusEffects - snapshot.weightedCollateral;\\n }\\n }\\n\\n return snapshot;\\n }\\n\\n /**\\n * @dev Retrieves price from oracle for an asset and checks it is nonzero\\n * @param asset Address for asset to query price\\n * @return Underlying price\\n */\\n function _safeGetUnderlyingPrice(VToken asset) internal view returns (uint256) {\\n uint256 oraclePriceMantissa = oracle.getUnderlyingPrice(address(asset));\\n if (oraclePriceMantissa == 0) {\\n revert PriceError(address(asset));\\n }\\n return oraclePriceMantissa;\\n }\\n\\n /**\\n * @dev Return collateral factor for a market\\n * @param asset Address for asset\\n * @return Collateral factor as exponential\\n */\\n function _getCollateralFactor(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].collateralFactorMantissa });\\n }\\n\\n /**\\n * @dev Retrieves liquidation threshold for a market as an exponential\\n * @param asset Address for asset to liquidation threshold\\n * @return Liquidation threshold as exponential\\n */\\n function _getLiquidationThreshold(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].liquidationThresholdMantissa });\\n }\\n\\n /**\\n * @dev Returns supply and borrow balances of user in vToken, reverts on failure\\n * @param vToken Market to query\\n * @param user Account address\\n * @return vTokenBalance Balance of vTokens, the same as vToken.balanceOf(user)\\n * @return borrowBalance Borrowed amount, including the interest\\n * @return exchangeRateMantissa Stored exchange rate\\n */\\n function _safeGetAccountSnapshot(\\n VToken vToken,\\n address user\\n ) internal view returns (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) {\\n uint256 err;\\n (err, vTokenBalance, borrowBalance, exchangeRateMantissa) = vToken.getAccountSnapshot(user);\\n if (err != 0) {\\n revert SnapshotError(address(vToken), user);\\n }\\n return (vTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /// @notice Reverts if the call is not from expectedSender\\n /// @param expectedSender Expected transaction sender\\n function _checkSenderIs(address expectedSender) internal view {\\n if (msg.sender != expectedSender) {\\n revert UnexpectedSender(expectedSender, msg.sender);\\n }\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n /// @param market Market to check\\n /// @param action Action to check\\n function _checkActionPauseState(address market, Action action) private view {\\n if (actionPaused(market, action)) {\\n revert ActionPaused(market, action);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7c6e1c6264e4681f82a9ac1bcd9155197a930033291ee5561ad97a56006f5e9c\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.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\\n/**\\n * @title ComptrollerInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract.\\n */\\ninterface ComptrollerInterface {\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\\n\\n function exitMarket(address vToken) external returns (uint256);\\n\\n /*** Policy Hooks ***/\\n\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external;\\n\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external;\\n\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external;\\n\\n function preRepayHook(address vToken, address borrower) external;\\n\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external;\\n\\n function preSeizeHook(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower\\n ) external;\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\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 seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external;\\n\\n function isComptroller() external view returns (bool);\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 repayAmount\\n ) external view returns (uint256, uint256);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n}\\n\\n/**\\n * @title ComptrollerViewInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract, including only some util view functions.\\n */\\ninterface ComptrollerViewInterface {\\n function markets(address) external view returns (bool, uint256);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function closeFactorMantissa() external view returns (uint256);\\n\\n function liquidationIncentiveMantissa() external view returns (uint256);\\n\\n function minLiquidatableCollateral() external view returns (uint256);\\n\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function borrowCaps(address) external view returns (uint256);\\n\\n function supplyCaps(address) external view returns (uint256);\\n\\n function approvedDelegates(address user, address delegate) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xcbf7f9977472650c61345b7cbde23e81f626e1f8863bab4c6ce3dacfc7604919\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { IPrime } from \\\"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\\\";\\nimport { Action } from \\\"./ComptrollerInterface.sol\\\";\\n\\n/**\\n * @title ComptrollerStorage\\n * @author Venus\\n * @notice Storage layout for the `Comptroller` contract.\\n */\\ncontract ComptrollerStorage {\\n struct LiquidationOrder {\\n VToken vTokenCollateral;\\n VToken vTokenBorrowed;\\n uint256 repayAmount;\\n }\\n\\n struct AccountLiquiditySnapshot {\\n uint256 totalCollateral;\\n uint256 weightedCollateral;\\n uint256 borrows;\\n uint256 effects;\\n uint256 liquidity;\\n uint256 shortfall;\\n }\\n\\n struct RewardSpeeds {\\n address rewardToken;\\n uint256 supplySpeed;\\n uint256 borrowSpeed;\\n }\\n\\n struct Market {\\n // Whether or not this market is listed\\n bool isListed;\\n // 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 uint256 collateralFactorMantissa;\\n // 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 uint256 liquidationThresholdMantissa;\\n // Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n }\\n\\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 Per-account mapping of \\\"assets you are in\\\"\\n */\\n mapping(address => VToken[]) public accountAssets;\\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 /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\\n mapping(address => uint256) public borrowCaps;\\n\\n /// @notice Minimal collateral required for regular (non-batch) liquidations\\n uint256 public minLiquidatableCollateral;\\n\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\\n mapping(address => uint256) public supplyCaps;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(Action => bool)) internal _actionPaused;\\n\\n // List of Reward Distributors added\\n RewardsDistributor[] internal rewardsDistributors;\\n\\n // Used to check if rewards distributor is added\\n mapping(address => bool) internal rewardsDistributorExists;\\n\\n /// @notice Flag indicating whether forced liquidation enabled for a market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n\\n uint256 internal constant NO_ERROR = 0;\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant MIN_CLOSE_FACTOR_MANTISSA = 0.05e18; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant MAX_CLOSE_FACTOR_MANTISSA = 0.9e18; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.95e18; // 0.95\\n\\n /// Prime token address\\n IPrime public prime;\\n\\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 /**\\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[47] private __gap;\\n}\\n\",\"keccak256\":\"0x4df44cb65ac152bac2be4b4545430e703005a74a55b72e144100b16421bd8bfd\",\"license\":\"BSD-3-Clause\"},\"contracts/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title TokenErrorReporter\\n * @author Venus\\n * @notice Errors that can be thrown by the `VToken` contract.\\n */\\ncontract TokenErrorReporter {\\n uint256 public constant NO_ERROR = 0; // support legacy return codes\\n\\n error TransferNotAllowed();\\n\\n error MintFreshnessCheck();\\n\\n error RedeemFreshnessCheck();\\n error RedeemTransferOutNotPossible();\\n\\n error BorrowFreshnessCheck();\\n error BorrowCashNotAvailable();\\n error DelegateNotApproved();\\n\\n error RepayBorrowFreshnessCheck();\\n\\n error HealBorrowUnauthorized();\\n error ForceLiquidateBorrowUnauthorized();\\n\\n error LiquidateFreshnessCheck();\\n error LiquidateCollateralFreshnessCheck();\\n error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\\n error LiquidateLiquidatorIsBorrower();\\n error LiquidateCloseAmountIsZero();\\n error LiquidateCloseAmountIsUintMax();\\n\\n error LiquidateSeizeLiquidatorIsBorrower();\\n\\n error ProtocolSeizeShareTooBig();\\n\\n error SetReserveFactorFreshCheck();\\n error SetReserveFactorBoundsCheck();\\n\\n error AddReservesFactorFreshCheck(uint256 actualAddAmount);\\n\\n error ReduceReservesFreshCheck();\\n error ReduceReservesCashNotAvailable();\\n error ReduceReservesCashValidation();\\n\\n error SetInterestRateModelFreshCheck();\\n}\\n\",\"keccak256\":\"0x7a7ced1caaac2d9242659ebd50b99f308c725ce958ac9e11f7ada404b1d97a7b\",\"license\":\"BSD-3-Clause\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from \\\"./lib/constants.sol\\\";\\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 struct Exp {\\n uint256 mantissa;\\n }\\n\\n struct Double {\\n uint256 mantissa;\\n }\\n\\n uint256 internal constant EXP_SCALE = EXP_SCALE_;\\n uint256 internal constant DOUBLE_SCALE = 1e36;\\n uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;\\n uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint256) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / EXP_SCALE;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\\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 // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint256 scalar, uint256 addend) internal pure returns (uint256) {\\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 function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\\n require(n <= type(uint224).max, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\\n require(n <= type(uint32).max, 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_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a + b;\\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_(uint256 a, uint256 b) internal pure returns (uint256) {\\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) / EXP_SCALE });\\n }\\n\\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / EXP_SCALE;\\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) / DOUBLE_SCALE });\\n }\\n\\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / DOUBLE_SCALE;\\n }\\n\\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a * b;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return div_(mul_(a, EXP_SCALE), 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, DOUBLE_SCALE), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return div_(mul_(a, DOUBLE_SCALE), b.mantissa);\\n }\\n\\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a / b;\\n }\\n\\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });\\n }\\n}\\n\",\"keccak256\":\"0x8afbe8a24fe3539c124e718681ed3dcebd24c40dd53095786c0155998213b9b0\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModel.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\nabstract contract InterestRateModel {\\n /**\\n * @notice Calculates the current borrow interest rate per slot (block or second)\\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 amount of reserves the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per slot (block or second)\\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 amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\\n * @return Always true\\n */\\n function isInterestRateModel() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xc4fda1ab75ebe4b187b707c4f10c58780f343cf343c537f641dc75d3cd28ab51\",\"license\":\"BSD-3-Clause\"},\"contracts/Lens/PoolLens.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { IERC20Metadata } from \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Action, ComptrollerInterface, ComptrollerViewInterface } from \\\"../ComptrollerInterface.sol\\\";\\nimport { PoolRegistryInterface } from \\\"../Pool/PoolRegistryInterface.sol\\\";\\nimport { PoolRegistry } from \\\"../Pool/PoolRegistry.sol\\\";\\nimport { RewardsDistributor } from \\\"../Rewards/RewardsDistributor.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\n\\n/**\\n * @title PoolLens\\n * @author Venus\\n * @notice The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information\\n * for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be\\n * looked up for specific pools and markets:\\n- the vToken balance of a given user;\\n- the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address;\\n- the vToken address in a pool for a given asset;\\n- a list of all pools that support an asset;\\n- the underlying asset price of a vToken;\\n- the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\\n */\\ncontract PoolLens is ExponentialNoError, TimeManagerV8 {\\n /**\\n * @dev Struct for PoolDetails.\\n */\\n struct PoolData {\\n string name;\\n address creator;\\n address comptroller;\\n uint256 blockPosted;\\n uint256 timestampPosted;\\n string category;\\n string logoURL;\\n string description;\\n address priceOracle;\\n uint256 closeFactor;\\n uint256 liquidationIncentive;\\n uint256 minLiquidatableCollateral;\\n VTokenMetadata[] vTokens;\\n }\\n\\n /**\\n * @dev Struct for VToken.\\n */\\n struct VTokenMetadata {\\n address vToken;\\n uint256 exchangeRateCurrent;\\n uint256 supplyRatePerBlockOrTimestamp;\\n uint256 borrowRatePerBlockOrTimestamp;\\n uint256 reserveFactorMantissa;\\n uint256 supplyCaps;\\n uint256 borrowCaps;\\n uint256 totalBorrows;\\n uint256 totalReserves;\\n uint256 totalSupply;\\n uint256 totalCash;\\n bool isListed;\\n uint256 collateralFactorMantissa;\\n address underlyingAssetAddress;\\n uint256 vTokenDecimals;\\n uint256 underlyingDecimals;\\n uint256 pausedActions;\\n }\\n\\n /**\\n * @dev Struct for VTokenBalance.\\n */\\n struct VTokenBalances {\\n address vToken;\\n uint256 balanceOf;\\n uint256 borrowBalanceCurrent;\\n uint256 balanceOfUnderlying;\\n uint256 tokenBalance;\\n uint256 tokenAllowance;\\n }\\n\\n /**\\n * @dev Struct for underlyingPrice of VToken.\\n */\\n struct VTokenUnderlyingPrice {\\n address vToken;\\n uint256 underlyingPrice;\\n }\\n\\n /**\\n * @dev Struct with pending reward info for a market.\\n */\\n struct PendingReward {\\n address vTokenAddress;\\n uint256 amount;\\n }\\n\\n /**\\n * @dev Struct with reward distribution totals for a single reward token and distributor.\\n */\\n struct RewardSummary {\\n address distributorAddress;\\n address rewardTokenAddress;\\n uint256 totalRewards;\\n PendingReward[] pendingRewards;\\n }\\n\\n /**\\n * @dev Struct used in RewardDistributor to save last updated market state.\\n */\\n struct RewardTokenState {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number or timestamp the index was last updated at\\n uint256 blockOrTimestamp;\\n // The block number or timestamp at which to stop rewards\\n uint256 lastRewardingBlockOrTimestamp;\\n }\\n\\n /**\\n * @dev Struct with bad debt of a market denominated\\n */\\n struct BadDebt {\\n address vTokenAddress;\\n uint256 badDebtUsd;\\n }\\n\\n /**\\n * @dev Struct with bad debt total denominated in usd for a pool and an array of BadDebt structs for each market\\n */\\n struct BadDebtSummary {\\n address comptroller;\\n uint256 totalBadDebtUsd;\\n BadDebt[] badDebts;\\n }\\n\\n /// @notice Address of the core pool comptroller (all markets are returned for this pool, including paused ones)\\n address public immutable corePoolComptroller;\\n\\n /**\\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @param corePoolComptroller_ The address of the core pool comptroller\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(\\n bool timeBased_,\\n uint256 blocksPerYear_,\\n address corePoolComptroller_\\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\\n corePoolComptroller = corePoolComptroller_;\\n }\\n\\n /**\\n * @notice Queries the user's supply/borrow balances in vTokens\\n * @param vTokens The list of vToken addresses\\n * @param account The user Account\\n * @return A list of structs containing balances data\\n */\\n function vTokenBalancesAll(VToken[] calldata vTokens, address account) external returns (VTokenBalances[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenBalances[] memory res = new VTokenBalances[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenBalances(vTokens[i], account);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Queries all pools with addtional details for each of them\\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @return Arrays of all Venus pools' data\\n */\\n function getAllPools(address poolRegistryAddress) external view returns (PoolData[] memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n PoolRegistry.VenusPool[] memory venusPools = poolRegistryInterface.getAllPools();\\n uint256 poolLength = venusPools.length;\\n\\n PoolData[] memory poolDataItems = new PoolData[](poolLength);\\n\\n for (uint256 i; i < poolLength; ++i) {\\n PoolRegistry.VenusPool memory venusPool = venusPools[i];\\n PoolData memory poolData = getPoolDataFromVenusPool(poolRegistryAddress, venusPool);\\n poolDataItems[i] = poolData;\\n }\\n\\n return poolDataItems;\\n }\\n\\n /**\\n * @notice Queries the details of a pool identified by Comptroller address\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param comptroller The Comptroller implementation address\\n * @return PoolData structure containing the details of the pool\\n */\\n function getPoolByComptroller(\\n address poolRegistryAddress,\\n address comptroller\\n ) external view returns (PoolData memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return getPoolDataFromVenusPool(poolRegistryAddress, poolRegistryInterface.getPoolByComptroller(comptroller));\\n }\\n\\n /**\\n * @notice Returns vToken holding the specified underlying asset in the specified pool\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param comptroller The pool comptroller\\n * @param asset The underlyingAsset of VToken\\n * @return Address of the vToken\\n */\\n function getVTokenForAsset(\\n address poolRegistryAddress,\\n address comptroller,\\n address asset\\n ) external view returns (address) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return poolRegistryInterface.getVTokenForAsset(comptroller, asset);\\n }\\n\\n /**\\n * @notice Returns all pools that support the specified underlying asset\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param asset The underlying asset of vToken\\n * @return A list of Comptroller contracts\\n */\\n function getPoolsSupportedByAsset(\\n address poolRegistryAddress,\\n address asset\\n ) external view returns (address[] memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return poolRegistryInterface.getPoolsSupportedByAsset(asset);\\n }\\n\\n /**\\n * @notice Returns the price data for the underlying assets of the specified vTokens\\n * @param vTokens The list of vToken addresses\\n * @return An array containing the price data for each asset\\n */\\n function vTokenUnderlyingPriceAll(\\n VToken[] calldata vTokens\\n ) external view returns (VTokenUnderlyingPrice[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenUnderlyingPrice[] memory res = new VTokenUnderlyingPrice[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenUnderlyingPrice(vTokens[i]);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Returns the pending rewards for a user for a given pool.\\n * @param account The user account.\\n * @param comptrollerAddress address\\n * @return Pending rewards array\\n */\\n function getPendingRewards(\\n address account,\\n address comptrollerAddress\\n ) external view returns (RewardSummary[] memory) {\\n VToken[] memory markets = _getMarkets(ComptrollerInterface(comptrollerAddress));\\n RewardsDistributor[] memory rewardsDistributors = ComptrollerViewInterface(comptrollerAddress)\\n .getRewardDistributors();\\n RewardSummary[] memory rewardSummary = new RewardSummary[](rewardsDistributors.length);\\n for (uint256 i; i < rewardsDistributors.length; ++i) {\\n RewardSummary memory reward;\\n reward.distributorAddress = address(rewardsDistributors[i]);\\n reward.rewardTokenAddress = address(rewardsDistributors[i].rewardToken());\\n reward.totalRewards = rewardsDistributors[i].rewardTokenAccrued(account);\\n reward.pendingRewards = _calculateNotDistributedAwards(account, markets, rewardsDistributors[i]);\\n rewardSummary[i] = reward;\\n }\\n return rewardSummary;\\n }\\n\\n /**\\n * @notice Returns a summary of a pool's bad debt broken down by market\\n *\\n * @param comptrollerAddress Address of the comptroller\\n *\\n * @return badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and\\n * a break down of bad debt by market\\n */\\n function getPoolBadDebt(address comptrollerAddress) external view returns (BadDebtSummary memory) {\\n uint256 totalBadDebtUsd;\\n\\n // Get every listed market in the pool\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\\n VToken[] memory markets = _getMarkets(ComptrollerInterface(comptrollerAddress));\\n ResilientOracleInterface priceOracle = comptroller.oracle();\\n\\n BadDebt[] memory badDebts = new BadDebt[](markets.length);\\n\\n BadDebtSummary memory badDebtSummary;\\n badDebtSummary.comptroller = comptrollerAddress;\\n badDebtSummary.badDebts = badDebts;\\n\\n // // Calculate the bad debt is USD per market\\n for (uint256 i; i < markets.length; ++i) {\\n BadDebt memory badDebt;\\n badDebt.vTokenAddress = address(markets[i]);\\n badDebt.badDebtUsd =\\n (VToken(address(markets[i])).badDebt() * priceOracle.getUnderlyingPrice(address(markets[i]))) /\\n EXP_SCALE;\\n badDebtSummary.badDebts[i] = badDebt;\\n totalBadDebtUsd = totalBadDebtUsd + badDebt.badDebtUsd;\\n }\\n\\n badDebtSummary.totalBadDebtUsd = totalBadDebtUsd;\\n\\n return badDebtSummary;\\n }\\n\\n /**\\n * @notice Queries the user's supply/borrow balances in the specified vToken\\n * @param vToken vToken address\\n * @param account The user Account\\n * @return A struct containing the balances data\\n */\\n function vTokenBalances(VToken vToken, address account) public returns (VTokenBalances memory) {\\n uint256 balanceOf = vToken.balanceOf(account);\\n uint256 borrowBalanceCurrent = vToken.borrowBalanceCurrent(account);\\n uint256 balanceOfUnderlying = vToken.balanceOfUnderlying(account);\\n uint256 tokenBalance;\\n uint256 tokenAllowance;\\n\\n IERC20 underlying = IERC20(vToken.underlying());\\n tokenBalance = underlying.balanceOf(account);\\n tokenAllowance = underlying.allowance(account, address(vToken));\\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 Queries additional information for the pool\\n * @param poolRegistryAddress Address of the PoolRegistry\\n * @param venusPool The VenusPool Object from PoolRegistry\\n * @return Enriched PoolData\\n */\\n function getPoolDataFromVenusPool(\\n address poolRegistryAddress,\\n PoolRegistry.VenusPool memory venusPool\\n ) public view returns (PoolData memory) {\\n // Get tokens in the Pool\\n ComptrollerInterface comptrollerInstance = ComptrollerInterface(venusPool.comptroller);\\n\\n VToken[] memory vTokens = _getMarkets(comptrollerInstance);\\n\\n VTokenMetadata[] memory vTokenMetadataItems = vTokenMetadataAll(vTokens);\\n\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n\\n PoolRegistry.VenusPoolMetaData memory venusPoolMetaData = poolRegistryInterface.getVenusPoolMetadata(\\n venusPool.comptroller\\n );\\n\\n ComptrollerViewInterface comptrollerViewInstance = ComptrollerViewInterface(venusPool.comptroller);\\n\\n PoolData memory poolData = PoolData({\\n name: venusPool.name,\\n creator: venusPool.creator,\\n comptroller: venusPool.comptroller,\\n blockPosted: venusPool.blockPosted,\\n timestampPosted: venusPool.timestampPosted,\\n category: venusPoolMetaData.category,\\n logoURL: venusPoolMetaData.logoURL,\\n description: venusPoolMetaData.description,\\n vTokens: vTokenMetadataItems,\\n priceOracle: address(comptrollerViewInstance.oracle()),\\n closeFactor: comptrollerViewInstance.closeFactorMantissa(),\\n liquidationIncentive: comptrollerViewInstance.liquidationIncentiveMantissa(),\\n minLiquidatableCollateral: comptrollerViewInstance.minLiquidatableCollateral()\\n });\\n\\n return poolData;\\n }\\n\\n /**\\n * @notice Returns the metadata of VToken\\n * @param vToken The address of vToken\\n * @return VTokenMetadata struct\\n */\\n function vTokenMetadata(VToken vToken) public view returns (VTokenMetadata memory) {\\n uint256 exchangeRateCurrent = vToken.exchangeRateStored();\\n address comptrollerAddress = address(vToken.comptroller());\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\\n (bool isListed, uint256 collateralFactorMantissa) = comptroller.markets(address(vToken));\\n\\n address underlyingAssetAddress = vToken.underlying();\\n uint256 underlyingDecimals = IERC20Metadata(underlyingAssetAddress).decimals();\\n\\n uint256 pausedActions;\\n for (uint8 i; i <= uint8(type(Action).max); ++i) {\\n uint256 paused = ComptrollerInterface(comptrollerAddress).actionPaused(address(vToken), Action(i)) ? 1 : 0;\\n pausedActions |= paused << i;\\n }\\n\\n uint256 supplyRatePerBlock;\\n\\n if (vToken.totalSupply() > 0) {\\n supplyRatePerBlock = vToken.supplyRatePerBlock();\\n }\\n\\n return\\n VTokenMetadata({\\n vToken: address(vToken),\\n exchangeRateCurrent: exchangeRateCurrent,\\n supplyRatePerBlockOrTimestamp: supplyRatePerBlock,\\n borrowRatePerBlockOrTimestamp: vToken.borrowRatePerBlock(),\\n reserveFactorMantissa: vToken.reserveFactorMantissa(),\\n supplyCaps: comptroller.supplyCaps(address(vToken)),\\n borrowCaps: comptroller.borrowCaps(address(vToken)),\\n totalBorrows: vToken.totalBorrows(),\\n totalReserves: vToken.totalReserves(),\\n totalSupply: vToken.totalSupply(),\\n totalCash: vToken.getCash(),\\n isListed: isListed,\\n collateralFactorMantissa: collateralFactorMantissa,\\n underlyingAssetAddress: underlyingAssetAddress,\\n vTokenDecimals: vToken.decimals(),\\n underlyingDecimals: underlyingDecimals,\\n pausedActions: pausedActions\\n });\\n }\\n\\n /**\\n * @notice Returns the metadata of all VTokens\\n * @param vTokens The list of vToken addresses\\n * @return An array of VTokenMetadata structs\\n */\\n function vTokenMetadataAll(VToken[] memory vTokens) public view returns (VTokenMetadata[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenMetadata[] memory res = new VTokenMetadata[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenMetadata(vTokens[i]);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Returns the price data for the underlying asset of the specified vToken\\n * @param vToken vToken address\\n * @return The price data for each asset\\n */\\n function vTokenUnderlyingPrice(VToken vToken) public view returns (VTokenUnderlyingPrice memory) {\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(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 Returns markets from a comptroller. For the core pool, all markets are returned.\\n * For other pools, markets with zero internalCash are filtered.\\n * @param comptroller The comptroller to query\\n * @return An array of VToken addresses\\n */\\n function _getMarkets(ComptrollerInterface comptroller) internal view returns (VToken[] memory) {\\n VToken[] memory allMarkets = comptroller.getAllMarkets();\\n\\n if (address(comptroller) == corePoolComptroller) {\\n return allMarkets;\\n }\\n\\n // Single-loop filter: pack active markets to the front of allMarkets\\n uint256 count;\\n uint256 len = allMarkets.length;\\n for (uint256 i; i < len; ++i) {\\n if (allMarkets[i].internalCash() > 0) {\\n allMarkets[count] = allMarkets[i];\\n ++count;\\n }\\n }\\n\\n // Trim the array to the active count\\n assembly {\\n mstore(allMarkets, count)\\n }\\n\\n return allMarkets;\\n }\\n\\n function _calculateNotDistributedAwards(\\n address account,\\n VToken[] memory markets,\\n RewardsDistributor rewardsDistributor\\n ) internal view returns (PendingReward[] memory) {\\n PendingReward[] memory pendingRewards = new PendingReward[](markets.length);\\n\\n for (uint256 i; i < markets.length; ++i) {\\n // Market borrow and supply state we will modify update in-memory, in order to not modify storage\\n RewardTokenState memory borrowState;\\n RewardTokenState memory supplyState;\\n\\n if (isTimeBased) {\\n (\\n borrowState.index,\\n borrowState.blockOrTimestamp,\\n borrowState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenBorrowStateTimeBased(address(markets[i]));\\n (\\n supplyState.index,\\n supplyState.blockOrTimestamp,\\n supplyState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenSupplyStateTimeBased(address(markets[i]));\\n } else {\\n (\\n borrowState.index,\\n borrowState.blockOrTimestamp,\\n borrowState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenBorrowState(address(markets[i]));\\n (\\n supplyState.index,\\n supplyState.blockOrTimestamp,\\n supplyState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenSupplyState(address(markets[i]));\\n }\\n\\n Exp memory marketBorrowIndex = Exp({ mantissa: markets[i].borrowIndex() });\\n\\n // Update market supply and borrow index in-memory\\n updateMarketBorrowIndex(address(markets[i]), rewardsDistributor, borrowState, marketBorrowIndex);\\n updateMarketSupplyIndex(address(markets[i]), rewardsDistributor, supplyState);\\n\\n // Calculate pending rewards\\n uint256 borrowReward = calculateBorrowerReward(\\n address(markets[i]),\\n rewardsDistributor,\\n account,\\n borrowState,\\n marketBorrowIndex\\n );\\n uint256 supplyReward = calculateSupplierReward(\\n address(markets[i]),\\n rewardsDistributor,\\n account,\\n supplyState\\n );\\n\\n PendingReward memory pendingReward;\\n pendingReward.vTokenAddress = address(markets[i]);\\n pendingReward.amount = borrowReward + supplyReward;\\n pendingRewards[i] = pendingReward;\\n }\\n return pendingRewards;\\n }\\n\\n function updateMarketBorrowIndex(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n RewardTokenState memory borrowState,\\n Exp memory marketBorrowIndex\\n ) internal view {\\n uint256 borrowSpeed = rewardsDistributor.rewardTokenBorrowSpeeds(vToken);\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (\\n borrowState.lastRewardingBlockOrTimestamp > 0 &&\\n blockNumberOrTimestamp > borrowState.lastRewardingBlockOrTimestamp\\n ) {\\n blockNumberOrTimestamp = borrowState.lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, borrowState.blockOrTimestamp);\\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\\n // Remove the total earned interest rate since the opening of the market from total borrows\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, borrowSpeed);\\n Double memory ratio = borrowAmount > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\\n } else if (deltaBlocksOrTimestamp > 0) {\\n borrowState.blockOrTimestamp = blockNumberOrTimestamp;\\n }\\n }\\n\\n function updateMarketSupplyIndex(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n RewardTokenState memory supplyState\\n ) internal view {\\n uint256 supplySpeed = rewardsDistributor.rewardTokenSupplySpeeds(vToken);\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (\\n supplyState.lastRewardingBlockOrTimestamp > 0 &&\\n blockNumberOrTimestamp > supplyState.lastRewardingBlockOrTimestamp\\n ) {\\n blockNumberOrTimestamp = supplyState.lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, supplyState.blockOrTimestamp);\\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, supplySpeed);\\n Double memory ratio = supplyTokens > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\\n } else if (deltaBlocksOrTimestamp > 0) {\\n supplyState.blockOrTimestamp = blockNumberOrTimestamp;\\n }\\n }\\n\\n function calculateBorrowerReward(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n address borrower,\\n RewardTokenState memory borrowState,\\n Exp memory marketBorrowIndex\\n ) internal view returns (uint256) {\\n Double memory borrowIndex = Double({ mantissa: borrowState.index });\\n Double memory borrowerIndex = Double({\\n mantissa: rewardsDistributor.rewardTokenBorrowerIndex(vToken, borrower)\\n });\\n if (borrowerIndex.mantissa == 0 && borrowIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set\\n borrowerIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\\n }\\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n return borrowerDelta;\\n }\\n\\n function calculateSupplierReward(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n address supplier,\\n RewardTokenState memory supplyState\\n ) internal view returns (uint256) {\\n Double memory supplyIndex = Double({ mantissa: supplyState.index });\\n Double memory supplierIndex = Double({\\n mantissa: rewardsDistributor.rewardTokenSupplierIndex(vToken, supplier)\\n });\\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\\n // Covers the case where users supplied tokens before the market's supply state index was set\\n supplierIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\\n }\\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n return supplierDelta;\\n }\\n}\\n\",\"keccak256\":\"0xfe3f00ebb7f0b5c98ee03cf1cfa1a013a56984cf6879373c70a74b3d9d0db399\",\"license\":\"BSD-3-Clause\"},\"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\",\"keccak256\":\"0x4c25e30635485d162177effa384eee51768b0141a567a0da16ff6ad673274166\",\"license\":\"BSD-3-Clause\"},\"contracts/Pool/PoolRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\nimport { PoolRegistryInterface } from \\\"./PoolRegistryInterface.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"../lib/validators.sol\\\";\\n\\n/**\\n * @title PoolRegistry\\n * @author Venus\\n * @notice The Isolated Pools architecture centers around the `PoolRegistry` contract. The `PoolRegistry` maintains a directory of isolated lending\\n * pools and can perform actions like creating and registering new pools, adding new markets to existing pools, setting and updating the pool's required\\n * metadata, and providing the getter methods to get information on the pools.\\n *\\n * Isolated lending has three main components: PoolRegistry, pools, and markets. The PoolRegistry is responsible for managing pools.\\n * It can create new pools, update pool metadata and manage markets within pools. PoolRegistry contains getter methods to get the details of\\n * any existing pool like `getVTokenForAsset` and `getPoolsSupportedByAsset`. It also contains methods for updating pool metadata (`updatePoolMetadata`)\\n * and setting pool name (`setPoolName`).\\n *\\n * The directory of pools is managed through two mappings: `_poolByComptroller` which is a hashmap with the comptroller address as the key and `VenusPool` as\\n * the value and `_poolsByID` which is an array of comptroller addresses. Individual pools can be accessed by calling `getPoolByComptroller` with the pool's\\n * comptroller address. `_poolsByID` is used to iterate through all of the pools.\\n *\\n * PoolRegistry also contains a map of asset addresses called `_supportedPools` that maps to an array of assets suppored by each pool. This array of pools by\\n * asset is retrieved by calling `getPoolsSupportedByAsset`.\\n *\\n * PoolRegistry registers new isolated pools in the directory with the `createRegistryPool` method. Isolated pools are composed of independent markets with\\n * specific assets and custom risk management configurations according to their markets.\\n */\\ncontract PoolRegistry is Ownable2StepUpgradeable, AccessControlledV8, PoolRegistryInterface {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n struct AddMarketInput {\\n VToken vToken;\\n uint256 collateralFactor;\\n uint256 liquidationThreshold;\\n uint256 initialSupply;\\n address vTokenReceiver;\\n uint256 supplyCap;\\n uint256 borrowCap;\\n }\\n\\n uint256 internal constant MAX_POOL_NAME_LENGTH = 100;\\n\\n /**\\n * @notice Maps pool's comptroller address to metadata.\\n */\\n mapping(address => VenusPoolMetaData) public metadata;\\n\\n /**\\n * @dev Maps pool ID to pool's comptroller address\\n */\\n mapping(uint256 => address) private _poolsByID;\\n\\n /**\\n * @dev Total number of pools created.\\n */\\n uint256 private _numberOfPools;\\n\\n /**\\n * @dev Maps comptroller address to Venus pool Index.\\n */\\n mapping(address => VenusPool) private _poolByComptroller;\\n\\n /**\\n * @dev Maps pool's comptroller address to asset to vToken.\\n */\\n mapping(address => mapping(address => address)) private _vTokens;\\n\\n /**\\n * @dev Maps asset to list of supported pools.\\n */\\n mapping(address => address[]) private _supportedPools;\\n\\n /**\\n * @notice Emitted when a new Venus pool is added to the directory.\\n */\\n event PoolRegistered(address indexed comptroller, VenusPool pool);\\n\\n /**\\n * @notice Emitted when a pool name is set.\\n */\\n event PoolNameSet(address indexed comptroller, string oldName, string newName);\\n\\n /**\\n * @notice Emitted when a pool metadata is updated.\\n */\\n event PoolMetadataUpdated(\\n address indexed comptroller,\\n VenusPoolMetaData oldMetadata,\\n VenusPoolMetaData newMetadata\\n );\\n\\n /**\\n * @notice Emitted when a Market is added to the pool.\\n */\\n event MarketAdded(address indexed comptroller, address indexed vTokenAddress);\\n\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor() {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializes the deployer to owner\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(address accessControlManager_) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n /**\\n * @notice Adds a new Venus pool to the directory\\n * @dev Price oracle must be configured before adding a pool\\n * @param name The name of the pool\\n * @param comptroller Pool's Comptroller contract\\n * @param closeFactor The pool's close factor (scaled by 1e18)\\n * @param liquidationIncentive The pool's liquidation incentive (scaled by 1e18)\\n * @param minLiquidatableCollateral Minimal collateral for regular (non-batch) liquidations flow\\n * @return index The index of the registered Venus pool\\n * @custom:error ZeroAddressNotAllowed is thrown when Comptroller address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\\n */\\n function addPool(\\n string calldata name,\\n Comptroller comptroller,\\n uint256 closeFactor,\\n uint256 liquidationIncentive,\\n uint256 minLiquidatableCollateral\\n ) external virtual returns (uint256 index) {\\n _checkAccessAllowed(\\\"addPool(string,address,uint256,uint256,uint256)\\\");\\n // Input validation\\n ensureNonzeroAddress(address(comptroller));\\n ensureNonzeroAddress(address(comptroller.oracle()));\\n\\n uint256 poolId = _registerPool(name, address(comptroller));\\n\\n // Set Venus pool parameters\\n comptroller.setCloseFactor(closeFactor);\\n comptroller.setLiquidationIncentive(liquidationIncentive);\\n comptroller.setMinLiquidatableCollateral(minLiquidatableCollateral);\\n\\n return poolId;\\n }\\n\\n /**\\n * @notice Add a market to an existing pool and then mint to provide initial supply\\n * @param input The structure describing the parameters for adding a market to a pool\\n * @custom:error ZeroAddressNotAllowed is thrown when vToken address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when vTokenReceiver address is zero\\n */\\n function addMarket(AddMarketInput memory input) external {\\n _checkAccessAllowed(\\\"addMarket(AddMarketInput)\\\");\\n ensureNonzeroAddress(address(input.vToken));\\n ensureNonzeroAddress(input.vTokenReceiver);\\n require(input.initialSupply > 0, \\\"PoolRegistry: initialSupply is zero\\\");\\n\\n VToken vToken = input.vToken;\\n address vTokenAddress = address(vToken);\\n address comptrollerAddress = address(vToken.comptroller());\\n Comptroller comptroller = Comptroller(comptrollerAddress);\\n address underlyingAddress = vToken.underlying();\\n IERC20Upgradeable underlying = IERC20Upgradeable(underlyingAddress);\\n\\n require(_poolByComptroller[comptrollerAddress].creator != address(0), \\\"PoolRegistry: Pool not registered\\\");\\n // solhint-disable-next-line reason-string\\n require(\\n _vTokens[comptrollerAddress][underlyingAddress] == address(0),\\n \\\"PoolRegistry: Market already added for asset comptroller combination\\\"\\n );\\n\\n comptroller.supportMarket(vToken);\\n comptroller.setCollateralFactor(vToken, input.collateralFactor, input.liquidationThreshold);\\n\\n uint256[] memory newSupplyCaps = new uint256[](1);\\n uint256[] memory newBorrowCaps = new uint256[](1);\\n VToken[] memory vTokens = new VToken[](1);\\n\\n newSupplyCaps[0] = input.supplyCap;\\n newBorrowCaps[0] = input.borrowCap;\\n vTokens[0] = vToken;\\n\\n comptroller.setMarketSupplyCaps(vTokens, newSupplyCaps);\\n comptroller.setMarketBorrowCaps(vTokens, newBorrowCaps);\\n\\n _vTokens[comptrollerAddress][underlyingAddress] = vTokenAddress;\\n _supportedPools[underlyingAddress].push(comptrollerAddress);\\n\\n uint256 amountToSupply = _transferIn(underlying, msg.sender, input.initialSupply);\\n underlying.forceApprove(vTokenAddress, 0);\\n underlying.forceApprove(vTokenAddress, amountToSupply);\\n vToken.mintBehalf(input.vTokenReceiver, amountToSupply);\\n\\n emit MarketAdded(comptrollerAddress, vTokenAddress);\\n }\\n\\n /**\\n * @notice Modify existing Venus pool name\\n * @param comptroller Pool's Comptroller\\n * @param name New pool name\\n */\\n function setPoolName(address comptroller, string calldata name) external {\\n _checkAccessAllowed(\\\"setPoolName(address,string)\\\");\\n _ensureValidName(name);\\n VenusPool storage pool = _poolByComptroller[comptroller];\\n string memory oldName = pool.name;\\n pool.name = name;\\n emit PoolNameSet(comptroller, oldName, name);\\n }\\n\\n /**\\n * @notice Update metadata of an existing pool\\n * @param comptroller Pool's Comptroller\\n * @param metadata_ New pool metadata\\n */\\n function updatePoolMetadata(address comptroller, VenusPoolMetaData calldata metadata_) external {\\n _checkAccessAllowed(\\\"updatePoolMetadata(address,VenusPoolMetaData)\\\");\\n VenusPoolMetaData memory oldMetadata = metadata[comptroller];\\n metadata[comptroller] = metadata_;\\n emit PoolMetadataUpdated(comptroller, oldMetadata, metadata_);\\n }\\n\\n /**\\n * @notice Returns arrays of all Venus pools' data\\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\\n * @return A list of all pools within PoolRegistry, with details for each pool\\n */\\n function getAllPools() external view override returns (VenusPool[] memory) {\\n uint256 numberOfPools_ = _numberOfPools; // storage load to save gas\\n VenusPool[] memory _pools = new VenusPool[](numberOfPools_);\\n for (uint256 i = 1; i <= numberOfPools_; ++i) {\\n address comptroller = _poolsByID[i];\\n _pools[i - 1] = (_poolByComptroller[comptroller]);\\n }\\n return _pools;\\n }\\n\\n /**\\n * @param comptroller The comptroller proxy address associated to the pool\\n * @return Returns Venus pool\\n */\\n function getPoolByComptroller(address comptroller) external view override returns (VenusPool memory) {\\n return _poolByComptroller[comptroller];\\n }\\n\\n /**\\n * @param comptroller comptroller of Venus pool\\n * @return Returns Metadata of Venus pool\\n */\\n function getVenusPoolMetadata(address comptroller) external view override returns (VenusPoolMetaData memory) {\\n return metadata[comptroller];\\n }\\n\\n function getVTokenForAsset(address comptroller, address asset) external view override returns (address) {\\n return _vTokens[comptroller][asset];\\n }\\n\\n function getPoolsSupportedByAsset(address asset) external view override returns (address[] memory) {\\n return _supportedPools[asset];\\n }\\n\\n /**\\n * @dev Adds a new Venus pool to the directory (without checking msg.sender).\\n * @param name The name of the pool\\n * @param comptroller The pool's Comptroller proxy contract address\\n * @return The index of the registered Venus pool\\n */\\n function _registerPool(string calldata name, address comptroller) internal returns (uint256) {\\n VenusPool storage storedPool = _poolByComptroller[comptroller];\\n\\n require(storedPool.creator == address(0), \\\"PoolRegistry: Pool already exists in the directory.\\\");\\n _ensureValidName(name);\\n\\n ++_numberOfPools;\\n uint256 numberOfPools_ = _numberOfPools; // cache on stack to save storage read gas\\n\\n VenusPool memory pool = VenusPool(name, msg.sender, comptroller, block.number, block.timestamp);\\n\\n _poolsByID[numberOfPools_] = comptroller;\\n _poolByComptroller[comptroller] = pool;\\n\\n emit PoolRegistered(comptroller, pool);\\n return numberOfPools_;\\n }\\n\\n function _transferIn(IERC20Upgradeable token, address from, uint256 amount) internal returns (uint256) {\\n uint256 balanceBefore = token.balanceOf(address(this));\\n token.safeTransferFrom(from, address(this), amount);\\n uint256 balanceAfter = token.balanceOf(address(this));\\n return balanceAfter - balanceBefore;\\n }\\n\\n function _ensureValidName(string calldata name) internal pure {\\n require(bytes(name).length <= MAX_POOL_NAME_LENGTH, \\\"Pool's name is too large\\\");\\n }\\n}\\n\",\"keccak256\":\"0xafbb871f7b4db3ef439d846baa5f18a136192f9b43ea695c81262a77b06c4b25\",\"license\":\"BSD-3-Clause\"},\"contracts/Pool/PoolRegistryInterface.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 /**\\n * @notice Struct for a Venus interest rate pool metadata.\\n */\\n struct VenusPoolMetaData {\\n string category;\\n string logoURL;\\n string description;\\n }\\n\\n /// @notice Get all pools in PoolRegistry\\n function getAllPools() external view returns (VenusPool[] memory);\\n\\n /// @notice Get a pool by comptroller address\\n function getPoolByComptroller(address comptroller) external view returns (VenusPool memory);\\n\\n /// @notice Get the address of the VToken contract in the Pool where the underlying token is the provided 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 /// @notice Get the metadata of a Pool by comptroller address\\n function getVenusPoolMetadata(address comptroller) external view returns (VenusPoolMetaData memory);\\n}\\n\",\"keccak256\":\"0x7b39cda3b372a686501ce3c2aad288c6af410148110318249d75d4516729c92c\",\"license\":\"BSD-3-Clause\"},\"contracts/Rewards/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\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 { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"../MaxLoopsLimitHelper.sol\\\";\\nimport { RewardsDistributorStorage } from \\\"./RewardsDistributorStorage.sol\\\";\\n\\n/**\\n * @title `RewardsDistributor`\\n * @author Venus\\n * @notice Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol.\\n * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward\\n * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool.\\n * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward\\n * token to be released each slot (block or second) for borrowers and suppliers, which is distributed based on a user\\u2019s percentage of the borrows or supplies\\n * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting\\n * their contributor reward token speed, which similarly allocates a fixed amount of reward token per slot (block or second).\\n *\\n * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed\\n * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized\\n * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\\n */\\ncontract RewardsDistributor is\\n ExponentialNoError,\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n MaxLoopsLimitHelper,\\n RewardsDistributorStorage,\\n TimeManagerV8\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice The initial REWARD TOKEN index for a market\\n uint224 public constant INITIAL_INDEX = 1e36;\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a supplier\\n event DistributedSupplierRewardToken(\\n VToken indexed vToken,\\n address indexed supplier,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenSupplyIndex\\n );\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a borrower\\n event DistributedBorrowerRewardToken(\\n VToken indexed vToken,\\n address indexed borrower,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenBorrowIndex\\n );\\n\\n /// @notice Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when REWARD TOKEN is granted by admin\\n event RewardTokenGranted(address indexed recipient, uint256 amount);\\n\\n /// @notice Emitted when a new REWARD TOKEN speed is set for a contributor\\n event ContributorRewardTokenSpeedUpdated(address indexed contributor, uint256 newSpeed);\\n\\n /// @notice Emitted when a market is initialized\\n event MarketInitialized(address indexed vToken);\\n\\n /// @notice Emitted when a reward token supply index is updated\\n event RewardTokenSupplyIndexUpdated(address indexed vToken);\\n\\n /// @notice Emitted when a reward token borrow index is updated\\n event RewardTokenBorrowIndexUpdated(address indexed vToken, Exp marketBorrowIndex);\\n\\n /// @notice Emitted when a reward for contributor is updated\\n event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued);\\n\\n /// @notice Emitted when a reward token last rewarding block for supply is updated\\n event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding block for borrow is updated\\n event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding timestamp for supply is updated\\n event SupplyLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\\n\\n /// @notice Emitted when a reward token last rewarding timestamp for borrow is updated\\n event BorrowLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\\n\\n modifier onlyComptroller() {\\n require(address(comptroller) == msg.sender, \\\"Only comptroller can call this function\\\");\\n _;\\n }\\n\\n /**\\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice RewardsDistributor initializer\\n * @dev Initializes the deployer to owner\\n * @param comptroller_ Comptroller to attach the reward distributor to\\n * @param rewardToken_ Reward token to distribute\\n * @param loopsLimit_ Maximum number of iterations for the loops in this contract\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(\\n Comptroller comptroller_,\\n IERC20Upgradeable rewardToken_,\\n uint256 loopsLimit_,\\n address accessControlManager_\\n ) external initializer {\\n comptroller = comptroller_;\\n rewardToken = rewardToken_;\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n\\n _setMaxLoopsLimit(loopsLimit_);\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken\\n * @param vToken The address of the vToken to be initialized\\n * @custom:event MarketInitialized emits on success\\n * @custom:access Only Comptroller\\n */\\n function initializeMarket(address vToken) external onlyComptroller {\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n isTimeBased\\n ? _initializeMarketTimestampBased(vToken, blockNumberOrTimestamp)\\n : _initializeMarketBlockBased(vToken, safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\"));\\n\\n emit MarketInitialized(vToken);\\n }\\n\\n /*** Reward Token Distribution ***/\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them\\n * Borrowers will begin to accrue after the first interaction with the protocol.\\n * @dev This function should only be called when the user has a borrow position in the market\\n * (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook)\\n * We avoid an external call to check if they are in the market to save gas because this function is called in many places\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function distributeBorrowerRewardToken(\\n address vToken,\\n address borrower,\\n Exp memory marketBorrowIndex\\n ) external onlyComptroller {\\n _distributeBorrowerRewardToken(vToken, borrower, marketBorrowIndex);\\n }\\n\\n function updateRewardTokenSupplyIndex(address vToken) external onlyComptroller {\\n _updateRewardTokenSupplyIndex(vToken);\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the recipient\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\\n * @param recipient The address of the recipient to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n */\\n function grantRewardToken(address recipient, uint256 amount) external onlyOwner {\\n uint256 amountLeft = _grantRewardToken(recipient, amount);\\n require(amountLeft == 0, \\\"insufficient rewardToken for grant\\\");\\n emit RewardTokenGranted(recipient, amount);\\n }\\n\\n function updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) external onlyComptroller {\\n _updateRewardTokenBorrowIndex(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN borrow and supply speeds for the specified markets\\n * @param vTokens The markets whose REWARD TOKEN speed to update\\n * @param supplySpeeds New supply-side REWARD TOKEN speed for the corresponding market\\n * @param borrowSpeeds New borrow-side REWARD TOKEN speed for the corresponding market\\n */\\n function setRewardTokenSpeeds(\\n VToken[] memory vTokens,\\n uint256[] memory supplySpeeds,\\n uint256[] memory borrowSpeeds\\n ) external {\\n _checkAccessAllowed(\\\"setRewardTokenSpeeds(address[],uint256[],uint256[])\\\");\\n uint256 numTokens = vTokens.length;\\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \\\"invalid setRewardTokenSpeeds\\\");\\n\\n for (uint256 i; i < numTokens; ++i) {\\n _setRewardTokenSpeed(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for the specified markets, used when contract is block based\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market\\n * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market\\n */\\n function setLastRewardingBlocks(\\n VToken[] calldata vTokens,\\n uint32[] calldata supplyLastRewardingBlocks,\\n uint32[] calldata borrowLastRewardingBlocks\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlocks(address[],uint32[],uint32[])\\\");\\n require(!isTimeBased, \\\"Block-based operation only\\\");\\n\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length,\\n \\\"RewardsDistributor::setLastRewardingBlocks invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlock(vTokens[i], supplyLastRewardingBlocks[i], borrowLastRewardingBlocks[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block timestamp for the specified markets, used when contract is time based\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlockTimestamps New supply-side REWARD TOKEN last rewarding block timestamp for the corresponding market\\n * @param borrowLastRewardingBlockTimestamps New borrow-side REWARD TOKEN last rewarding block timestamp for the corresponding market\\n */\\n function setLastRewardingBlockTimestamps(\\n VToken[] calldata vTokens,\\n uint256[] calldata supplyLastRewardingBlockTimestamps,\\n uint256[] calldata borrowLastRewardingBlockTimestamps\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlockTimestamps(address[],uint256[],uint256[])\\\");\\n require(isTimeBased, \\\"Time-based operation only\\\");\\n\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlockTimestamps.length &&\\n numTokens == borrowLastRewardingBlockTimestamps.length,\\n \\\"RewardsDistributor::setLastRewardingBlockTimestamps invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlockTimestamp(\\n vTokens[i],\\n supplyLastRewardingBlockTimestamps[i],\\n borrowLastRewardingBlockTimestamps[i]\\n );\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single contributor\\n * @param contributor The contributor whose REWARD TOKEN speed to update\\n * @param rewardTokenSpeed New REWARD TOKEN speed for contributor\\n */\\n function setContributorRewardTokenSpeed(address contributor, uint256 rewardTokenSpeed) external onlyOwner {\\n // note that REWARD TOKEN speed could be set to 0 to halt liquidity rewards for a contributor\\n updateContributorRewards(contributor);\\n if (rewardTokenSpeed == 0) {\\n // release storage\\n delete lastContributorBlock[contributor];\\n } else {\\n lastContributorBlock[contributor] = getBlockNumberOrTimestamp();\\n }\\n rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed;\\n\\n emit ContributorRewardTokenSpeedUpdated(contributor, rewardTokenSpeed);\\n }\\n\\n function distributeSupplierRewardToken(address vToken, address supplier) external onlyComptroller {\\n _distributeSupplierRewardToken(vToken, supplier);\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in all markets\\n * @param holder The address to claim REWARD TOKEN for\\n */\\n function claimRewardToken(address holder) external {\\n return claimRewardToken(holder, comptroller.getAllMarkets());\\n }\\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) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Calculate additional accrued REWARD TOKEN for a contributor since last accrual\\n * @param contributor The address to calculate contributor rewards for\\n */\\n function updateContributorRewards(address contributor) public {\\n uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, lastContributorBlock[contributor]);\\n if (deltaBlocksOrTimestamp > 0 && rewardTokenSpeed > 0) {\\n uint256 newAccrued = mul_(deltaBlocksOrTimestamp, rewardTokenSpeed);\\n uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued);\\n\\n rewardTokenAccrued[contributor] = contributorAccrued;\\n lastContributorBlock[contributor] = blockNumberOrTimestamp;\\n\\n emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]);\\n }\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in the specified markets\\n * @param holder The address to claim REWARD TOKEN for\\n * @param vTokens The list of markets to claim REWARD TOKEN in\\n */\\n function claimRewardToken(address holder, VToken[] memory vTokens) public {\\n uint256 vTokensCount = vTokens.length;\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n VToken vToken = vTokens[i];\\n require(comptroller.isMarketListed(vToken), \\\"market must be listed\\\");\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n _distributeBorrowerRewardToken(address(vToken), holder, borrowIndex);\\n _updateRewardTokenSupplyIndex(address(vToken));\\n _distributeSupplierRewardToken(address(vToken), holder);\\n }\\n rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for a single market.\\n * @param vToken market's whose reward token last rewarding block to be updated\\n * @param supplyLastRewardingBlock New supply-side REWARD TOKEN last rewarding block for market\\n * @param borrowLastRewardingBlock New borrow-side REWARD TOKEN last rewarding block for market\\n */\\n function _setLastRewardingBlock(\\n VToken vToken,\\n uint32 supplyLastRewardingBlock,\\n uint32 borrowLastRewardingBlock\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockNumber = getBlockNumberOrTimestamp();\\n\\n require(supplyLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n require(borrowLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n\\n uint32 currentSupplyLastRewardingBlock = rewardTokenSupplyState[address(vToken)].lastRewardingBlock;\\n uint32 currentBorrowLastRewardingBlock = rewardTokenBorrowState[address(vToken)].lastRewardingBlock;\\n\\n require(\\n currentSupplyLastRewardingBlock == 0 || currentSupplyLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlock == 0 || currentBorrowLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlock != supplyLastRewardingBlock) {\\n rewardTokenSupplyState[address(vToken)].lastRewardingBlock = supplyLastRewardingBlock;\\n emit SupplyLastRewardingBlockUpdated(address(vToken), supplyLastRewardingBlock);\\n }\\n\\n if (currentBorrowLastRewardingBlock != borrowLastRewardingBlock) {\\n rewardTokenBorrowState[address(vToken)].lastRewardingBlock = borrowLastRewardingBlock;\\n emit BorrowLastRewardingBlockUpdated(address(vToken), borrowLastRewardingBlock);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding timestamp for a single market.\\n * @param vToken market's whose reward token last rewarding timestamp to be updated\\n * @param supplyLastRewardingBlockTimestamp New supply-side REWARD TOKEN last rewarding timestamp for market\\n * @param borrowLastRewardingBlockTimestamp New borrow-side REWARD TOKEN last rewarding timestamp for market\\n */\\n function _setLastRewardingBlockTimestamp(\\n VToken vToken,\\n uint256 supplyLastRewardingBlockTimestamp,\\n uint256 borrowLastRewardingBlockTimestamp\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockTimestamp = getBlockNumberOrTimestamp();\\n\\n require(\\n supplyLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"setting last rewarding timestamp in the past is not allowed\\\"\\n );\\n require(\\n borrowLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"setting last rewarding timestamp in the past is not allowed\\\"\\n );\\n\\n uint256 currentSupplyLastRewardingBlockTimestamp = rewardTokenSupplyStateTimeBased[address(vToken)]\\n .lastRewardingTimestamp;\\n uint256 currentBorrowLastRewardingBlockTimestamp = rewardTokenBorrowStateTimeBased[address(vToken)]\\n .lastRewardingTimestamp;\\n\\n require(\\n currentSupplyLastRewardingBlockTimestamp == 0 || currentSupplyLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlockTimestamp == 0 || currentBorrowLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlockTimestamp != supplyLastRewardingBlockTimestamp) {\\n rewardTokenSupplyStateTimeBased[address(vToken)].lastRewardingTimestamp = supplyLastRewardingBlockTimestamp;\\n emit SupplyLastRewardingBlockTimestampUpdated(address(vToken), supplyLastRewardingBlockTimestamp);\\n }\\n\\n if (currentBorrowLastRewardingBlockTimestamp != borrowLastRewardingBlockTimestamp) {\\n rewardTokenBorrowStateTimeBased[address(vToken)].lastRewardingTimestamp = borrowLastRewardingBlockTimestamp;\\n emit BorrowLastRewardingBlockTimestampUpdated(address(vToken), borrowLastRewardingBlockTimestamp);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single market.\\n * @param vToken market's whose reward token rate to be updated\\n * @param supplySpeed New supply-side REWARD TOKEN speed for market\\n * @param borrowSpeed New borrow-side REWARD TOKEN speed for market\\n */\\n function _setRewardTokenSpeed(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n if (rewardTokenSupplySpeeds[address(vToken)] != supplySpeed) {\\n // Supply speed updated so let's update supply state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n _updateRewardTokenSupplyIndex(address(vToken));\\n\\n // Update speed and emit event\\n rewardTokenSupplySpeeds[address(vToken)] = supplySpeed;\\n emit RewardTokenSupplySpeedUpdated(vToken, supplySpeed);\\n }\\n\\n if (rewardTokenBorrowSpeeds[address(vToken)] != borrowSpeed) {\\n // Borrow speed updated so let's update borrow state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n\\n // Update speed and emit event\\n rewardTokenBorrowSpeeds[address(vToken)] = borrowSpeed;\\n emit RewardTokenBorrowSpeedUpdated(vToken, borrowSpeed);\\n }\\n }\\n\\n /**\\n * @notice Calculate REWARD TOKEN 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 REWARD TOKEN to\\n */\\n function _distributeSupplierRewardToken(address vToken, address supplier) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\\n\\n uint256 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\\n uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier];\\n\\n // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenSupplierIndex[vToken][supplier] = supplyIndex;\\n\\n if (supplierIndex == 0 && supplyIndex >= INITIAL_INDEX) {\\n // Covers the case where users supplied tokens before the market's supply state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when supplier rewards were first\\n // set for the market.\\n supplierIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per vToken accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\\n\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerVToken\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n\\n uint256 supplierAccrued = add_(rewardTokenAccrued[supplier], supplierDelta);\\n rewardTokenAccrued[supplier] = supplierAccrued;\\n\\n emit DistributedSupplierRewardToken(VToken(vToken), supplier, supplierDelta, supplierAccrued, supplyIndex);\\n }\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them.\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function _distributeBorrowerRewardToken(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\\n\\n uint256 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\\n uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower];\\n\\n // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenBorrowerIndex[vToken][borrower] = borrowIndex;\\n\\n if (borrowerIndex == 0 && borrowIndex >= INITIAL_INDEX) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when borrower rewards were first\\n // set for the market.\\n borrowerIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per borrowed unit accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\\n\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerBorrowedUnit\\n if (borrowerAmount != 0) {\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n\\n uint256 borrowerAccrued = add_(rewardTokenAccrued[borrower], borrowerDelta);\\n rewardTokenAccrued[borrower] = borrowerAccrued;\\n\\n emit DistributedBorrowerRewardToken(VToken(vToken), borrower, borrowerDelta, borrowerAccrued, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the user.\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all.\\n * @param user The address of the user to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n * @return The amount of REWARD TOKEN which was NOT transferred to the user\\n */\\n function _grantRewardToken(address user, uint256 amount) internal returns (uint256) {\\n uint256 rewardTokenRemaining = rewardToken.balanceOf(address(this));\\n if (amount > 0 && amount <= rewardTokenRemaining) {\\n rewardToken.safeTransfer(user, amount);\\n return 0;\\n }\\n return amount;\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the supply index\\n * @param vToken The market whose supply index to update\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenSupplyIndex(address vToken) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\\n\\n uint256 supplySpeed = rewardTokenSupplySpeeds[vToken];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (!isTimeBased) {\\n safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\");\\n }\\n\\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\\n ? supplyStateTimeBased.lastRewardingTimestamp\\n : uint256(supplyState.lastRewardingBlock);\\n\\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(\\n blockNumberOrTimestamp,\\n (isTimeBased ? supplyStateTimeBased.timestamp : uint256(supplyState.block))\\n );\\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, supplySpeed);\\n Double memory ratio = supplyTokens > 0\\n ? fraction(accruedSinceUpdate, supplyTokens)\\n : Double({ mantissa: 0 });\\n uint224 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\\n uint224 index = safe224(\\n add_(Double({ mantissa: supplyIndex }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n\\n if (isTimeBased) {\\n supplyStateTimeBased.index = index;\\n supplyStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n supplyState.index = index;\\n supplyState.block = uint32(blockNumberOrTimestamp);\\n }\\n } else if (deltaBlocksOrTimestamp > 0) {\\n isTimeBased ? supplyStateTimeBased.timestamp = blockNumberOrTimestamp : supplyState.block = uint32(\\n blockNumberOrTimestamp\\n );\\n }\\n\\n emit RewardTokenSupplyIndexUpdated(vToken);\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the borrow index\\n * @param vToken The market whose borrow index to update\\n * @param marketBorrowIndex The current global borrow index of vToken\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\\n\\n uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (!isTimeBased) {\\n safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\");\\n }\\n\\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\\n ? borrowStateTimeBased.lastRewardingTimestamp\\n : uint256(borrowState.lastRewardingBlock);\\n\\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(\\n blockNumberOrTimestamp,\\n (isTimeBased ? borrowStateTimeBased.timestamp : uint256(borrowState.block))\\n );\\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, borrowSpeed);\\n Double memory ratio = borrowAmount > 0\\n ? fraction(accruedSinceUpdate, borrowAmount)\\n : Double({ mantissa: 0 });\\n uint224 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\\n uint224 index = safe224(\\n add_(Double({ mantissa: borrowIndex }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n\\n if (isTimeBased) {\\n borrowStateTimeBased.index = index;\\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n borrowState.index = index;\\n borrowState.block = uint32(blockNumberOrTimestamp);\\n }\\n } else if (deltaBlocksOrTimestamp > 0) {\\n if (isTimeBased) {\\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n borrowState.block = uint32(blockNumberOrTimestamp);\\n }\\n }\\n\\n emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken called when contract is block-based\\n * @param vToken The address of the vToken to be initialized\\n * @param blockNumber current block number\\n */\\n function _initializeMarketBlockBased(address vToken, uint32 blockNumber) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n RewardToken storage borrowState = rewardTokenBorrowState[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 = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block numbers\\n */\\n supplyState.block = borrowState.block = blockNumber;\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken called when contract is time-based\\n * @param vToken The address of the vToken to be initialized\\n * @param blockTimestamp current block timestamp\\n */\\n function _initializeMarketTimestampBased(address vToken, uint256 blockTimestamp) internal {\\n TimeBasedRewardToken storage supplyState = rewardTokenSupplyStateTimeBased[vToken];\\n TimeBasedRewardToken storage borrowState = rewardTokenBorrowStateTimeBased[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 = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block timestamp\\n */\\n supplyState.timestamp = borrowState.timestamp = blockTimestamp;\\n }\\n}\\n\",\"keccak256\":\"0x3cc824e59c923cfe25c4f1a875959b7e9410cde8e73cd405de13f301298c697f\",\"license\":\"BSD-3-Clause\"},\"contracts/Rewards/RewardsDistributorStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\n\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\n\\n/**\\n * @title RewardsDistributorStorage\\n * @author Venus\\n * @dev Storage for RewardsDistributor\\n */\\ncontract RewardsDistributorStorage {\\n struct RewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number the index was last updated at\\n uint32 block;\\n // The block number at which to stop rewards\\n uint32 lastRewardingBlock;\\n }\\n\\n struct TimeBasedRewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block timestamp the index was last updated at\\n uint256 timestamp;\\n // The block timestamp at which to stop rewards\\n uint256 lastRewardingTimestamp;\\n }\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => RewardToken) public rewardTokenSupplyState;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex;\\n\\n /// @notice The REWARD TOKEN accrued but not yet transferred to each user\\n mapping(address => uint256) public rewardTokenAccrued;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding borrow market per slot (block or second)\\n mapping(address => uint256) public rewardTokenBorrowSpeeds;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding supply market per slot (block or second)\\n mapping(address => uint256) public rewardTokenSupplySpeeds;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => RewardToken) public rewardTokenBorrowState;\\n\\n /// @notice The portion of REWARD TOKEN that each contributor receives per slot (block or second)\\n mapping(address => uint256) public rewardTokenContributorSpeeds;\\n\\n /// @notice Last slot (block or second) at which a contributor's REWARD TOKEN rewards have been allocated\\n mapping(address => uint256) public lastContributorBlock;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex;\\n\\n Comptroller internal comptroller;\\n\\n IERC20Upgradeable public rewardToken;\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => TimeBasedRewardToken) public rewardTokenSupplyStateTimeBased;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => TimeBasedRewardToken) public rewardTokenBorrowStateTimeBased;\\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[37] private __gap;\\n}\\n\",\"keccak256\":\"0x70e5015a78a2acf95277949c8b4796e10b9ac194130be006d5e5217e158070c0\",\"license\":\"BSD-3-Clause\"},\"contracts/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\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 { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"@venusprotocol/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\\\";\\n\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { ComptrollerInterface, ComptrollerViewInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"./ErrorReporter.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title VToken\\n * @author Venus\\n * @notice Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview,\\n * each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of\\n * the pool. The main actions a user regularly interacts with in a market are:\\n\\n- mint/redeem of vTokens;\\n- transfer of vTokens;\\n- borrow/repay a loan on an underlying asset;\\n- liquidate a borrow or liquidate/heal an account.\\n\\n * A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`.\\n * The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted\\n * `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken`\\n * as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that\\n * a user may borrow up to a portion of their collateral determined by the market\\u2019s collateral factor. However, if their borrowed amount exceeds an amount\\n * calculated using the market\\u2019s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also\\n * pay off interest accrued on the borrow.\\n * \\n * The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller`\\n * and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a\\n * total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`.\\n * Both functions settle all of an account\\u2019s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of\\n * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\\n */\\ncontract VToken is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n VTokenInterface,\\n ExponentialNoError,\\n TokenErrorReporter,\\n TimeManagerV8\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5%\\n\\n // Maximum fraction of interest that can be set aside for reserves\\n uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18;\\n\\n // Maximum borrow rate that can ever be applied per slot(block or second)\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n uint256 internal immutable MAX_BORROW_RATE_MANTISSA;\\n\\n /**\\n * Reentrancy Guard **\\n */\\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 * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @param maxBorrowRateMantissa_ The maximum value of borrowing rate mantissa\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(\\n bool timeBased_,\\n uint256 blocksPerYear_,\\n uint256 maxBorrowRateMantissa_\\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n require(maxBorrowRateMantissa_ <= 1e18, \\\"Max borrow rate must be <= 1e18\\\");\\n\\n MAX_BORROW_RATE_MANTISSA = maxBorrowRateMantissa_;\\n _disableInitializers();\\n }\\n\\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_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n */\\n function initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) external initializer {\\n ensureNonzeroAddress(admin_);\\n\\n // Initialize the market\\n _initialize(\\n underlying_,\\n comptroller_,\\n interestRateModel_,\\n initialExchangeRateMantissa_,\\n name_,\\n symbol_,\\n decimals_,\\n admin_,\\n accessControlManager_,\\n riskManagement,\\n reserveFactorMantissa_\\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 * @return success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, msg.sender, dst, amount);\\n return true;\\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 success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, src, dst, amount);\\n return true;\\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 (uint256.max means infinite)\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Increase approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param addedValue The number of additional tokens spender can transfer\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function increaseAllowance(address spender, uint256 addedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 newAllowance = transferAllowances[src][spender];\\n newAllowance += addedValue;\\n transferAllowances[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n return true;\\n }\\n\\n /**\\n * @notice Decreases approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param subtractedValue The number of tokens to remove from total approval\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 currentAllowance = transferAllowances[src][spender];\\n require(currentAllowance >= subtractedValue, \\\"decreased allowance below zero\\\");\\n unchecked {\\n currentAllowance -= subtractedValue;\\n }\\n\\n transferAllowances[src][spender] = currentAllowance;\\n\\n emit Approval(src, spender, currentAllowance);\\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 amount The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint256) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return totalBorrows The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\\n accrueInterest();\\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 borrowBalance The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n return _borrowBalanceStored(account);\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function mint(uint256 mintAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _mintFresh(msg.sender, msg.sender, mintAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param minter User whom the supply will be attributed to\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when minter address is zero\\n */\\n function mintBehalf(address minter, uint256 mintAmount) external override nonReentrant returns (uint256) {\\n ensureNonzeroAddress(minter);\\n\\n accrueInterest();\\n\\n _mintFresh(msg.sender, minter, mintAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function redeem(uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _redeemFresh(msg.sender, msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function redeemBehalf(address redeemer, uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n _ensureSenderIsDelegateOf(redeemer);\\n\\n accrueInterest();\\n\\n _redeemFresh(redeemer, msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\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 receive from redeeming vTokens\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n */\\n function redeemUnderlying(uint256 redeemAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _redeemFresh(msg.sender, msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function redeemUnderlyingBehalf(\\n address redeemer,\\n uint256 redeemAmount\\n ) external override nonReentrant returns (uint256) {\\n _ensureSenderIsDelegateOf(redeemer);\\n\\n accrueInterest();\\n\\n _redeemFresh(redeemer, msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function borrow(uint256 borrowAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _borrowFresh(msg.sender, msg.sender, borrowAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error DelegateNotApproved is thrown if caller is not approved delegate\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function borrowBehalf(address borrower, uint256 borrowAmount) external override returns (uint256) {\\n _ensureSenderIsDelegateOf(borrower);\\n accrueInterest();\\n\\n _borrowFresh(borrower, msg.sender, borrowAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrow(uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n return NO_ERROR;\\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, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _repayBorrowFresh(msg.sender, borrower, repayAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Not restricted\\n */\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external override returns (uint256) {\\n _liquidateBorrow(msg.sender, borrower, repayAmount, vTokenCollateral, false);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice sets protocol share accumulated from liquidations\\n * @dev must be equal or less than liquidation incentive - 1\\n * @param newProtocolSeizeShareMantissa_ new protocol share mantissa\\n * @custom:event Emits NewProtocolSeizeShare event on success\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error ProtocolSeizeShareTooBig is thrown when the new seize share is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa_) external {\\n _checkAccessAllowed(\\\"setProtocolSeizeShare(uint256)\\\");\\n uint256 liquidationIncentive = ComptrollerViewInterface(address(comptroller)).liquidationIncentiveMantissa();\\n if (newProtocolSeizeShareMantissa_ + MANTISSA_ONE > liquidationIncentive) {\\n revert ProtocolSeizeShareTooBig();\\n }\\n\\n uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\\n protocolSeizeShareMantissa = newProtocolSeizeShareMantissa_;\\n emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa_);\\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 * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n * @custom:event Emits NewReserveFactor event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant {\\n _checkAccessAllowed(\\\"setReserveFactor(uint256)\\\");\\n\\n accrueInterest();\\n _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to the protocol reserve contract\\n * @dev Gracefully return if reserves already reduced in accrueInterest\\n * @param reduceAmount Amount of reduction to reserves\\n * @custom:event Emits ReservesReduced event; may emit AccrueInterest\\n * @custom:error ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash\\n * @custom:error ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\\n * @custom:access Not restricted\\n */\\n function reduceReserves(uint256 reduceAmount) external override nonReentrant {\\n accrueInterest();\\n if (reduceReservesBlockNumber == getBlockNumberOrTimestamp()) return;\\n _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice The sender adds to reserves.\\n * @param addAmount The amount of underlying token to add as reserves\\n * @custom:event Emits ReservesAdded event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function addReserves(uint256 addAmount) external override nonReentrant {\\n accrueInterest();\\n _addReservesFresh(addAmount);\\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 * @custom:event Emits NewMarketInterestRateModel event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external override {\\n _checkAccessAllowed(\\\"setInterestRateModel(address)\\\");\\n\\n accrueInterest();\\n _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially\\n * \\\"forgiving\\\" the borrower. Healing is a situation that should rarely happen. However, some pools\\n * may list risky assets or be configured improperly \\u2013 we want to still handle such cases gracefully.\\n * We assume that Comptroller does the seizing, so this function is only available to Comptroller.\\n * @dev This function does not call any Comptroller hooks (like \\\"healAllowed\\\"), because we assume\\n * the Comptroller does all the necessary checks before calling this function.\\n * @param payer account who repays the debt\\n * @param borrower account to heal\\n * @param repayAmount amount to repay\\n * @custom:event Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\\n * @custom:error HealBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:access Only Comptroller\\n */\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external override nonReentrant {\\n if (repayAmount != 0) {\\n comptroller.preRepayHook(address(this), borrower);\\n }\\n\\n if (msg.sender != address(comptroller)) {\\n revert HealBorrowUnauthorized();\\n }\\n\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 totalBorrowsNew = totalBorrows;\\n\\n uint256 actualRepayAmount;\\n if (repayAmount != 0) {\\n // _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // We violate checks-effects-interactions here to account for tokens that take transfer fees\\n actualRepayAmount = _doTransferIn(payer, repayAmount);\\n totalBorrowsNew = totalBorrowsNew - actualRepayAmount;\\n emit RepayBorrow(\\n payer,\\n borrower,\\n actualRepayAmount,\\n accountBorrowsPrev - actualRepayAmount,\\n totalBorrowsNew\\n );\\n }\\n\\n // The transaction will fail if trying to repay too much\\n uint256 badDebtDelta = accountBorrowsPrev - actualRepayAmount;\\n if (badDebtDelta != 0) {\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld + badDebtDelta;\\n totalBorrowsNew = totalBorrowsNew - badDebtDelta;\\n badDebt = badDebtNew;\\n\\n // We treat healing as \\\"repayment\\\", where vToken is the payer\\n emit RepayBorrow(address(this), borrower, badDebtDelta, 0, totalBorrowsNew);\\n emit BadDebtIncreased(borrower, badDebtDelta, badDebtOld, badDebtNew);\\n }\\n\\n accountBorrows[borrower].principal = 0;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n emit HealBorrow(payer, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice The extended version of liquidations, callable only by Comptroller. May skip\\n * the close factor check. The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Only Comptroller\\n */\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) external override {\\n if (msg.sender != address(comptroller)) {\\n revert ForceLiquidateBorrowUnauthorized();\\n }\\n _liquidateBorrow(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\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 * @custom:event Emits Transfer, ReservesAdded events\\n * @custom:error LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:access Not restricted\\n */\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external override nonReentrant {\\n _seize(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Updates bad debt\\n * @dev Called only when bad debt is recovered from auction. Updates internal cash balance.\\n * @param recoveredAmount_ The amount of bad debt recovered\\n * @custom:event Emits BadDebtRecovered event\\n * @custom:access Only Shortfall contract\\n */\\n function badDebtRecovered(uint256 recoveredAmount_) external {\\n require(msg.sender == shortfall, \\\"only shortfall contract can update bad debt\\\");\\n require(recoveredAmount_ <= badDebt, \\\"more than bad debt recovered from auction\\\");\\n\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld - recoveredAmount_;\\n badDebt = badDebtNew;\\n internalCash += recoveredAmount_;\\n\\n emit BadDebtRecovered(badDebtOld, badDebtNew);\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protocolShareReserve_ The address of the protocol share reserve contract\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n * @custom:access Only Governance\\n */\\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\\n _setProtocolShareReserve(protocolShareReserve_);\\n }\\n\\n /**\\n * @notice Sets shortfall contract address\\n * @param shortfall_ The address of the shortfall contract\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:access Only Governance\\n */\\n function setShortfallContract(address shortfall_) external onlyOwner {\\n _setShortfallContract(shortfall_);\\n }\\n\\n /**\\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\\n * @param token The address of the ERC-20 token to sweep\\n * @custom:access Only Governance\\n */\\n function sweepToken(IERC20Upgradeable token) external override {\\n require(msg.sender == owner(), \\\"VToken::sweepToken: only admin can sweep tokens\\\");\\n require(address(token) != underlying, \\\"VToken::sweepToken: can not sweep underlying token\\\");\\n uint256 balance = token.balanceOf(address(this));\\n token.safeTransfer(owner(), balance);\\n\\n emit SweepToken(address(token));\\n }\\n\\n /**\\n * @notice Sync internalCash with the actual underlying token balance\\n * @dev Used for one-time migration after upgrade to initialize internalCash\\n * @custom:event Emits CashSynced\\n * @custom:access Controlled by AccessControlManager\\n */\\n function syncCash() external override nonReentrant {\\n _checkAccessAllowed(\\\"syncCash()\\\");\\n uint256 oldInternalCash = internalCash;\\n uint256 actualCash = IERC20Upgradeable(underlying).balanceOf(address(this));\\n internalCash = actualCash;\\n emit CashSynced(oldInternalCash, actualCash);\\n }\\n\\n /**\\n * @notice A public function to set new threshold of slot(block or second) difference after which funds will be sent to the protocol share reserve\\n * @param _newReduceReservesBlockOrTimestampDelta slot(block or second) difference value\\n * @custom:access Only Governance\\n */\\n function setReduceReservesBlockDelta(uint256 _newReduceReservesBlockOrTimestampDelta) external {\\n _checkAccessAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n require(_newReduceReservesBlockOrTimestampDelta > 0, \\\"Invalid Input\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, _newReduceReservesBlockOrTimestampDelta);\\n reduceReservesBlockDelta = _newReduceReservesBlockOrTimestampDelta;\\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 amount 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 amount 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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return vTokenBalance User's balance of vTokens\\n * @return borrowBalance Amount owed in terms of underlying\\n * @return exchangeRate Stored exchange rate\\n */\\n function getAccountSnapshot(\\n address account\\n )\\n external\\n view\\n override\\n returns (uint256 error, uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRate)\\n {\\n return (NO_ERROR, accountTokens[account], _borrowBalanceStored(account), _exchangeRateStored());\\n }\\n\\n /**\\n * @notice Get the internally tracked cash balance of this vToken in the underlying asset\\n * @return cash The quantity of underlying asset tracked internally by this contract\\n */\\n function getCash() external view override returns (uint256) {\\n return _getCashPrior();\\n }\\n\\n /**\\n * @notice Returns the current per slot(block or second) borrow interest rate for this vToken\\n * @return rate The borrow interest rate per slot(block or second), scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint256) {\\n return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt);\\n }\\n\\n /**\\n * @notice Returns the current per-slot(block or second) supply interest rate for this v\\n * @return rate The supply interest rate per slot(block or second), scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint256) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPrior(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa,\\n badDebt\\n );\\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 borrowBalance The calculated balance\\n */\\n function borrowBalanceStored(address account) external view override returns (uint256) {\\n return _borrowBalanceStored(account);\\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 exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() external view override returns (uint256) {\\n return _exchangeRateStored();\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\\n accrueInterest();\\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 slot(block or second)\\n * up to the current slot(block or second) and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentSlot - reduceReservesBlockNumber >= slotDelta\\n * @return Always NO_ERROR\\n * @custom:event Emits AccrueInterest event on success\\n * @custom:access Not restricted\\n */\\n function accrueInterest() public virtual override returns (uint256) {\\n /* Remember the initial block number or timestamp */\\n uint256 currentSlotNumber = getBlockNumberOrTimestamp();\\n uint256 accrualSlotNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualSlotNumberPrior == currentSlotNumber) {\\n return NO_ERROR;\\n }\\n\\n /* Read the previous values out of storage */\\n uint256 cashPrior = _getCashPrior();\\n uint256 borrowsPrior = totalBorrows;\\n uint256 reservesPrior = totalReserves;\\n uint256 borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt);\\n require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of slots elapsed since the last accrual */\\n uint256 slotDelta = currentSlotNumber - accrualSlotNumberPrior;\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * slotDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), slotDelta);\\n uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\\n uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;\\n uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentSlotNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n if (currentSlotNumber - reduceReservesBlockNumber >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentSlotNumber;\\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 NO_ERROR;\\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 or timestamp\\n * @param payer The address of the account which is sending the assets for supply\\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 */\\n function _mintFresh(address payer, address minter, uint256 mintAmount) internal {\\n /* Fail if mint not allowed */\\n comptroller.preMintHook(address(this), minter, mintAmount);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert MintFreshnessCheck();\\n }\\n\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\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 * `_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 uint256 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 uint256 mintTokens = div_(actualMintAmount, exchangeRate);\\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 * And write them into storage\\n */\\n totalSupply = totalSupply + mintTokens;\\n uint256 balanceAfter = accountTokens[minter] + mintTokens;\\n accountTokens[minter] = balanceAfter;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, actualMintAmount, mintTokens, balanceAfter);\\n emit Transfer(address(0), minter, mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, actualMintAmount, mintTokens);\\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 Comptroller.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current slot(block or second)\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the underlying 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 */\\n function _redeemFresh(address redeemer, address receiver, uint256 redeemTokensIn, uint256 redeemAmountIn) internal {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert RedeemFreshnessCheck();\\n }\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n\\n uint256 redeemTokens;\\n uint256 redeemAmount;\\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 */\\n redeemTokens = redeemTokensIn;\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n */\\n redeemTokens = div_(redeemAmountIn, exchangeRate);\\n\\n uint256 _redeemAmount = mul_(redeemTokens, exchangeRate);\\n if (_redeemAmount != 0 && _redeemAmount != redeemAmountIn) redeemTokens++; // round up\\n }\\n\\n // redeemAmount = exchangeRate * redeemTokens\\n redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokens);\\n\\n // Revert if amount is zero\\n if (redeemAmount == 0) {\\n revert(\\\"redeemAmount is zero\\\");\\n }\\n\\n /* Fail if redeem not allowed */\\n comptroller.preRedeemHook(address(this), redeemer, redeemTokens);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (_getCashPrior() - totalReserves < redeemAmount) {\\n revert RedeemTransferOutNotPossible();\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\\n */\\n totalSupply = totalSupply - redeemTokens;\\n uint256 balanceAfter = accountTokens[redeemer] - redeemTokens;\\n accountTokens[redeemer] = balanceAfter;\\n\\n /*\\n * We invoke _doTransferOut for the receiver and the redeemAmount.\\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 _doTransferOut(receiver, redeemAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), redeemTokens);\\n emit Redeem(redeemer, redeemAmount, redeemTokens, balanceAfter);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, redeemAmount, redeemTokens);\\n }\\n\\n /**\\n * @notice Users or their delegates borrow assets from the protocol\\n * @param borrower User who borrows the assets\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param borrowAmount The amount of the underlying asset to borrow\\n */\\n function _borrowFresh(address borrower, address receiver, uint256 borrowAmount) internal {\\n /* Fail if borrow not allowed */\\n comptroller.preBorrowHook(address(this), borrower, borrowAmount);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert BorrowFreshnessCheck();\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (_getCashPrior() - totalReserves < borrowAmount) {\\n revert BorrowCashNotAvailable();\\n }\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowNew = accountBorrow + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;\\n uint256 totalBorrowsNew = totalBorrows + borrowAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\\n `*/\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /*\\n * We invoke _doTransferOut for the receiver and the borrowAmount.\\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, accountBorrowsNew, totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\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 underlying tokens being returned, or type(uint256).max for the full outstanding amount\\n * @return (uint) the actual repayment amount.\\n */\\n function _repayBorrowFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256) {\\n /* Fail if repayBorrow not allowed */\\n comptroller.preRepayHook(address(this), borrower);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert RepayBorrowFreshnessCheck();\\n }\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n\\n uint256 repayAmountFinal = repayAmount >= accountBorrowsPrev ? accountBorrowsPrev : 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 * 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 uint256 actualRepayAmount = _doTransferIn(payer, repayAmountFinal);\\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 uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\\n uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, actualRepayAmount, borrowIndex);\\n\\n return actualRepayAmount;\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal nonReentrant {\\n accrueInterest();\\n\\n uint256 error = vTokenCollateral.accrueInterest();\\n if (error != NO_ERROR) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n revert LiquidateAccrueCollateralInterestFailed(error);\\n }\\n\\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal {\\n /* Fail if liquidate not allowed */\\n comptroller.preLiquidateHook(\\n address(this),\\n address(vTokenCollateral),\\n borrower,\\n repayAmount,\\n skipLiquidityCheck\\n );\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert LiquidateFreshnessCheck();\\n }\\n\\n /* Verify vTokenCollateral market's slot(block or second) number equals current slot(block or second) number */\\n if (vTokenCollateral.accrualBlockNumber() != getBlockNumberOrTimestamp()) {\\n revert LiquidateCollateralFreshnessCheck();\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateLiquidatorIsBorrower();\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n revert LiquidateCloseAmountIsZero();\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n revert LiquidateCloseAmountIsUintMax();\\n }\\n\\n /* Fail if repayBorrow fails */\\n uint256 actualRepayAmount = _repayBorrowFresh(liquidator, borrower, repayAmount);\\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.liquidateCalculateSeizeTokens(\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n require(amountSeizeError == 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, call _seize internally to avoid re-entrancy, otherwise make an external call\\n if (address(vTokenCollateral) == address(this)) {\\n _seize(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\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\\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 * It's absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerContract The contract seizing the collateral (either borrowed vToken or Comptroller)\\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 */\\n function _seize(address seizerContract, address liquidator, address borrower, uint256 seizeTokens) internal {\\n /* Fail if seize not allowed */\\n comptroller.preSeizeHook(address(this), seizerContract, liquidator, borrower);\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateSeizeLiquidatorIsBorrower();\\n }\\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 uint256 liquidationIncentiveMantissa = ComptrollerViewInterface(address(comptroller))\\n .liquidationIncentiveMantissa();\\n uint256 numerator = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));\\n uint256 protocolSeizeTokens = div_(numerator, Exp({ mantissa: liquidationIncentiveMantissa }));\\n uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n uint256 protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the calculated values into storage */\\n totalSupply = totalSupply - protocolSeizeTokens;\\n accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\\n accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\\n\\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, protocolSeizeAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.LIQUIDATION\\n );\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\\n emit ProtocolSeize(borrower, protocolShareReserve, protocolSeizeAmount);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerContract, liquidator, borrower, seizeTokens);\\n }\\n\\n function _setComptroller(ComptrollerInterface newComptroller) internal {\\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\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n */\\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal {\\n // Verify market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert SetReserveFactorFreshCheck();\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > MAX_RESERVE_FACTOR_MANTISSA) {\\n revert SetReserveFactorBoundsCheck();\\n }\\n\\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\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 actualAddAmount The actual amount added, excluding the potential token fees\\n */\\n function _addReservesFresh(uint256 addAmount) internal returns (uint256) {\\n // totalReserves + actualAddAmount\\n uint256 totalReservesNew;\\n uint256 actualAddAmount;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert AddReservesFactorFreshCheck(actualAddAmount);\\n }\\n\\n actualAddAmount = _doTransferIn(msg.sender, addAmount);\\n totalReservesNew = totalReserves + actualAddAmount;\\n totalReserves = totalReservesNew;\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n return actualAddAmount;\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to the protocol reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n */\\n function _reduceReservesFresh(uint256 reduceAmount) internal {\\n if (reduceAmount == 0) {\\n return;\\n }\\n // totalReserves - reduceAmount\\n uint256 totalReservesNew;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert ReduceReservesFreshCheck();\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (_getCashPrior() < reduceAmount) {\\n revert ReduceReservesCashNotAvailable();\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n revert ReduceReservesCashValidation();\\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 // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, reduceAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit SpreadReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal {\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert SetInterestRateModelFreshCheck();\\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\\n /**\\n * Safe Token **\\n */\\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 returns (uint256) {\\n IERC20Upgradeable token = IERC20Upgradeable(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 * @param to Receiver of the underlying tokens\\n * @param amount Amount of underlying to transfer\\n */\\n function _doTransferOut(address to, uint256 amount) internal virtual {\\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\\n internalCash -= amount;\\n token.safeTransfer(to, amount);\\n }\\n\\n /**\\n * @notice Transfer `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 */\\n function _transferTokens(address spender, address src, address dst, uint256 tokens) internal {\\n /* Fail if transfer not allowed */\\n comptroller.preTransferHook(address(this), src, dst, tokens);\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n revert TransferNotAllowed();\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint256 startingAllowance;\\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 uint256 allowanceNew = startingAllowance - tokens;\\n uint256 srcTokensNew = accountTokens[src] - tokens;\\n uint256 dstTokensNew = accountTokens[dst] + tokens;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n\\n accountTokens[src] = srcTokensNew;\\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\\n /**\\n * @notice Initialize the 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_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n */\\n function _initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\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 _setComptroller(comptroller_);\\n\\n // Initialize slot(block or second) number and borrow index (slot(block or second) number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumberOrTimestamp();\\n borrowIndex = MANTISSA_ONE;\\n\\n // Set the interest rate model (depends on slot(block or second) number / borrow index)\\n _setInterestRateModelFresh(interestRateModel_);\\n\\n _setReserveFactorFresh(reserveFactorMantissa_);\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n _setShortfallContract(riskManagement.shortfall);\\n _setProtocolShareReserve(riskManagement.protocolShareReserve);\\n protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA;\\n\\n // Set underlying and sanity check it\\n underlying = underlying_;\\n IERC20Upgradeable(underlying).totalSupply();\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n _transferOwnership(admin_);\\n }\\n\\n function _setShortfallContract(address shortfall_) internal {\\n ensureNonzeroAddress(shortfall_);\\n address oldShortfall = shortfall;\\n shortfall = shortfall_;\\n emit NewShortfallContract(oldShortfall, shortfall_);\\n }\\n\\n function _setProtocolShareReserve(address payable protocolShareReserve_) internal {\\n ensureNonzeroAddress(protocolShareReserve_);\\n address oldProtocolShareReserve = address(protocolShareReserve);\\n protocolShareReserve = protocolShareReserve_;\\n emit NewProtocolShareReserve(oldProtocolShareReserve, address(protocolShareReserve_));\\n }\\n\\n function _ensureSenderIsDelegateOf(address user) internal view {\\n if (!ComptrollerViewInterface(address(comptroller)).approvedDelegates(user, msg.sender)) {\\n revert DelegateNotApproved();\\n }\\n }\\n\\n /**\\n * @notice Gets the internally tracked cash balance of this market\\n * @dev Returns the internalCash state variable, which is updated on transfers in/out\\n * @return The quantity of underlying tokens tracked internally by this contract\\n */\\n function _getCashPrior() internal view virtual returns (uint256) {\\n return internalCash;\\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 borrowBalance the calculated balance\\n */\\n function _borrowBalanceStored(address account) internal view returns (uint256) {\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot memory 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 0;\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;\\n\\n return principalTimesIndex / borrowSnapshot.interestIndex;\\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 exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function _exchangeRateStored() internal view virtual returns (uint256) {\\n uint256 _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return initialExchangeRateMantissa;\\n }\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply\\n */\\n uint256 totalCash = _getCashPrior();\\n uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;\\n uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply;\\n\\n return exchangeRate;\\n }\\n}\\n\",\"keccak256\":\"0x7267f5337062ad01a5011f7725a86cc2ad0351cca0aaceadc167341f168cdef2\",\"license\":\"BSD-3-Clause\"},\"contracts/VTokenInterfaces.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\\nimport { ComptrollerInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title VTokenStorage\\n * @author Venus\\n * @notice Storage layout used by the `VToken` contract\\n */\\n// solhint-disable-next-line max-states-count\\ncontract VTokenStorage {\\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 uint256 principal;\\n uint256 interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\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 Protocol share Reserve contract address\\n */\\n address payable public protocolShareReserve;\\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 InterestRateModel public interestRateModel;\\n\\n // Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n uint256 internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint256 public reserveFactorMantissa;\\n\\n /**\\n * @notice Slot(block or second) number that interest was last accrued at\\n */\\n uint256 public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint256 public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint256 public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint256 public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint256 public totalSupply;\\n\\n /**\\n * @notice Total bad debt of the market\\n */\\n uint256 public badDebt;\\n\\n // Official record of token balances for each account\\n mapping(address => uint256) internal accountTokens;\\n\\n // Approved token transfer amounts on behalf of others\\n mapping(address => mapping(address => uint256)) internal transferAllowances;\\n\\n // Mapping of account addresses to outstanding borrow balances\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint256 public protocolSeizeShareMantissa;\\n\\n /**\\n * @notice Storage of Shortfall contract address\\n */\\n address public shortfall;\\n\\n /**\\n * @notice delta slot (block or second) after which reserves will be reduced\\n */\\n uint256 public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last slot (block or second) number at which reserves were reduced\\n */\\n uint256 public reduceReservesBlockNumber;\\n\\n /**\\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\\n * @dev Updated via _doTransferIn(), _doTransferOut(), syncCash(), and badDebtRecovered(). Must be initialized via syncCash() 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[47] private __gap;\\n}\\n\\n/**\\n * @title VTokenInterface\\n * @author Venus\\n * @notice Interface implemented by the `VToken` contract\\n */\\nabstract contract VTokenInterface is VTokenStorage {\\n struct RiskManagementInit {\\n address shortfall;\\n address payable protocolShareReserve;\\n }\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address indexed minter, uint256 mintAmount, uint256 mintTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address indexed borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(\\n address indexed payer,\\n address indexed borrower,\\n uint256 repayAmount,\\n uint256 accountBorrows,\\n uint256 totalBorrows\\n );\\n\\n /**\\n * @notice Event emitted when bad debt is accumulated on a market\\n * @param borrower borrower to \\\"forgive\\\"\\n * @param badDebtDelta amount of new bad debt recorded\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtIncreased(address indexed borrower, uint256 badDebtDelta, uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when bad debt is recovered via an auction\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtRecovered(uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address indexed liquidator,\\n address indexed borrower,\\n uint256 repayAmount,\\n address indexed vTokenCollateral,\\n uint256 seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface indexed oldComptroller, ComptrollerInterface indexed newComptroller);\\n\\n /**\\n * @notice Event emitted when shortfall contract address is changed\\n */\\n event NewShortfallContract(address indexed oldShortfall, address indexed newShortfall);\\n\\n /**\\n * @notice Event emitted when protocol share reserve contract address is changed\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModel indexed oldInterestRateModel,\\n InterestRateModel indexed newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when protocol seize share is changed\\n */\\n event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address indexed benefactor, uint256 addAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the spread reserves are reduced\\n */\\n event SpreadReservesReduced(address indexed protocolShareReserve, uint256 reduceAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /**\\n * @notice Event emitted when healing the borrow\\n */\\n event HealBorrow(address indexed payer, address indexed borrower, uint256 repayAmount);\\n\\n /**\\n * @notice Event emitted when tokens are swept\\n */\\n event SweepToken(address indexed token);\\n\\n /**\\n * @notice Event emitted when reduce reserves slot (block or second) delta is changed\\n */\\n event NewReduceReservesBlockDelta(\\n uint256 oldReduceReservesBlockOrTimestampDelta,\\n uint256 newReduceReservesBlockOrTimestampDelta\\n );\\n\\n /**\\n * @notice Event emitted when liquidation reserves are reduced\\n */\\n event ProtocolSeize(address indexed from, address indexed to, uint256 amount);\\n\\n /**\\n * @notice Event emitted when internalCash is synced with actual token balance\\n */\\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\\n\\n /*** User Interface ***/\\n\\n function mint(uint256 mintAmount) external virtual returns (uint256);\\n\\n function mintBehalf(address minter, uint256 mintAllowed) external virtual returns (uint256);\\n\\n function redeem(uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemBehalf(address redeemer, uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);\\n\\n function redeemUnderlyingBehalf(address redeemer, uint256 redeemAmount) external virtual returns (uint256);\\n\\n function borrow(uint256 borrowAmount) external virtual returns (uint256);\\n\\n function borrowBehalf(address borrwwer, uint256 borrowAmount) external virtual returns (uint256);\\n\\n function repayBorrow(uint256 repayAmount) external virtual returns (uint256);\\n\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external virtual returns (uint256);\\n\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external virtual;\\n\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipCloseFactorCheck\\n ) external virtual;\\n\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external virtual;\\n\\n function transfer(address dst, uint256 amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint256 amount) external virtual returns (bool);\\n\\n function accrueInterest() external virtual returns (uint256);\\n\\n function sweepToken(IERC20Upgradeable token) external virtual;\\n\\n /*** Admin Functions ***/\\n\\n function setReserveFactor(uint256 newReserveFactorMantissa) external virtual;\\n\\n function reduceReserves(uint256 reduceAmount) external virtual;\\n\\n function exchangeRateCurrent() external virtual returns (uint256);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint256);\\n\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external virtual;\\n\\n function addReserves(uint256 addAmount) external virtual;\\n\\n function syncCash() external virtual;\\n\\n function totalBorrowsCurrent() external virtual returns (uint256);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint256);\\n\\n function approve(address spender, uint256 amount) external virtual returns (bool);\\n\\n function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool);\\n\\n function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint256);\\n\\n function balanceOf(address owner) external view virtual returns (uint256);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint256, uint256, uint256, uint256);\\n\\n function borrowRatePerBlock() external view virtual returns (uint256);\\n\\n function supplyRatePerBlock() external view virtual returns (uint256);\\n\\n function borrowBalanceStored(address account) external view virtual returns (uint256);\\n\\n function exchangeRateStored() external view virtual returns (uint256);\\n\\n function getCash() external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is a VToken contract (for inspection)\\n * @return Always true\\n */\\n function isVToken() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x155684e9cb12cdd8be63d2314c9452b68ee44ff98a00e0d65cd1fd7d0bdd4391\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\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\",\"keccak256\":\"0x54ab3a6f3bc87569ed12370f3470a1ec84cea9796d4d0ccf3d07dd4280c044aa\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/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 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\",\"keccak256\":\"0x93bdd5cfb100f0f9a1d446857e23c3633df6ab12c266333c978428edd96b1367\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x61010060405234801561001157600080fd5b50604051614176380380614176833981016040819052610030916100e9565b82828115801561003e575080155b1561005c576040516302723dfb60e21b815260040160405180910390fd5b81801561006857508015155b156100865760405163ae0fcab360e01b815260040160405180910390fd5b81151560a05281610097578061009d565b6301e133805b608052816100b4576100e160201b611d0c176100bf565b6100e560201b611d10175b6001600160401b031660c05250506001600160a01b031660e0525061013d9050565b4390565b4290565b6000806000606084860312156100fe57600080fd5b8351801515811461010e57600080fd5b6020850151604086015191945092506001600160a01b038116811461013257600080fd5b809150509250925092565b60805160a05160c05160e051613ff2610184600039600081816102e80152611d8201526000611ce00152600081816102b10152611f80015260006101dc0152613ff26000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c80637c51b642116100a2578063c7ad089511610071578063c7ad0895146102ac578063d26998e9146102e3578063d77ebf961461030a578063e0a67f111461032a578063e1d146fb1461034a57600080fd5b80637c51b6421461022c5780637c84e3b31461024c578063aa5dbd231461026c578063b31242391461028c57600080fd5b806347d86a81116100de57806347d86a811461019957806355dd9515146101ac5780636857249c146101d75780637a27db571461020c57600080fd5b80630d3ae318146101105780631f884fdf14610139578063345954dc146101595780633e3e399c14610179575b600080fd5b61012361011e366004612ff0565b610352565b604051610130919061335d565b60405180910390f35b61014c6101473660046133bb565b610626565b60405161013091906133fc565b61016c61016736600461345c565b6106ee565b6040516101309190613479565b61018c61018736600461345c565b610821565b60405161013091906134dd565b6101236101a7366004613567565b610b30565b6101bf6101ba3660046135a0565b610bb7565b6040516001600160a01b039091168152602001610130565b6101fe7f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610130565b61021f61021a366004613567565b610c37565b60405161013091906135eb565b61023f61023a3660046136c7565b610ee7565b6040516101309190613752565b61025f61025a36600461345c565b610fa0565b60405161013091906137a0565b61027f61027a36600461345c565b61110a565b60405161013091906137c0565b61029f61029a366004613567565b6118ca565b60405161013091906137cf565b6102d37f000000000000000000000000000000000000000000000000000000000000000081565b6040519015158152602001610130565b6101bf7f000000000000000000000000000000000000000000000000000000000000000081565b61031d610318366004613567565b611bb1565b60405161013091906137dd565b61033d610338366004613841565b611c24565b60405161013091906138da565b6101fe611cd9565b61035a612db7565b6040820151600061036a82611d14565b9050600061037782611c24565b60408681015190516328ebbe8b60e21b81526001600160a01b039182166004820152919250879160009183169063a3aefa2c90602401600060405180830381865afa1580156103ca573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526103f29190810190613962565b90506000876040015190506000604051806101a001604052808a6000015181526020018a602001516001600160a01b031681526020018a604001516001600160a01b031681526020018a6060015181526020018a608001518152602001846000015181526020018460200151815260200184604001518152602001836001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104cf9190613a16565b6001600160a01b03168152602001836001600160a01b031663e87554466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561051b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053f9190613a33565b8152602001836001600160a01b0316634ada90af6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610582573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105a69190613a33565b8152602001836001600160a01b031663db5c65de6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060d9190613a33565b8152602001959095525092955050505050505b92915050565b6060816000816001600160401b0381111561064357610643612f39565b60405190808252806020026020018201604052801561068857816020015b60408051808201909152600080825260208201528152602001906001900390816106615790505b50905060005b828110156106e5576106c08686838181106106ab576106ab613a4c565b905060200201602081019061025a919061345c565b8282815181106106d2576106d2613a4c565b602090810291909101015260010161068e565b50949350505050565b606060008290506000816001600160a01b031663d88ff1f46040518163ffffffff1660e01b8152600401600060405180830381865afa158015610735573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261075d9190810190613ae5565b80519091506000816001600160401b0381111561077c5761077c612f39565b6040519080825280602002602001820160405280156107b557816020015b6107a2612db7565b81526020019060019003908161079a5790505b50905060005b828110156108175760008482815181106107d7576107d7613a4c565b6020026020010151905060006107ed8983610352565b90508084848151811061080257610802613a4c565b602090810291909101015250506001016107bb565b5095945050505050565b60408051606080820183526000808352602083018190529282015290828161084882611d14565b90506000826001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561088a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ae9190613a16565b9050600082516001600160401b038111156108cb576108cb612f39565b60405190808252806020026020018201604052801561091057816020015b60408051808201909152600080825260208201528152602001906001900390816108e95790505b509050610940604051806060016040528060006001600160a01b0316815260200160008152602001606081525090565b6001600160a01b03881681526040810182905260005b8451811015610b1c57604080518082019091526000808252602082015285828151811061098557610985613a4c565b602002602001015181600001906001600160a01b031690816001600160a01b031681525050670de0b6b3a7640000856001600160a01b031663fc57d4df8885815181106109d4576109d4613a4c565b60200260200101516040518263ffffffff1660e01b8152600401610a0791906001600160a01b0391909116815260200190565b602060405180830381865afa158015610a24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a489190613a33565b878481518110610a5a57610a5a613a4c565b60200260200101516001600160a01b031663bbcac5576040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac39190613a33565b610acd9190613bab565b610ad79190613bc2565b60208201526040830151805182919084908110610af657610af6613a4c565b6020026020010181905250806020015188610b119190613be4565b975050600101610956565b506020810195909552509295945050505050565b610b38612db7565b604051637aee632d60e01b81526001600160a01b0383811660048301528491610baf91839190821690637aee632d90602401600060405180830381865afa158015610b87573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261011e9190810190613bf7565b949350505050565b60405163266e0a7f60e01b81526001600160a01b0383811660048301528281166024830152600091859182169063266e0a7f90604401602060405180830381865afa158015610c0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2e9190613a16565b95945050505050565b60606000610c4483611d14565b90506000836001600160a01b03166361252fd16040518163ffffffff1660e01b8152600401600060405180830381865afa158015610c86573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cae9190810190613c2b565b9050600081516001600160401b03811115610ccb57610ccb612f39565b604051908082528060200260200182016040528015610d1c57816020015b6040805160808101825260008082526020808301829052928201526060808201528252600019909201910181610ce95790505b50905060005b8251811015610817576040805160808101825260008082526020820181905291810191909152606080820152838281518110610d6057610d60613a4c565b60209081029190910101516001600160a01b031681528351849083908110610d8a57610d8a613a4c565b60200260200101516001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dcf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df39190613a16565b6001600160a01b031660208201528351849083908110610e1557610e15613a4c565b6020908102919091010151604051631627ee8960e01b81526001600160a01b038a8116600483015290911690631627ee8990602401602060405180830381865afa158015610e67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8b9190613a33565b816040018181525050610eb88886868581518110610eab57610eab613a4c565b6020026020010151611eb3565b816060018190525080838381518110610ed357610ed3613a4c565b602090810291909101015250600101610d22565b6060826000816001600160401b03811115610f0457610f04612f39565b604051908082528060200260200182016040528015610f3d57816020015b610f2a612e3a565b815260200190600190039081610f225790505b50905060005b8281101561081757610f7b878783818110610f6057610f60613a4c565b9050602002016020810190610f75919061345c565b866118ca565b828281518110610f8d57610f8d613a4c565b6020908102919091010152600101610f43565b60408051808201909152600080825260208201526000826001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ff4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110189190613a16565b90506000816001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561105a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061107e9190613a16565b6040805180820182526001600160a01b03808816808352925163fc57d4df60e01b815260048101939093529293509160208301919084169063fc57d4df90602401602060405180830381865afa1580156110dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111009190613a33565b9052949350505050565b611112612e79565b6000826001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611152573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111769190613a33565b90506000836001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111dc9190613a16565b604051638e8f294b60e01b81526001600160a01b03868116600483015291925082916000918291841690638e8f294b906024016040805180830381865afa15801561122b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061124f9190613cc9565b915091506000876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611293573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b79190613a16565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061131d9190613cf5565b60ff1690506000805b600860ff8216116113e3576000886001600160a01b031663e85a29608d8460ff16600881111561135857611358613d18565b6040518363ffffffff1660e01b8152600401611375929190613d2e565b602060405180830381865afa158015611392573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b69190613d69565b6113c15760006113c4565b60015b60ff9081169083161b9290921791506113dc81613d84565b9050611326565b506000808b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611425573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114499190613a33565b11156114b4578a6001600160a01b031663ae9d70b06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561148d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114b19190613a33565b90505b6040518061022001604052808c6001600160a01b031681526020018a81526020018281526020018c6001600160a01b031663f8f9da286040518163ffffffff1660e01b8152600401602060405180830381865afa158015611519573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153d9190613a33565b81526020018c6001600160a01b031663173b99046040518163ffffffff1660e01b8152600401602060405180830381865afa158015611580573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a49190613a33565b81526040516302c3bcbb60e01b81526001600160a01b038e811660048301526020909201918a16906302c3bcbb90602401602060405180830381865afa1580156115f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116169190613a33565b815260405163252c221960e11b81526001600160a01b038e811660048301526020909201918a1690634a58443290602401602060405180830381865afa158015611664573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116889190613a33565b81526020018c6001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ef9190613a33565b81526020018c6001600160a01b0316638f840ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611732573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117569190613a33565b81526020018c6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611799573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117bd9190613a33565b81526020018c6001600160a01b0316633b1d21a26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611800573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118249190613a33565b81526020018715158152602001868152602001856001600160a01b031681526020018c6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611884573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118a89190613cf5565b60ff168152602001848152602001838152509950505050505050505050919050565b6118d2612e3a565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908516906370a0823190602401602060405180830381865afa15801561191c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119409190613a33565b6040516305eff7ef60e21b81526001600160a01b0385811660048301529192506000918616906317bfdfbc906024016020604051808303816000875af115801561198e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b29190613a33565b604051633af9e66960e01b81526001600160a01b038681166004830152919250600091871690633af9e669906024016020604051808303816000875af1158015611a00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a249190613a33565b90506000806000886001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a8d9190613a16565b6040516370a0823160e01b81526001600160a01b038a81166004830152919250908216906370a0823190602401602060405180830381865afa158015611ad7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611afb9190613a33565b604051636eb1769f60e11b81526001600160a01b038a811660048301528b811660248301529194509082169063dd62ed3e90604401602060405180830381865afa158015611b4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b719190613a33565b6040805160c0810182526001600160a01b038c168152602081019890985287019590955250506060840191909152608083015260a0820152905092915050565b604051631e6db74760e31b81526001600160a01b038281166004830152606091849182169063f36dba3890602401600060405180830381865afa158015611bfc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610baf9190810190613da3565b80516060906000816001600160401b03811115611c4357611c43612f39565b604051908082528060200260200182016040528015611c7c57816020015b611c69612e79565b815260200190600190039081611c615790505b50905060005b82811015611cd157611cac858281518110611c9f57611c9f613a4c565b602002602001015161110a565b828281518110611cbe57611cbe613a4c565b6020908102919091010152600101611c82565b509392505050565b6000611d077f000000000000000000000000000000000000000000000000000000000000000063ffffffff16565b905090565b4390565b4290565b60606000826001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015611d56573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d7e9190810190613e31565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031603611dbf5792915050565b8051600090815b81811015611ea9576000848281518110611de257611de2613a4c565b60200260200101516001600160a01b03166322abdbf56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e4b9190613a33565b1115611ea157838181518110611e6357611e63613a4c565b6020026020010151848481518110611e7d57611e7d613a4c565b6001600160a01b0390921660209283029190910190910152611e9e83613ebf565b92505b600101611dc6565b5050815292915050565b6060600083516001600160401b03811115611ed057611ed0612f39565b604051908082528060200260200182016040528015611f1557816020015b6040805180820190915260008082526020820152815260200190600190039081611eee5790505b50905060005b84518110156106e557611f51604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b611f7e604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b7f00000000000000000000000000000000000000000000000000000000000000001561210157856001600160a01b0316638f693ec7888581518110611fc557611fc5613a4c565b60200260200101516040518263ffffffff1660e01b8152600401611ff891906001600160a01b0391909116815260200190565b606060405180830381865afa158015612015573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120399190613eef565b604085015260208401526001600160e01b0316825286516001600160a01b0387169063818149459089908690811061207357612073613a4c565b60200260200101516040518263ffffffff1660e01b81526004016120a691906001600160a01b0391909116815260200190565b606060405180830381865afa1580156120c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e79190613eef565b604084015260208301526001600160e01b0316815261226c565b856001600160a01b0316632c427b5788858151811061212257612122613a4c565b60200260200101516040518263ffffffff1660e01b815260040161215591906001600160a01b0391909116815260200190565b606060405180830381865afa158015612172573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121969190613f38565b63ffffffff90811660408601521660208401526001600160e01b0316825286516001600160a01b038716906392a18235908990869081106121d9576121d9613a4c565b60200260200101516040518263ffffffff1660e01b815260040161220c91906001600160a01b0391909116815260200190565b606060405180830381865afa158015612229573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061224d9190613f38565b63ffffffff90811660408501521660208301526001600160e01b031681525b6000604051806020016040528089868151811061228b5761228b613a4c565b60200260200101516001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122f49190613a33565b815250905061231e88858151811061230e5761230e613a4c565b6020026020010151888584612413565b61234288858151811061233357612333613a4c565b60200260200101518884612614565b600061236a89868151811061235957612359613a4c565b6020026020010151898c878661280b565b905060006123938a878151811061238357612383613a4c565b60200260200101518a8d87612a3b565b60408051808201909152600080825260208201529091508a87815181106123bc576123bc613a4c565b60209081029190910101516001600160a01b031681526123dc8284613be4565b6020820152875181908990899081106123f7576123f7613a4c565b6020026020010181905250505050505050806001019050611f1b565b604051637c05a7c560e01b81526001600160a01b03858116600483015260009190851690637c05a7c590602401602060405180830381865afa15801561245d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124819190613a33565b9050600061248d611cd9565b9050600084604001511180156124a65750836040015181115b156124b2575060408301515b60006124c2828660200151612c5f565b90506000811180156124d45750600083115b156125fd576000612546886001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561251c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125409190613a33565b86612c72565b905060006125548386612c90565b90506000808311612574576040518060200160405280600081525061257e565b61257e8284612c9c565b905060006125a760405180602001604052808b600001516001600160e01b031681525083612ce1565b90506125e28160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612d0d565b6001600160e01b03168952505050506020850182905261260b565b801561260b57602085018290525b50505050505050565b604051631d31307360e21b81526001600160a01b038481166004830152600091908416906374c4c1cc90602401602060405180830381865afa15801561265e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126829190613a33565b9050600061268e611cd9565b9050600083604001511180156126a75750826040015181115b156126b3575060408201515b60006126c3828560200151612c5f565b90506000811180156126d55750600083115b156127f5576000866001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561271a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061273e9190613a33565b9050600061274c8386612c90565b9050600080831161276c5760405180602001604052806000815250612776565b6127768284612c9c565b9050600061279f60405180602001604052808a600001516001600160e01b031681525083612ce1565b90506127da8160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612d0d565b6001600160e01b031688525050505060208401829052612803565b801561280357602084018290525b505050505050565b604080516020808201835284516001600160e01b031682528251908101928390526336fe846560e11b9092526001600160a01b0387811660248401528581166044840152600092839181908916636dfd08ca60648301602060405180830381865afa15801561287e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a29190613a33565b905280519091501580156129245750866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129139190613f7b565b6001600160e01b0316826000015110155b1561299757866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061298b9190613f7b565b6001600160e01b031681525b60006129a38383612d49565b6040516395dd919360e01b81526001600160a01b038981166004830152919250600091612a1e91908c16906395dd919390602401602060405180830381865afa1580156129f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a189190613a33565b87612c72565b90506000612a2c8284612d75565b9b9a5050505050505050505050565b604080516020808201835283516001600160e01b0316825282519081019283905263552c097160e01b9092526001600160a01b038681166024840152848116604484015260009283918190881663552c097160648301602060405180830381865afa158015612aae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ad29190613a33565b90528051909150158015612b545750856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b439190613f7b565b6001600160e01b0316826000015110155b15612bc757856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bbb9190613f7b565b6001600160e01b031681525b6000612bd38383612d49565b6040516370a0823160e01b81526001600160a01b0388811660048301529192506000918a16906370a0823190602401602060405180830381865afa158015612c1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c439190613a33565b90506000612c518284612d75565b9a9950505050505050505050565b6000612c6b8284613f96565b9392505050565b6000612c6b612c8984670de0b6b3a7640000612c90565b8351612d9f565b6000612c6b8284613bab565b6040805160208101909152600081526040518060200160405280612cd8612cd2866ec097ce7bc90715b34b9f1000000000612c90565b85612d9f565b90529392505050565b6040805160208101909152600081526040518060200160405280612cd885600001518560000151612dab565b6000816001600160e01b03841115612d415760405162461bcd60e51b8152600401612d389190613fa9565b60405180910390fd5b509192915050565b6040805160208101909152600081526040518060200160405280612cd885600001518560000151612c5f565b60006ec097ce7bc90715b34b9f1000000000612d95848460000151612c90565b612c6b9190613bc2565b6000612c6b8284613bc2565b6000612c6b8284613be4565b604051806101a001604052806060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160608152602001606081526020016060815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001606081525090565b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180610220016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b6001600160a01b0381168114612f2657600080fd5b50565b8035612f3481612f11565b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715612f7157612f71612f39565b60405290565b604051606081016001600160401b0381118282101715612f7157612f71612f39565b604051601f8201601f191681016001600160401b0381118282101715612fc157612fc1612f39565b604052919050565b60006001600160401b03821115612fe257612fe2612f39565b50601f01601f191660200190565b6000806040838503121561300357600080fd5b823561300e81612f11565b91506020838101356001600160401b038082111561302b57600080fd5b9085019060a0828803121561303f57600080fd5b613047612f4f565b82358281111561305657600080fd5b83019150601f8201881361306957600080fd5b813561307c61307782612fc9565b612f99565b818152898683860101111561309057600080fd5b8186850187830137600086838301015280835250506130b0848401612f29565b848201526130c060408401612f29565b60408201526060830135606082015260808301356080820152809450505050509250929050565b60005b838110156131025781810151838201526020016130ea565b50506000910152565b600081518084526131238160208601602086016130e7565b601f01601f19169290920160200192915050565b80516001600160a01b031682526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e0830152610100808201518184015250610120808201518184015250610140808201518184015250610160808201516131c28285018215159052565b505061018081810151908301526101a0808201516001600160a01b0316908301526101c080820151908301526101e0808201519083015261020090810151910152565b60008151808452602080850194506020840160005b838110156132415761322d878351613137565b61022096909601959082019060010161321a565b509495945050505050565b60006101a082518185526132628286018261310b565b915050602083015161327f60208601826001600160a01b03169052565b50604083015161329a60408601826001600160a01b03169052565b50606083015160608501526080830151608085015260a083015184820360a08601526132c6828261310b565b91505060c083015184820360c08601526132e0828261310b565b91505060e083015184820360e08601526132fa828261310b565b91505061010080840151613318828701826001600160a01b03169052565b505061012083810151908501526101408084015190850152610160808401519085015261018080840151858303828701526133538382613205565b9695505050505050565b602081526000612c6b602083018461324c565b60008083601f84011261338257600080fd5b5081356001600160401b0381111561339957600080fd5b6020830191508360208260051b85010111156133b457600080fd5b9250929050565b600080602083850312156133ce57600080fd5b82356001600160401b038111156133e457600080fd5b6133f085828601613370565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b8281101561344f5761343f84835180516001600160a01b03168252602090810151910152565b9284019290850190600101613419565b5091979650505050505050565b60006020828403121561346e57600080fd5b8135612c6b81612f11565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156134d057603f198886030184526134be85835161324c565b945092850192908501906001016134a2565b5092979650505050505050565b602080825282516001600160a01b03168282015282810151604080840191909152808401516060808501528051608085018190526000939291830191849160a08701905b8084101561355b5761354782865180516001600160a01b03168252602090810151910152565b938501936001939093019290820190613521565b50979650505050505050565b6000806040838503121561357a57600080fd5b823561358581612f11565b9150602083013561359581612f11565b809150509250929050565b6000806000606084860312156135b557600080fd5b83356135c081612f11565b925060208401356135d081612f11565b915060408401356135e081612f11565b809150509250925092565b600060208083018184528085518083526040925060408601915060408160051b8701018488016000805b848110156136b857898403603f19018652825180516001600160a01b03908116865289820151168986015287810151888601526060908101516080918601829052805191860182905289019060a086019084905b808210156136a35761368f83855180516001600160a01b03168252602090810151910152565b928b0192918a019160019190910190613669565b50509689019694505091870191600101613615565b50919998505050505050505050565b6000806000604084860312156136dc57600080fd5b83356001600160401b038111156136f257600080fd5b6136fe86828701613370565b90945092505060208401356135e081612f11565b80516001600160a01b031682526020808201519083015260408082015190830152606080820151908301526080808201519083015260a090810151910152565b6020808252825182820181905260009190848201906040850190845b8181101561379457613781838551613712565b9284019260c0929092019160010161376e565b50909695505050505050565b81516001600160a01b031681526020808301519082015260408101610620565b61022081016106208284613137565b60c081016106208284613712565b6020808252825182820181905260009190848201906040850190845b818110156137945783516001600160a01b0316835292840192918401916001016137f9565b60006001600160401b0382111561383757613837612f39565b5060051b60200190565b6000602080838503121561385457600080fd5b82356001600160401b0381111561386a57600080fd5b8301601f8101851361387b57600080fd5b80356138896130778261381e565b81815260059190911b820183019083810190878311156138a857600080fd5b928401925b828410156138cf5783356138c081612f11565b825292840192908401906138ad565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561379457613909838551613137565b9284019261022092909201916001016138f6565b600082601f83011261392e57600080fd5b815161393c61307782612fc9565b81815284602083860101111561395157600080fd5b610baf8260208301602087016130e7565b60006020828403121561397457600080fd5b81516001600160401b038082111561398b57600080fd5b908301906060828603121561399f57600080fd5b6139a7612f77565b8251828111156139b657600080fd5b6139c28782860161391d565b8252506020830151828111156139d757600080fd5b6139e38782860161391d565b6020830152506040830151828111156139fb57600080fd5b613a078782860161391d565b60408301525095945050505050565b600060208284031215613a2857600080fd5b8151612c6b81612f11565b600060208284031215613a4557600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600060a08284031215613a7457600080fd5b613a7c612f4f565b905081516001600160401b03811115613a9457600080fd5b613aa08482850161391d565b8252506020820151613ab181612f11565b60208201526040820151613ac481612f11565b80604083015250606082015160608201526080820151608082015292915050565b60006020808385031215613af857600080fd5b82516001600160401b0380821115613b0f57600080fd5b818501915085601f830112613b2357600080fd5b8151613b316130778261381e565b81815260059190911b83018401908481019088831115613b5057600080fd5b8585015b83811015613b8857805185811115613b6c5760008081fd5b613b7a8b89838a0101613a62565b845250918601918601613b54565b5098975050505050505050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761062057610620613b95565b600082613bdf57634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561062057610620613b95565b600060208284031215613c0957600080fd5b81516001600160401b03811115613c1f57600080fd5b610baf84828501613a62565b60006020808385031215613c3e57600080fd5b82516001600160401b03811115613c5457600080fd5b8301601f81018513613c6557600080fd5b8051613c736130778261381e565b81815260059190911b82018301908381019087831115613c9257600080fd5b928401925b828410156138cf578351613caa81612f11565b82529284019290840190613c97565b80518015158114612f3457600080fd5b60008060408385031215613cdc57600080fd5b613ce583613cb9565b9150602083015190509250929050565b600060208284031215613d0757600080fd5b815160ff81168114612c6b57600080fd5b634e487b7160e01b600052602160045260246000fd5b6001600160a01b03831681526040810160098310613d5c57634e487b7160e01b600052602160045260246000fd5b8260208301529392505050565b600060208284031215613d7b57600080fd5b612c6b82613cb9565b600060ff821660ff8103613d9a57613d9a613b95565b60010192915050565b60006020808385031215613db657600080fd5b82516001600160401b03811115613dcc57600080fd5b8301601f81018513613ddd57600080fd5b8051613deb6130778261381e565b81815260059190911b82018301908381019087831115613e0a57600080fd5b928401925b828410156138cf578351613e2281612f11565b82529284019290840190613e0f565b60006020808385031215613e4457600080fd5b82516001600160401b03811115613e5a57600080fd5b8301601f81018513613e6b57600080fd5b8051613e796130778261381e565b81815260059190911b82018301908381019087831115613e9857600080fd5b928401925b828410156138cf578351613eb081612f11565b82529284019290840190613e9d565b600060018201613ed157613ed1613b95565b5060010190565b80516001600160e01b0381168114612f3457600080fd5b600080600060608486031215613f0457600080fd5b613f0d84613ed8565b925060208401519150604084015190509250925092565b805163ffffffff81168114612f3457600080fd5b600080600060608486031215613f4d57600080fd5b613f5684613ed8565b9250613f6460208501613f24565b9150613f7260408501613f24565b90509250925092565b600060208284031215613f8d57600080fd5b612c6b82613ed8565b8181038181111561062057610620613b95565b602081526000612c6b602083018461310b56fea264697066735822122096dca9ef030f65331631c7305d4d9405c1d0b56d48eb3787508d19369d85297764736f6c63430008190033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061010b5760003560e01c80637c51b642116100a2578063c7ad089511610071578063c7ad0895146102ac578063d26998e9146102e3578063d77ebf961461030a578063e0a67f111461032a578063e1d146fb1461034a57600080fd5b80637c51b6421461022c5780637c84e3b31461024c578063aa5dbd231461026c578063b31242391461028c57600080fd5b806347d86a81116100de57806347d86a811461019957806355dd9515146101ac5780636857249c146101d75780637a27db571461020c57600080fd5b80630d3ae318146101105780631f884fdf14610139578063345954dc146101595780633e3e399c14610179575b600080fd5b61012361011e366004612ff0565b610352565b604051610130919061335d565b60405180910390f35b61014c6101473660046133bb565b610626565b60405161013091906133fc565b61016c61016736600461345c565b6106ee565b6040516101309190613479565b61018c61018736600461345c565b610821565b60405161013091906134dd565b6101236101a7366004613567565b610b30565b6101bf6101ba3660046135a0565b610bb7565b6040516001600160a01b039091168152602001610130565b6101fe7f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610130565b61021f61021a366004613567565b610c37565b60405161013091906135eb565b61023f61023a3660046136c7565b610ee7565b6040516101309190613752565b61025f61025a36600461345c565b610fa0565b60405161013091906137a0565b61027f61027a36600461345c565b61110a565b60405161013091906137c0565b61029f61029a366004613567565b6118ca565b60405161013091906137cf565b6102d37f000000000000000000000000000000000000000000000000000000000000000081565b6040519015158152602001610130565b6101bf7f000000000000000000000000000000000000000000000000000000000000000081565b61031d610318366004613567565b611bb1565b60405161013091906137dd565b61033d610338366004613841565b611c24565b60405161013091906138da565b6101fe611cd9565b61035a612db7565b6040820151600061036a82611d14565b9050600061037782611c24565b60408681015190516328ebbe8b60e21b81526001600160a01b039182166004820152919250879160009183169063a3aefa2c90602401600060405180830381865afa1580156103ca573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526103f29190810190613962565b90506000876040015190506000604051806101a001604052808a6000015181526020018a602001516001600160a01b031681526020018a604001516001600160a01b031681526020018a6060015181526020018a608001518152602001846000015181526020018460200151815260200184604001518152602001836001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104cf9190613a16565b6001600160a01b03168152602001836001600160a01b031663e87554466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561051b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053f9190613a33565b8152602001836001600160a01b0316634ada90af6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610582573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105a69190613a33565b8152602001836001600160a01b031663db5c65de6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060d9190613a33565b8152602001959095525092955050505050505b92915050565b6060816000816001600160401b0381111561064357610643612f39565b60405190808252806020026020018201604052801561068857816020015b60408051808201909152600080825260208201528152602001906001900390816106615790505b50905060005b828110156106e5576106c08686838181106106ab576106ab613a4c565b905060200201602081019061025a919061345c565b8282815181106106d2576106d2613a4c565b602090810291909101015260010161068e565b50949350505050565b606060008290506000816001600160a01b031663d88ff1f46040518163ffffffff1660e01b8152600401600060405180830381865afa158015610735573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261075d9190810190613ae5565b80519091506000816001600160401b0381111561077c5761077c612f39565b6040519080825280602002602001820160405280156107b557816020015b6107a2612db7565b81526020019060019003908161079a5790505b50905060005b828110156108175760008482815181106107d7576107d7613a4c565b6020026020010151905060006107ed8983610352565b90508084848151811061080257610802613a4c565b602090810291909101015250506001016107bb565b5095945050505050565b60408051606080820183526000808352602083018190529282015290828161084882611d14565b90506000826001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561088a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ae9190613a16565b9050600082516001600160401b038111156108cb576108cb612f39565b60405190808252806020026020018201604052801561091057816020015b60408051808201909152600080825260208201528152602001906001900390816108e95790505b509050610940604051806060016040528060006001600160a01b0316815260200160008152602001606081525090565b6001600160a01b03881681526040810182905260005b8451811015610b1c57604080518082019091526000808252602082015285828151811061098557610985613a4c565b602002602001015181600001906001600160a01b031690816001600160a01b031681525050670de0b6b3a7640000856001600160a01b031663fc57d4df8885815181106109d4576109d4613a4c565b60200260200101516040518263ffffffff1660e01b8152600401610a0791906001600160a01b0391909116815260200190565b602060405180830381865afa158015610a24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a489190613a33565b878481518110610a5a57610a5a613a4c565b60200260200101516001600160a01b031663bbcac5576040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac39190613a33565b610acd9190613bab565b610ad79190613bc2565b60208201526040830151805182919084908110610af657610af6613a4c565b6020026020010181905250806020015188610b119190613be4565b975050600101610956565b506020810195909552509295945050505050565b610b38612db7565b604051637aee632d60e01b81526001600160a01b0383811660048301528491610baf91839190821690637aee632d90602401600060405180830381865afa158015610b87573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261011e9190810190613bf7565b949350505050565b60405163266e0a7f60e01b81526001600160a01b0383811660048301528281166024830152600091859182169063266e0a7f90604401602060405180830381865afa158015610c0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2e9190613a16565b95945050505050565b60606000610c4483611d14565b90506000836001600160a01b03166361252fd16040518163ffffffff1660e01b8152600401600060405180830381865afa158015610c86573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cae9190810190613c2b565b9050600081516001600160401b03811115610ccb57610ccb612f39565b604051908082528060200260200182016040528015610d1c57816020015b6040805160808101825260008082526020808301829052928201526060808201528252600019909201910181610ce95790505b50905060005b8251811015610817576040805160808101825260008082526020820181905291810191909152606080820152838281518110610d6057610d60613a4c565b60209081029190910101516001600160a01b031681528351849083908110610d8a57610d8a613a4c565b60200260200101516001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dcf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df39190613a16565b6001600160a01b031660208201528351849083908110610e1557610e15613a4c565b6020908102919091010151604051631627ee8960e01b81526001600160a01b038a8116600483015290911690631627ee8990602401602060405180830381865afa158015610e67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8b9190613a33565b816040018181525050610eb88886868581518110610eab57610eab613a4c565b6020026020010151611eb3565b816060018190525080838381518110610ed357610ed3613a4c565b602090810291909101015250600101610d22565b6060826000816001600160401b03811115610f0457610f04612f39565b604051908082528060200260200182016040528015610f3d57816020015b610f2a612e3a565b815260200190600190039081610f225790505b50905060005b8281101561081757610f7b878783818110610f6057610f60613a4c565b9050602002016020810190610f75919061345c565b866118ca565b828281518110610f8d57610f8d613a4c565b6020908102919091010152600101610f43565b60408051808201909152600080825260208201526000826001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ff4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110189190613a16565b90506000816001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561105a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061107e9190613a16565b6040805180820182526001600160a01b03808816808352925163fc57d4df60e01b815260048101939093529293509160208301919084169063fc57d4df90602401602060405180830381865afa1580156110dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111009190613a33565b9052949350505050565b611112612e79565b6000826001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611152573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111769190613a33565b90506000836001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111dc9190613a16565b604051638e8f294b60e01b81526001600160a01b03868116600483015291925082916000918291841690638e8f294b906024016040805180830381865afa15801561122b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061124f9190613cc9565b915091506000876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611293573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b79190613a16565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061131d9190613cf5565b60ff1690506000805b600860ff8216116113e3576000886001600160a01b031663e85a29608d8460ff16600881111561135857611358613d18565b6040518363ffffffff1660e01b8152600401611375929190613d2e565b602060405180830381865afa158015611392573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b69190613d69565b6113c15760006113c4565b60015b60ff9081169083161b9290921791506113dc81613d84565b9050611326565b506000808b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611425573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114499190613a33565b11156114b4578a6001600160a01b031663ae9d70b06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561148d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114b19190613a33565b90505b6040518061022001604052808c6001600160a01b031681526020018a81526020018281526020018c6001600160a01b031663f8f9da286040518163ffffffff1660e01b8152600401602060405180830381865afa158015611519573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153d9190613a33565b81526020018c6001600160a01b031663173b99046040518163ffffffff1660e01b8152600401602060405180830381865afa158015611580573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a49190613a33565b81526040516302c3bcbb60e01b81526001600160a01b038e811660048301526020909201918a16906302c3bcbb90602401602060405180830381865afa1580156115f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116169190613a33565b815260405163252c221960e11b81526001600160a01b038e811660048301526020909201918a1690634a58443290602401602060405180830381865afa158015611664573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116889190613a33565b81526020018c6001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ef9190613a33565b81526020018c6001600160a01b0316638f840ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611732573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117569190613a33565b81526020018c6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611799573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117bd9190613a33565b81526020018c6001600160a01b0316633b1d21a26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611800573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118249190613a33565b81526020018715158152602001868152602001856001600160a01b031681526020018c6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611884573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118a89190613cf5565b60ff168152602001848152602001838152509950505050505050505050919050565b6118d2612e3a565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908516906370a0823190602401602060405180830381865afa15801561191c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119409190613a33565b6040516305eff7ef60e21b81526001600160a01b0385811660048301529192506000918616906317bfdfbc906024016020604051808303816000875af115801561198e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b29190613a33565b604051633af9e66960e01b81526001600160a01b038681166004830152919250600091871690633af9e669906024016020604051808303816000875af1158015611a00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a249190613a33565b90506000806000886001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a8d9190613a16565b6040516370a0823160e01b81526001600160a01b038a81166004830152919250908216906370a0823190602401602060405180830381865afa158015611ad7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611afb9190613a33565b604051636eb1769f60e11b81526001600160a01b038a811660048301528b811660248301529194509082169063dd62ed3e90604401602060405180830381865afa158015611b4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b719190613a33565b6040805160c0810182526001600160a01b038c168152602081019890985287019590955250506060840191909152608083015260a0820152905092915050565b604051631e6db74760e31b81526001600160a01b038281166004830152606091849182169063f36dba3890602401600060405180830381865afa158015611bfc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610baf9190810190613da3565b80516060906000816001600160401b03811115611c4357611c43612f39565b604051908082528060200260200182016040528015611c7c57816020015b611c69612e79565b815260200190600190039081611c615790505b50905060005b82811015611cd157611cac858281518110611c9f57611c9f613a4c565b602002602001015161110a565b828281518110611cbe57611cbe613a4c565b6020908102919091010152600101611c82565b509392505050565b6000611d077f000000000000000000000000000000000000000000000000000000000000000063ffffffff16565b905090565b4390565b4290565b60606000826001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015611d56573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d7e9190810190613e31565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031603611dbf5792915050565b8051600090815b81811015611ea9576000848281518110611de257611de2613a4c565b60200260200101516001600160a01b03166322abdbf56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e4b9190613a33565b1115611ea157838181518110611e6357611e63613a4c565b6020026020010151848481518110611e7d57611e7d613a4c565b6001600160a01b0390921660209283029190910190910152611e9e83613ebf565b92505b600101611dc6565b5050815292915050565b6060600083516001600160401b03811115611ed057611ed0612f39565b604051908082528060200260200182016040528015611f1557816020015b6040805180820190915260008082526020820152815260200190600190039081611eee5790505b50905060005b84518110156106e557611f51604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b611f7e604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b7f00000000000000000000000000000000000000000000000000000000000000001561210157856001600160a01b0316638f693ec7888581518110611fc557611fc5613a4c565b60200260200101516040518263ffffffff1660e01b8152600401611ff891906001600160a01b0391909116815260200190565b606060405180830381865afa158015612015573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120399190613eef565b604085015260208401526001600160e01b0316825286516001600160a01b0387169063818149459089908690811061207357612073613a4c565b60200260200101516040518263ffffffff1660e01b81526004016120a691906001600160a01b0391909116815260200190565b606060405180830381865afa1580156120c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e79190613eef565b604084015260208301526001600160e01b0316815261226c565b856001600160a01b0316632c427b5788858151811061212257612122613a4c565b60200260200101516040518263ffffffff1660e01b815260040161215591906001600160a01b0391909116815260200190565b606060405180830381865afa158015612172573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121969190613f38565b63ffffffff90811660408601521660208401526001600160e01b0316825286516001600160a01b038716906392a18235908990869081106121d9576121d9613a4c565b60200260200101516040518263ffffffff1660e01b815260040161220c91906001600160a01b0391909116815260200190565b606060405180830381865afa158015612229573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061224d9190613f38565b63ffffffff90811660408501521660208301526001600160e01b031681525b6000604051806020016040528089868151811061228b5761228b613a4c565b60200260200101516001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122f49190613a33565b815250905061231e88858151811061230e5761230e613a4c565b6020026020010151888584612413565b61234288858151811061233357612333613a4c565b60200260200101518884612614565b600061236a89868151811061235957612359613a4c565b6020026020010151898c878661280b565b905060006123938a878151811061238357612383613a4c565b60200260200101518a8d87612a3b565b60408051808201909152600080825260208201529091508a87815181106123bc576123bc613a4c565b60209081029190910101516001600160a01b031681526123dc8284613be4565b6020820152875181908990899081106123f7576123f7613a4c565b6020026020010181905250505050505050806001019050611f1b565b604051637c05a7c560e01b81526001600160a01b03858116600483015260009190851690637c05a7c590602401602060405180830381865afa15801561245d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124819190613a33565b9050600061248d611cd9565b9050600084604001511180156124a65750836040015181115b156124b2575060408301515b60006124c2828660200151612c5f565b90506000811180156124d45750600083115b156125fd576000612546886001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561251c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125409190613a33565b86612c72565b905060006125548386612c90565b90506000808311612574576040518060200160405280600081525061257e565b61257e8284612c9c565b905060006125a760405180602001604052808b600001516001600160e01b031681525083612ce1565b90506125e28160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612d0d565b6001600160e01b03168952505050506020850182905261260b565b801561260b57602085018290525b50505050505050565b604051631d31307360e21b81526001600160a01b038481166004830152600091908416906374c4c1cc90602401602060405180830381865afa15801561265e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126829190613a33565b9050600061268e611cd9565b9050600083604001511180156126a75750826040015181115b156126b3575060408201515b60006126c3828560200151612c5f565b90506000811180156126d55750600083115b156127f5576000866001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561271a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061273e9190613a33565b9050600061274c8386612c90565b9050600080831161276c5760405180602001604052806000815250612776565b6127768284612c9c565b9050600061279f60405180602001604052808a600001516001600160e01b031681525083612ce1565b90506127da8160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612d0d565b6001600160e01b031688525050505060208401829052612803565b801561280357602084018290525b505050505050565b604080516020808201835284516001600160e01b031682528251908101928390526336fe846560e11b9092526001600160a01b0387811660248401528581166044840152600092839181908916636dfd08ca60648301602060405180830381865afa15801561287e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a29190613a33565b905280519091501580156129245750866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129139190613f7b565b6001600160e01b0316826000015110155b1561299757866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061298b9190613f7b565b6001600160e01b031681525b60006129a38383612d49565b6040516395dd919360e01b81526001600160a01b038981166004830152919250600091612a1e91908c16906395dd919390602401602060405180830381865afa1580156129f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a189190613a33565b87612c72565b90506000612a2c8284612d75565b9b9a5050505050505050505050565b604080516020808201835283516001600160e01b0316825282519081019283905263552c097160e01b9092526001600160a01b038681166024840152848116604484015260009283918190881663552c097160648301602060405180830381865afa158015612aae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ad29190613a33565b90528051909150158015612b545750856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b439190613f7b565b6001600160e01b0316826000015110155b15612bc757856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bbb9190613f7b565b6001600160e01b031681525b6000612bd38383612d49565b6040516370a0823160e01b81526001600160a01b0388811660048301529192506000918a16906370a0823190602401602060405180830381865afa158015612c1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c439190613a33565b90506000612c518284612d75565b9a9950505050505050505050565b6000612c6b8284613f96565b9392505050565b6000612c6b612c8984670de0b6b3a7640000612c90565b8351612d9f565b6000612c6b8284613bab565b6040805160208101909152600081526040518060200160405280612cd8612cd2866ec097ce7bc90715b34b9f1000000000612c90565b85612d9f565b90529392505050565b6040805160208101909152600081526040518060200160405280612cd885600001518560000151612dab565b6000816001600160e01b03841115612d415760405162461bcd60e51b8152600401612d389190613fa9565b60405180910390fd5b509192915050565b6040805160208101909152600081526040518060200160405280612cd885600001518560000151612c5f565b60006ec097ce7bc90715b34b9f1000000000612d95848460000151612c90565b612c6b9190613bc2565b6000612c6b8284613bc2565b6000612c6b8284613be4565b604051806101a001604052806060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160608152602001606081526020016060815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001606081525090565b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180610220016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b6001600160a01b0381168114612f2657600080fd5b50565b8035612f3481612f11565b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715612f7157612f71612f39565b60405290565b604051606081016001600160401b0381118282101715612f7157612f71612f39565b604051601f8201601f191681016001600160401b0381118282101715612fc157612fc1612f39565b604052919050565b60006001600160401b03821115612fe257612fe2612f39565b50601f01601f191660200190565b6000806040838503121561300357600080fd5b823561300e81612f11565b91506020838101356001600160401b038082111561302b57600080fd5b9085019060a0828803121561303f57600080fd5b613047612f4f565b82358281111561305657600080fd5b83019150601f8201881361306957600080fd5b813561307c61307782612fc9565b612f99565b818152898683860101111561309057600080fd5b8186850187830137600086838301015280835250506130b0848401612f29565b848201526130c060408401612f29565b60408201526060830135606082015260808301356080820152809450505050509250929050565b60005b838110156131025781810151838201526020016130ea565b50506000910152565b600081518084526131238160208601602086016130e7565b601f01601f19169290920160200192915050565b80516001600160a01b031682526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e0830152610100808201518184015250610120808201518184015250610140808201518184015250610160808201516131c28285018215159052565b505061018081810151908301526101a0808201516001600160a01b0316908301526101c080820151908301526101e0808201519083015261020090810151910152565b60008151808452602080850194506020840160005b838110156132415761322d878351613137565b61022096909601959082019060010161321a565b509495945050505050565b60006101a082518185526132628286018261310b565b915050602083015161327f60208601826001600160a01b03169052565b50604083015161329a60408601826001600160a01b03169052565b50606083015160608501526080830151608085015260a083015184820360a08601526132c6828261310b565b91505060c083015184820360c08601526132e0828261310b565b91505060e083015184820360e08601526132fa828261310b565b91505061010080840151613318828701826001600160a01b03169052565b505061012083810151908501526101408084015190850152610160808401519085015261018080840151858303828701526133538382613205565b9695505050505050565b602081526000612c6b602083018461324c565b60008083601f84011261338257600080fd5b5081356001600160401b0381111561339957600080fd5b6020830191508360208260051b85010111156133b457600080fd5b9250929050565b600080602083850312156133ce57600080fd5b82356001600160401b038111156133e457600080fd5b6133f085828601613370565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b8281101561344f5761343f84835180516001600160a01b03168252602090810151910152565b9284019290850190600101613419565b5091979650505050505050565b60006020828403121561346e57600080fd5b8135612c6b81612f11565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156134d057603f198886030184526134be85835161324c565b945092850192908501906001016134a2565b5092979650505050505050565b602080825282516001600160a01b03168282015282810151604080840191909152808401516060808501528051608085018190526000939291830191849160a08701905b8084101561355b5761354782865180516001600160a01b03168252602090810151910152565b938501936001939093019290820190613521565b50979650505050505050565b6000806040838503121561357a57600080fd5b823561358581612f11565b9150602083013561359581612f11565b809150509250929050565b6000806000606084860312156135b557600080fd5b83356135c081612f11565b925060208401356135d081612f11565b915060408401356135e081612f11565b809150509250925092565b600060208083018184528085518083526040925060408601915060408160051b8701018488016000805b848110156136b857898403603f19018652825180516001600160a01b03908116865289820151168986015287810151888601526060908101516080918601829052805191860182905289019060a086019084905b808210156136a35761368f83855180516001600160a01b03168252602090810151910152565b928b0192918a019160019190910190613669565b50509689019694505091870191600101613615565b50919998505050505050505050565b6000806000604084860312156136dc57600080fd5b83356001600160401b038111156136f257600080fd5b6136fe86828701613370565b90945092505060208401356135e081612f11565b80516001600160a01b031682526020808201519083015260408082015190830152606080820151908301526080808201519083015260a090810151910152565b6020808252825182820181905260009190848201906040850190845b8181101561379457613781838551613712565b9284019260c0929092019160010161376e565b50909695505050505050565b81516001600160a01b031681526020808301519082015260408101610620565b61022081016106208284613137565b60c081016106208284613712565b6020808252825182820181905260009190848201906040850190845b818110156137945783516001600160a01b0316835292840192918401916001016137f9565b60006001600160401b0382111561383757613837612f39565b5060051b60200190565b6000602080838503121561385457600080fd5b82356001600160401b0381111561386a57600080fd5b8301601f8101851361387b57600080fd5b80356138896130778261381e565b81815260059190911b820183019083810190878311156138a857600080fd5b928401925b828410156138cf5783356138c081612f11565b825292840192908401906138ad565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561379457613909838551613137565b9284019261022092909201916001016138f6565b600082601f83011261392e57600080fd5b815161393c61307782612fc9565b81815284602083860101111561395157600080fd5b610baf8260208301602087016130e7565b60006020828403121561397457600080fd5b81516001600160401b038082111561398b57600080fd5b908301906060828603121561399f57600080fd5b6139a7612f77565b8251828111156139b657600080fd5b6139c28782860161391d565b8252506020830151828111156139d757600080fd5b6139e38782860161391d565b6020830152506040830151828111156139fb57600080fd5b613a078782860161391d565b60408301525095945050505050565b600060208284031215613a2857600080fd5b8151612c6b81612f11565b600060208284031215613a4557600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600060a08284031215613a7457600080fd5b613a7c612f4f565b905081516001600160401b03811115613a9457600080fd5b613aa08482850161391d565b8252506020820151613ab181612f11565b60208201526040820151613ac481612f11565b80604083015250606082015160608201526080820151608082015292915050565b60006020808385031215613af857600080fd5b82516001600160401b0380821115613b0f57600080fd5b818501915085601f830112613b2357600080fd5b8151613b316130778261381e565b81815260059190911b83018401908481019088831115613b5057600080fd5b8585015b83811015613b8857805185811115613b6c5760008081fd5b613b7a8b89838a0101613a62565b845250918601918601613b54565b5098975050505050505050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761062057610620613b95565b600082613bdf57634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561062057610620613b95565b600060208284031215613c0957600080fd5b81516001600160401b03811115613c1f57600080fd5b610baf84828501613a62565b60006020808385031215613c3e57600080fd5b82516001600160401b03811115613c5457600080fd5b8301601f81018513613c6557600080fd5b8051613c736130778261381e565b81815260059190911b82018301908381019087831115613c9257600080fd5b928401925b828410156138cf578351613caa81612f11565b82529284019290840190613c97565b80518015158114612f3457600080fd5b60008060408385031215613cdc57600080fd5b613ce583613cb9565b9150602083015190509250929050565b600060208284031215613d0757600080fd5b815160ff81168114612c6b57600080fd5b634e487b7160e01b600052602160045260246000fd5b6001600160a01b03831681526040810160098310613d5c57634e487b7160e01b600052602160045260246000fd5b8260208301529392505050565b600060208284031215613d7b57600080fd5b612c6b82613cb9565b600060ff821660ff8103613d9a57613d9a613b95565b60010192915050565b60006020808385031215613db657600080fd5b82516001600160401b03811115613dcc57600080fd5b8301601f81018513613ddd57600080fd5b8051613deb6130778261381e565b81815260059190911b82018301908381019087831115613e0a57600080fd5b928401925b828410156138cf578351613e2281612f11565b82529284019290840190613e0f565b60006020808385031215613e4457600080fd5b82516001600160401b03811115613e5a57600080fd5b8301601f81018513613e6b57600080fd5b8051613e796130778261381e565b81815260059190911b82018301908381019087831115613e9857600080fd5b928401925b828410156138cf578351613eb081612f11565b82529284019290840190613e9d565b600060018201613ed157613ed1613b95565b5060010190565b80516001600160e01b0381168114612f3457600080fd5b600080600060608486031215613f0457600080fd5b613f0d84613ed8565b925060208401519150604084015190509250925092565b805163ffffffff81168114612f3457600080fd5b600080600060608486031215613f4d57600080fd5b613f5684613ed8565b9250613f6460208501613f24565b9150613f7260408501613f24565b90509250925092565b600060208284031215613f8d57600080fd5b612c6b82613ed8565b8181038181111561062057610620613b95565b602081526000612c6b602083018461310b56fea264697066735822122096dca9ef030f65331631c7305d4d9405c1d0b56d48eb3787508d19369d85297764736f6c63430008190033", "devdoc": { "author": "Venus", "kind": "dev", @@ -1198,6 +1216,7 @@ "custom:oz-upgrades-unsafe-allow": "constructor", "params": { "blocksPerYear_": "The number of blocks per year", + "corePoolComptroller_": "The address of the core pool comptroller", "timeBased_": "A boolean indicating whether the contract is based on time or block." } }, @@ -1342,6 +1361,9 @@ "blocksOrSecondsPerYear()": { "notice": "Stores blocksPerYear if isTimeBased is true else secondsPerYear is stored" }, + "corePoolComptroller()": { + "notice": "Address of the core pool comptroller (all markets are returned for this pool, including paused ones)" + }, "getAllPools(address)": { "notice": "Queries all pools with addtional details for each of them" }, @@ -1391,7 +1413,7 @@ "storageLayout": { "storage": [ { - "astId": 5815, + "astId": 1737, "contract": "contracts/Lens/PoolLens.sol:PoolLens", "label": "__gap", "offset": 0, diff --git a/deployments/opmainnet/solcInputs/09f8b2889a382752688c03578bc27f8d.json b/deployments/opmainnet/solcInputs/09f8b2889a382752688c03578bc27f8d.json new file mode 100644 index 000000000..b2e4f0f5c --- /dev/null +++ b/deployments/opmainnet/solcInputs/09f8b2889a382752688c03578bc27f8d.json @@ -0,0 +1,139 @@ +{ + "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/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/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/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/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" + }, + "@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/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/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\ninterface IProtocolShareReserve {\n /// @notice it represents the type of vToken income\n enum IncomeType {\n SPREAD,\n LIQUIDATION,\n ERC4626_WRAPPER_REWARDS,\n FLASHLOAN\n }\n\n function updateAssetsState(\n address comptroller,\n address asset,\n IncomeType incomeType\n ) external;\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/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/venus-protocol/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" + }, + "@venusprotocol/venus-protocol/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/Comptroller.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { IPrime } from \"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\";\n\nimport { ComptrollerInterface, Action } from \"./ComptrollerInterface.sol\";\nimport { ComptrollerStorage } from \"./ComptrollerStorage.sol\";\nimport { ExponentialNoError } from \"./ExponentialNoError.sol\";\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.sol\";\nimport { MaxLoopsLimitHelper } from \"./MaxLoopsLimitHelper.sol\";\nimport { ensureNonzeroAddress } from \"./lib/validators.sol\";\n\n/**\n * @title Comptroller\n * @author Venus\n * @notice The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating,\n * and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts\n * with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows\n * or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing\n * liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow,\n * as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the\n * markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market’s corresponding liquidation threshold,\n * the borrow is eligible for liquidation.\n *\n * The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed\n * the `minLiquidatableCollateral` for the `Comptroller`:\n *\n * - `healAccount()`: This function is called to seize all of a given user’s collateral, requiring the `msg.sender` repay a certain percentage\n * of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed\n * 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt\n * and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool.\n * - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation\n * incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic\n * verifying that the repay amount does not exceed the close factor.\n */\ncontract Comptroller is\n Ownable2StepUpgradeable,\n AccessControlledV8,\n ComptrollerStorage,\n ComptrollerInterface,\n ExponentialNoError,\n MaxLoopsLimitHelper\n{\n // PoolRegistry, immutable to save on gas\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable poolRegistry;\n\n /// @notice Emitted when an account enters a market\n event MarketEntered(VToken indexed vToken, address indexed account);\n\n /// @notice Emitted when an account exits a market\n event MarketExited(VToken indexed vToken, address indexed account);\n\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(VToken vToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa);\n\n /// @notice Emitted when liquidation threshold is changed by admin\n event NewLiquidationThreshold(\n VToken vToken,\n uint256 oldLiquidationThresholdMantissa,\n uint256 newLiquidationThresholdMantissa\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 an action is paused on a market\n event ActionPausedMarket(VToken vToken, Action action, bool pauseState);\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 the collateral threshold (in USD) for non-batch liquidations is changed\n event NewMinLiquidatableCollateral(uint256 oldMinLiquidatableCollateral, uint256 newMinLiquidatableCollateral);\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 a rewards distributor is added\n event NewRewardsDistributor(address indexed rewardsDistributor, address indexed rewardToken);\n\n /// @notice Emitted when a market is supported\n event MarketSupported(VToken vToken);\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 a market\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\n\n /// @notice Emitted when a market is unlisted\n event MarketUnlisted(address indexed vToken);\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 Thrown when collateral factor exceeds the upper bound\n error InvalidCollateralFactor();\n\n /// @notice Thrown when liquidation threshold exceeds the collateral factor\n error InvalidLiquidationThreshold();\n\n /// @notice Thrown when the action is only available to specific sender, but the real sender was different\n error UnexpectedSender(address expectedSender, address actualSender);\n\n /// @notice Thrown when the oracle returns an invalid price for some asset\n error PriceError(address vToken);\n\n /// @notice Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\n error SnapshotError(address vToken, address user);\n\n /// @notice Thrown when the market is not listed\n error MarketNotListed(address market);\n\n /// @notice Thrown when a market has an unexpected comptroller\n error ComptrollerMismatch();\n\n /// @notice Thrown when user is not member of market\n error MarketNotCollateral(address vToken, address user);\n\n /// @notice Thrown when borrow action is not paused\n error BorrowActionNotPaused();\n\n /// @notice Thrown when mint action is not paused\n error MintActionNotPaused();\n\n /// @notice Thrown when redeem action is not paused\n error RedeemActionNotPaused();\n\n /// @notice Thrown when repay action is not paused\n error RepayActionNotPaused();\n\n /// @notice Thrown when seize action is not paused\n error SeizeActionNotPaused();\n\n /// @notice Thrown when exit market action is not paused\n error ExitMarketActionNotPaused();\n\n /// @notice Thrown when transfer action is not paused\n error TransferActionNotPaused();\n\n /// @notice Thrown when enter market action is not paused\n error EnterMarketActionNotPaused();\n\n /// @notice Thrown when liquidate action is not paused\n error LiquidateActionNotPaused();\n\n /// @notice Thrown when borrow cap is not zero\n error BorrowCapIsNotZero();\n\n /// @notice Thrown when supply cap is not zero\n error SupplyCapIsNotZero();\n\n /// @notice Thrown when collateral factor is not zero\n error CollateralFactorIsNotZero();\n\n /**\n * @notice Thrown during the liquidation if user's total collateral amount is lower than\n * a predefined threshold. In this case only batch liquidations (either liquidateAccount\n * or healAccount) are available.\n */\n error MinimalCollateralViolated(uint256 expectedGreaterThan, uint256 actual);\n error CollateralExceedsThreshold(uint256 expectedLessThanOrEqualTo, uint256 actual);\n error InsufficientCollateral(uint256 collateralToSeize, uint256 availableCollateral);\n\n /// @notice Thrown when the account doesn't have enough liquidity to redeem or borrow\n error InsufficientLiquidity();\n\n /// @notice Thrown when trying to liquidate a healthy account\n error InsufficientShortfall();\n\n /// @notice Thrown when trying to repay more than allowed by close factor\n error TooMuchRepay();\n\n /// @notice Thrown if the user is trying to exit a market in which they have an outstanding debt\n error NonzeroBorrowBalance();\n\n /// @notice Thrown when trying to perform an action that is paused\n error ActionPaused(address market, Action action);\n\n /// @notice Thrown when trying to add a market that is already listed\n error MarketAlreadyListed(address market);\n\n /// @notice Thrown if the supply cap is exceeded\n error SupplyCapExceeded(address market, uint256 cap);\n\n /// @notice Thrown if the borrow cap is exceeded\n error BorrowCapExceeded(address market, uint256 cap);\n\n /// @notice Thrown if delegate approval status is already set to the requested value\n error DelegationStatusUnchanged();\n\n /// @param poolRegistry_ Pool registry address\n /// @custom:oz-upgrades-unsafe-allow constructor\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n constructor(address poolRegistry_) {\n ensureNonzeroAddress(poolRegistry_);\n\n poolRegistry = poolRegistry_;\n _disableInitializers();\n }\n\n /**\n * @param loopLimit Limit for the loops can iterate to avoid the DOS\n * @param accessControlManager Access control manager contract address\n */\n function initialize(uint256 loopLimit, address accessControlManager) external initializer {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager);\n\n _setMaxLoopsLimit(loopLimit);\n }\n\n /**\n * @notice Add assets to be included in account liquidity calculation; enabling them to be used as collateral\n * @param vTokens The list of addresses of the vToken markets to be enabled\n * @return errors An array of NO_ERROR for compatibility with Venus core tooling\n * @custom:event MarketEntered is emitted for each market on success\n * @custom:error ActionPaused error is thrown if entering any of the markets is paused\n * @custom:error MarketNotListed error is thrown if any of the markets is not listed\n * @custom:access Not restricted\n */\n function enterMarkets(address[] memory vTokens) external override returns (uint256[] memory) {\n uint256 len = vTokens.length;\n\n uint256[] memory results = new uint256[](len);\n for (uint256 i; i < len; ++i) {\n VToken vToken = VToken(vTokens[i]);\n\n _addToMarket(vToken, msg.sender);\n results[i] = NO_ERROR;\n }\n\n return results;\n }\n\n /**\n * @notice Unlist a market by setting isListed to false\n * @dev Checks if all actions are paused, borrow/supply caps is set to 0 and collateral factor is to 0.\n * @param market The address of the market (token) to unlist\n * @return uint256 Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event MarketUnlisted is emitted on success\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error BorrowActionNotPaused error is thrown if borrow action is not paused\n * @custom:error MintActionNotPaused error is thrown if mint action is not paused\n * @custom:error RedeemActionNotPaused error is thrown if redeem action is not paused\n * @custom:error RepayActionNotPaused error is thrown if repay action is not paused\n * @custom:error EnterMarketActionNotPaused error is thrown if enter market action is not paused\n * @custom:error LiquidateActionNotPaused error is thrown if liquidate action is not paused\n * @custom:error BorrowCapIsNotZero error is thrown if borrow cap is not zero\n * @custom:error SupplyCapIsNotZero error is thrown if supply cap is not zero\n * @custom:error CollateralFactorIsNotZero error is thrown if collateral factor is not zero\n */\n function unlistMarket(address market) external returns (uint256) {\n _checkAccessAllowed(\"unlistMarket(address)\");\n\n Market storage _market = markets[market];\n\n if (!_market.isListed) {\n revert MarketNotListed(market);\n }\n\n if (!actionPaused(market, Action.BORROW)) {\n revert BorrowActionNotPaused();\n }\n\n if (!actionPaused(market, Action.MINT)) {\n revert MintActionNotPaused();\n }\n\n if (!actionPaused(market, Action.REDEEM)) {\n revert RedeemActionNotPaused();\n }\n\n if (!actionPaused(market, Action.REPAY)) {\n revert RepayActionNotPaused();\n }\n\n if (!actionPaused(market, Action.SEIZE)) {\n revert SeizeActionNotPaused();\n }\n\n if (!actionPaused(market, Action.ENTER_MARKET)) {\n revert EnterMarketActionNotPaused();\n }\n\n if (!actionPaused(market, Action.LIQUIDATE)) {\n revert LiquidateActionNotPaused();\n }\n\n if (!actionPaused(market, Action.TRANSFER)) {\n revert TransferActionNotPaused();\n }\n\n if (!actionPaused(market, Action.EXIT_MARKET)) {\n revert ExitMarketActionNotPaused();\n }\n\n if (borrowCaps[market] != 0) {\n revert BorrowCapIsNotZero();\n }\n\n if (supplyCaps[market] != 0) {\n revert SupplyCapIsNotZero();\n }\n\n if (_market.collateralFactorMantissa != 0) {\n revert CollateralFactorIsNotZero();\n }\n\n _market.isListed = false;\n emit MarketUnlisted(market);\n\n return NO_ERROR;\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 * @custom:event DelegateUpdated emits on success\n * @custom:error ZeroAddressNotAllowed is thrown when delegate address is zero\n * @custom:error DelegationStatusUnchanged is thrown if approval status is already set to the requested value\n * @custom:access Not restricted\n */\n function updateDelegate(address delegate, bool approved) external {\n ensureNonzeroAddress(delegate);\n if (approvedDelegates[msg.sender][delegate] == approved) {\n revert DelegationStatusUnchanged();\n }\n\n approvedDelegates[msg.sender][delegate] = approved;\n emit DelegateUpdated(msg.sender, delegate, approved);\n }\n\n /**\n * @notice Removes asset from sender's account liquidity calculation; disabling them as collateral\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event MarketExited is emitted on success\n * @custom:error ActionPaused error is thrown if exiting the market is paused\n * @custom:error NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function exitMarket(address vTokenAddress) external override returns (uint256) {\n _checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\n VToken vToken = VToken(vTokenAddress);\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\n (uint256 tokensHeld, uint256 amountOwed, ) = _safeGetAccountSnapshot(vToken, msg.sender);\n\n /* Fail if the sender has a borrow balance */\n if (amountOwed != 0) {\n revert NonzeroBorrowBalance();\n }\n\n /* Fail if the sender is not permitted to redeem all of their tokens */\n _checkRedeemAllowed(vTokenAddress, msg.sender, tokensHeld);\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 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 // load into memory for faster iteration\n VToken[] memory userAssetList = accountAssets[msg.sender];\n uint256 len = userAssetList.length;\n\n uint256 assetIndex = len;\n for (uint256 i; i < len; ++i) {\n if (userAssetList[i] == vToken) {\n assetIndex = i;\n break;\n }\n }\n\n // We *must* have found the asset in the list or our redundant data structure is broken\n assert(assetIndex < len);\n\n // copy last item in list to location of item to be removed, reduce length by 1\n VToken[] storage storedList = accountAssets[msg.sender];\n storedList[assetIndex] = storedList[storedList.length - 1];\n storedList.pop();\n\n emit MarketExited(vToken, msg.sender);\n\n return NO_ERROR;\n }\n\n /*** Policy Hooks ***/\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 * @custom:error ActionPaused error is thrown if supplying to this market is paused\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\n * @custom:access Not restricted\n */\n function preMintHook(address vToken, address minter, uint256 mintAmount) external override {\n _checkActionPauseState(vToken, Action.MINT);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n uint256 supplyCap = supplyCaps[vToken];\n // Skipping the cap check for uncapped coins to save some gas\n if (supplyCap != type(uint256).max) {\n uint256 vTokenSupply = VToken(vToken).totalSupply();\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\n if (nextTotalSupply > supplyCap) {\n revert SupplyCapExceeded(vToken, supplyCap);\n }\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, minter);\n }\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external override {\n _checkActionPauseState(vToken, Action.REDEEM);\n\n _checkRedeemAllowed(vToken, redeemer, redeemTokens);\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, redeemer);\n }\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 if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(redeemer, vToken);\n }\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 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 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 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 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 * @custom:error ActionPaused error is thrown if borrowing is paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if there is not enough collateral to borrow\n * @custom:error BorrowCapExceeded is thrown if the borrow cap will be exceeded should this borrow succeed\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted if vToken is enabled as collateral, otherwise only vToken\n */\n /// disable-eslint\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external override {\n _checkActionPauseState(vToken, Action.BORROW);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n if (!markets[vToken].accountMembership[borrower]) {\n // only vTokens may call borrowAllowed if borrower not in market\n _checkSenderIs(vToken);\n\n // attempt to add borrower to the market or revert\n _addToMarket(VToken(msg.sender), borrower);\n }\n\n // Update the prices of tokens\n updatePrices(borrower);\n\n if (oracle.getUnderlyingPrice(vToken) == 0) {\n revert PriceError(address(vToken));\n }\n\n uint256 borrowCap = borrowCaps[vToken];\n // Skipping the cap check for uncapped coins to save some gas\n if (borrowCap != type(uint256).max) {\n uint256 totalBorrows = VToken(vToken).totalBorrows();\n uint256 badDebt = VToken(vToken).badDebt();\n uint256 nextTotalBorrows = totalBorrows + borrowAmount + badDebt;\n if (nextTotalBorrows > borrowCap) {\n revert BorrowCapExceeded(vToken, borrowCap);\n }\n }\n\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n borrower,\n VToken(vToken),\n 0,\n borrowAmount,\n _getCollateralFactor\n );\n\n if (snapshot.shortfall > 0) {\n revert InsufficientLiquidity();\n }\n\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\n }\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 borrower The account which would borrowed the asset\n * @custom:error ActionPaused error is thrown if repayments are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:access Not restricted\n */\n function preRepayHook(address vToken, address borrower) external override {\n _checkActionPauseState(vToken, Action.REPAY);\n\n oracle.updatePrice(vToken);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\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 borrower The address of the borrower\n * @param repayAmount The amount of underlying being repaid\n * @param skipLiquidityCheck Allows the borrow to be liquidated regardless of the account liquidity\n * @custom:error ActionPaused error is thrown if liquidations are paused in this market\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\n * @custom:error TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor\n * @custom:error MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations\n * @custom:error InsufficientShortfall is thrown when trying to liquidate a healthy account\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n */\n function preLiquidateHook(\n address vTokenBorrowed,\n address vTokenCollateral,\n address borrower,\n uint256 repayAmount,\n bool skipLiquidityCheck\n ) external override {\n // Pause Action.LIQUIDATE on BORROWED TOKEN to prevent liquidating it.\n // If we want to pause liquidating to vTokenCollateral, we should pause\n // Action.SEIZE on it\n _checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\n\n // Update the prices of tokens\n updatePrices(borrower);\n\n if (!markets[vTokenBorrowed].isListed) {\n revert MarketNotListed(address(vTokenBorrowed));\n }\n if (!markets[vTokenCollateral].isListed) {\n revert MarketNotListed(address(vTokenCollateral));\n }\n\n uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\n\n /* Allow accounts to be liquidated if it is a forced liquidation */\n if (skipLiquidityCheck || isForcedLiquidationEnabled[vTokenBorrowed]) {\n if (repayAmount > borrowBalance) {\n revert TooMuchRepay();\n }\n return;\n }\n\n /* The borrower must have shortfall and collateral > threshold in order to be liquidatable */\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral <= minLiquidatableCollateral) {\n /* The liquidator should use either liquidateAccount or healAccount */\n revert MinimalCollateralViolated(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n /* The liquidator may not repay more than what is allowed by the closeFactor */\n uint256 maxClose = mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance);\n if (repayAmount > maxClose) {\n revert TooMuchRepay();\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 seizerContract Contract that tries to seize the asset (either borrowed vToken or Comptroller)\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @custom:error ActionPaused error is thrown if seizing this type of collateral is paused\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\n * @custom:error ComptrollerMismatch error is when seizer contract or seized asset belong to different pools\n * @custom:access Not restricted\n */\n function preSeizeHook(\n address vTokenCollateral,\n address seizerContract,\n address liquidator,\n address borrower\n ) external override {\n // Pause Action.SEIZE on COLLATERAL to prevent seizing it.\n // If we want to pause liquidating vTokenBorrowed, we should pause\n // Action.LIQUIDATE on it\n _checkActionPauseState(vTokenCollateral, Action.SEIZE);\n\n Market storage market = markets[vTokenCollateral];\n\n if (!market.isListed) {\n revert MarketNotListed(vTokenCollateral);\n }\n\n if (seizerContract == address(this)) {\n // If Comptroller is the seizer, just check if collateral's comptroller\n // is equal to the current address\n if (address(VToken(vTokenCollateral).comptroller()) != address(this)) {\n revert ComptrollerMismatch();\n }\n } else {\n // If the seizer is not the Comptroller, check that the seizer is a\n // listed market, and that the markets' comptrollers match\n if (!markets[seizerContract].isListed) {\n revert MarketNotListed(seizerContract);\n }\n if (VToken(vTokenCollateral).comptroller() != VToken(seizerContract).comptroller()) {\n revert ComptrollerMismatch();\n }\n }\n\n if (!market.accountMembership[borrower]) {\n revert MarketNotCollateral(vTokenCollateral, borrower);\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vTokenCollateral);\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, borrower);\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, liquidator);\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external override {\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 _checkRedeemAllowed(vToken, src, transferTokens);\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, src);\n rewardsDistributor.distributeSupplierRewardToken(vToken, dst);\n }\n }\n\n /*** Pool-level operations ***/\n\n /**\n * @notice Seizes all the remaining collateral, makes msg.sender repay the existing\n * borrows, and treats the rest of the debt as bad debt (for each market).\n * The sender has to repay a certain percentage of the debt, computed as\n * collateral / (borrows * liquidationIncentive).\n * @param user account to heal\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for healing\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function healAccount(address user) external {\n VToken[] memory userAssets = getAssetsIn(user);\n uint256 userAssetsCount = userAssets.length;\n\n address liquidator = msg.sender;\n {\n ResilientOracleInterface oracle_ = oracle;\n // We need all user's markets to be fresh for the computations to be correct\n for (uint256 i; i < userAssetsCount; ++i) {\n userAssets[i].accrueInterest();\n oracle_.updatePrice(address(userAssets[i]));\n }\n }\n\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(user, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n // percentage = collateral / (borrows * liquidation incentive)\n Exp memory collateral = Exp({ mantissa: snapshot.totalCollateral });\n Exp memory scaledBorrows = mul_(\n Exp({ mantissa: snapshot.borrows }),\n Exp({ mantissa: liquidationIncentiveMantissa })\n );\n\n Exp memory percentage = div_(collateral, scaledBorrows);\n if (lessThanExp(Exp({ mantissa: MANTISSA_ONE }), percentage)) {\n revert CollateralExceedsThreshold(scaledBorrows.mantissa, collateral.mantissa);\n }\n\n for (uint256 i; i < userAssetsCount; ++i) {\n VToken market = userAssets[i];\n\n (uint256 tokens, uint256 borrowBalance, ) = _safeGetAccountSnapshot(market, user);\n uint256 repaymentAmount = mul_ScalarTruncate(percentage, borrowBalance);\n\n // Seize the entire collateral\n if (tokens != 0) {\n market.seize(liquidator, user, tokens);\n }\n // Repay a certain percentage of the borrow, forgive the rest\n if (borrowBalance != 0) {\n market.healBorrow(liquidator, user, repaymentAmount);\n }\n }\n }\n\n /**\n * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than\n * a predefined threshold, and the account collateral can be seized to cover all borrows. If\n * the collateral is higher than the threshold, use regular liquidations. If the collateral is\n * below the threshold, and the account is insolvent, use healAccount.\n * @param borrower the borrower address\n * @param orders an array of liquidation orders\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation\n * @custom:error InsufficientCollateral error is thrown when there is not enough collateral to cover the debt\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function liquidateAccount(address borrower, LiquidationOrder[] calldata orders) external {\n // We will accrue interest and update the oracle prices later during the liquidation\n\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\n // You should use the regular vToken.liquidateBorrow(...) call\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n uint256 collateralToSeize = mul_ScalarTruncate(\n Exp({ mantissa: liquidationIncentiveMantissa }),\n snapshot.borrows\n );\n if (collateralToSeize >= snapshot.totalCollateral) {\n // There is not enough collateral to seize. Use healBorrow to repay some part of the borrow\n // and record bad debt.\n revert InsufficientCollateral(collateralToSeize, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n uint256 ordersCount = orders.length;\n\n _ensureMaxLoops(ordersCount / 2);\n\n for (uint256 i; i < ordersCount; ++i) {\n if (!markets[address(orders[i].vTokenBorrowed)].isListed) {\n revert MarketNotListed(address(orders[i].vTokenBorrowed));\n }\n if (!markets[address(orders[i].vTokenCollateral)].isListed) {\n revert MarketNotListed(address(orders[i].vTokenCollateral));\n }\n\n LiquidationOrder calldata order = orders[i];\n order.vTokenBorrowed.forceLiquidateBorrow(\n msg.sender,\n borrower,\n order.repayAmount,\n order.vTokenCollateral,\n true\n );\n }\n\n VToken[] memory borrowMarkets = getAssetsIn(borrower);\n uint256 marketsCount = borrowMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower);\n require(borrowBalance == 0, \"Nonzero borrow balance after liquidation\");\n }\n }\n\n /**\n * @notice Sets the closeFactor to use when liquidating borrows\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\n * @custom:event Emits NewCloseFactor on success\n * @custom:access Controlled by AccessControlManager\n */\n function setCloseFactor(uint256 newCloseFactorMantissa) external {\n _checkAccessAllowed(\"setCloseFactor(uint256)\");\n require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, \"Close factor greater than maximum close factor\");\n require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, \"Close factor smaller than minimum close factor\");\n\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\n closeFactorMantissa = newCloseFactorMantissa;\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\n }\n\n /**\n * @notice Sets the collateralFactor for a market\n * @dev This function is restricted by the AccessControlManager\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 * @custom:event Emits NewCollateralFactor when collateral factor is updated\n * and NewLiquidationThreshold when liquidation threshold is updated\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InvalidCollateralFactor error is thrown when collateral factor is too high\n * @custom:error InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor\n * @custom:error PriceError is thrown when the oracle returns an invalid price for the asset\n * @custom:access Controlled by AccessControlManager\n */\n function setCollateralFactor(\n VToken vToken,\n uint256 newCollateralFactorMantissa,\n uint256 newLiquidationThresholdMantissa\n ) external {\n _checkAccessAllowed(\"setCollateralFactor(address,uint256,uint256)\");\n\n // Verify market is listed\n Market storage market = markets[address(vToken)];\n if (!market.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n // Check collateral factor <= 0.9\n if (newCollateralFactorMantissa > MAX_COLLATERAL_FACTOR_MANTISSA) {\n revert InvalidCollateralFactor();\n }\n\n // Ensure that liquidation threshold <= 1\n if (newLiquidationThresholdMantissa > MANTISSA_ONE) {\n revert InvalidLiquidationThreshold();\n }\n\n // Ensure that liquidation threshold >= CF\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\n revert InvalidLiquidationThreshold();\n }\n\n // If collateral factor != 0, fail if price == 0\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\n revert PriceError(address(vToken));\n }\n\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\n market.collateralFactorMantissa = newCollateralFactorMantissa;\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\n }\n\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\n emit NewLiquidationThreshold(vToken, oldLiquidationThresholdMantissa, newLiquidationThresholdMantissa);\n }\n }\n\n /**\n * @notice Sets liquidationIncentive\n * @dev This function is restricted by the AccessControlManager\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\n * @custom:event Emits NewLiquidationIncentive on success\n * @custom:access Controlled by AccessControlManager\n */\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external {\n require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, \"liquidation incentive should be greater than 1e18\");\n\n _checkAccessAllowed(\"setLiquidationIncentive(uint256)\");\n\n // Save current value for use in log\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\n\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\n /**\n * @notice Add the market to the markets mapping and set it as listed\n * @dev Only callable by the PoolRegistry\n * @param vToken The address of the market (token) to list\n * @custom:error MarketAlreadyListed is thrown if the market is already listed in this pool\n * @custom:access Only PoolRegistry\n */\n function supportMarket(VToken vToken) external {\n _checkSenderIs(poolRegistry);\n\n if (markets[address(vToken)].isListed) {\n revert MarketAlreadyListed(address(vToken));\n }\n\n require(vToken.isVToken(), \"Comptroller: Invalid vToken\"); // Sanity check to make sure its really a VToken\n\n Market storage newMarket = markets[address(vToken)];\n newMarket.isListed = true;\n newMarket.collateralFactorMantissa = 0;\n newMarket.liquidationThresholdMantissa = 0;\n\n _addMarket(address(vToken));\n\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n rewardsDistributors[i].initializeMarket(address(vToken));\n }\n\n emit MarketSupported(vToken);\n }\n\n /**\n * @notice Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\n * @dev This function is restricted by the AccessControlManager\n * @dev A borrow cap of type(uint256).max corresponds to unlimited borrowing.\n * @dev Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed\n until the total borrows amount goes below the new borrow cap\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 type(uint256).max corresponds to unlimited borrowing.\n * @custom:access Controlled by AccessControlManager\n */\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\n _checkAccessAllowed(\"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 _ensureMaxLoops(numMarkets);\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 * @notice Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\n * @dev This function is restricted by the AccessControlManager\n * @dev A supply cap of type(uint256).max corresponds to unlimited supply.\n * @dev Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed\n until the total supplies amount goes below the new supply cap\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 type(uint256).max corresponds to unlimited supply.\n * @custom:access Controlled by AccessControlManager\n */\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\n _checkAccessAllowed(\"setMarketSupplyCaps(address[],uint256[])\");\n uint256 vTokensCount = vTokens.length;\n\n require(vTokensCount != 0, \"invalid number of markets\");\n require(vTokensCount == newSupplyCaps.length, \"invalid number of markets\");\n\n _ensureMaxLoops(vTokensCount);\n\n for (uint256 i; i < vTokensCount; ++i) {\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\n }\n }\n\n /**\n * @notice Pause/unpause specified actions\n * @dev This function is restricted by the AccessControlManager\n * @param marketsList Markets to pause/unpause the actions on\n * @param actionsList List of action ids to pause/unpause\n * @param paused The new paused state (true=paused, false=unpaused)\n * @custom:access Controlled by AccessControlManager\n */\n function setActionsPaused(VToken[] calldata marketsList, Action[] calldata actionsList, bool paused) external {\n _checkAccessAllowed(\"setActionsPaused(address[],uint256[],bool)\");\n\n uint256 marketsCount = marketsList.length;\n uint256 actionsCount = actionsList.length;\n\n _ensureMaxLoops(marketsCount * actionsCount);\n\n for (uint256 marketIdx; marketIdx < marketsCount; ++marketIdx) {\n for (uint256 actionIdx; actionIdx < actionsCount; ++actionIdx) {\n _setActionPaused(address(marketsList[marketIdx]), actionsList[actionIdx], paused);\n }\n }\n }\n\n /**\n * @notice Set the given collateral threshold for non-batch liquidations. Regular liquidations\n * will fail if the collateral amount is less than this threshold. Liquidators should use batch\n * operations like liquidateAccount or healAccount.\n * @dev This function is restricted by the AccessControlManager\n * @param newMinLiquidatableCollateral The new min liquidatable collateral (in USD).\n * @custom:access Controlled by AccessControlManager\n */\n function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external {\n _checkAccessAllowed(\"setMinLiquidatableCollateral(uint256)\");\n\n uint256 oldMinLiquidatableCollateral = minLiquidatableCollateral;\n minLiquidatableCollateral = newMinLiquidatableCollateral;\n emit NewMinLiquidatableCollateral(oldMinLiquidatableCollateral, newMinLiquidatableCollateral);\n }\n\n /**\n * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor\n * contracts with the same rewardToken, and there could be overlaping among them considering the last reward slot (block or second)\n * @dev Only callable by the admin\n * @param _rewardsDistributor Address of the RewardDistributor contract to add\n * @custom:access Only Governance\n * @custom:event Emits NewRewardsDistributor with distributor address\n */\n function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner {\n require(!rewardsDistributorExists[address(_rewardsDistributor)], \"already exists\");\n\n uint256 rewardsDistributorsLen = rewardsDistributors.length;\n _ensureMaxLoops(rewardsDistributorsLen + 1);\n\n rewardsDistributors.push(_rewardsDistributor);\n rewardsDistributorExists[address(_rewardsDistributor)] = true;\n\n uint256 marketsCount = allMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n _rewardsDistributor.initializeMarket(address(allMarkets[i]));\n }\n\n emit NewRewardsDistributor(address(_rewardsDistributor), address(_rewardsDistributor.rewardToken()));\n }\n\n /**\n * @notice Sets a new price oracle for the Comptroller\n * @dev Only callable by the admin\n * @param newOracle Address of the new price oracle to set\n * @custom:event Emits NewPriceOracle on success\n * @custom:error ZeroAddressNotAllowed is thrown when the new oracle address is zero\n */\n function setPriceOracle(ResilientOracleInterface newOracle) external onlyOwner {\n ensureNonzeroAddress(address(newOracle));\n\n ResilientOracleInterface oldOracle = oracle;\n oracle = newOracle;\n emit NewPriceOracle(oldOracle, newOracle);\n }\n\n /**\n * @notice Set the for loop iteration limit to avoid DOS\n * @param limit Limit for the max loops can execute at a time\n */\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\n _setMaxLoopsLimit(limit);\n }\n\n /**\n * @notice Sets the prime token contract for the comptroller\n * @param _prime Address of the Prime contract\n */\n function setPrimeToken(IPrime _prime) external onlyOwner {\n ensureNonzeroAddress(address(_prime));\n\n emit NewPrimeToken(prime, _prime);\n prime = _prime;\n }\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 * @param vTokenBorrowed Borrowed vToken\n * @param enable Whether to enable forced liquidations\n */\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\n _checkAccessAllowed(\"setForcedLiquidation(address,bool)\");\n ensureNonzeroAddress(vTokenBorrowed);\n\n if (!markets[vTokenBorrowed].isListed) {\n revert MarketNotListed(vTokenBorrowed);\n }\n\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\n }\n\n /**\n * @notice Determine the current account liquidity with respect to liquidation threshold requirements\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\n * @param account The account get liquidity for\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Account liquidity in excess of liquidation threshold requirements,\n * @return shortfall Account shortfall below liquidation threshold requirements\n */\n function getAccountLiquidity(\n address account\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getLiquidationThreshold);\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\n }\n\n /**\n * @notice Determine the current account liquidity with respect to collateral requirements\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\n * @param account The account get liquidity for\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Account liquidity in excess of collateral requirements,\n * @return shortfall Account shortfall below collateral requirements\n */\n function getBorrowingPower(\n address account\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getCollateralFactor);\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\n }\n\n /**\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Hypothetical account liquidity in excess of collateral requirements,\n * @return shortfall 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 error, uint256 liquidity, uint256 shortfall) {\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n account,\n VToken(vTokenModify),\n redeemTokens,\n borrowAmount,\n _getCollateralFactor\n );\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\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 markets The list of market addresses\n */\n function getAllMarkets() external view override returns (VToken[] memory) {\n return allMarkets;\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 /*** Assets You Are In ***/\n\n /**\n * @notice Returns whether the given account is entered in a given market\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 market specified, 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 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 error Always NO_ERROR for compatibility with Venus core tooling\n * @return tokensToSeize Number of vTokenCollateral tokens to be seized in a liquidation\n * @custom:error PriceError if the oracle returns an invalid price\n */\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view override returns (uint256 error, uint256 tokensToSeize) {\n /* Read oracle prices for borrowed and collateral markets */\n uint256 priceBorrowedMantissa = _safeGetUnderlyingPrice(VToken(vTokenBorrowed));\n uint256 priceCollateralMantissa = _safeGetUnderlyingPrice(VToken(vTokenCollateral));\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 uint256 exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\n uint256 seizeTokens;\n Exp memory numerator;\n Exp memory denominator;\n Exp memory ratio;\n\n numerator = mul_(Exp({ mantissa: liquidationIncentiveMantissa }), Exp({ mantissa: priceBorrowedMantissa }));\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\n ratio = div_(numerator, denominator);\n\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\n\n return (NO_ERROR, seizeTokens);\n }\n\n /**\n * @notice Returns reward speed given a vToken\n * @param vToken The vToken to get the reward speeds for\n * @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors\n */\n function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {\n uint256 rewardsDistributorsLength = rewardsDistributors.length;\n rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);\n for (uint256 i; i < rewardsDistributorsLength; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n address rewardToken = address(rewardsDistributor.rewardToken());\n rewardSpeeds[i] = RewardSpeeds({\n rewardToken: rewardToken,\n supplySpeed: rewardsDistributor.rewardTokenSupplySpeeds(vToken),\n borrowSpeed: rewardsDistributor.rewardTokenBorrowSpeeds(vToken)\n });\n }\n return rewardSpeeds;\n }\n\n /**\n * @notice Return all reward distributors for this pool\n * @return Array of RewardDistributor addresses\n */\n function getRewardDistributors() external view returns (RewardsDistributor[] memory) {\n return rewardsDistributors;\n }\n\n /**\n * @notice A marker method that returns true for a valid Comptroller contract\n * @return Always true\n */\n function isComptroller() external pure override returns (bool) {\n return true;\n }\n\n /**\n * @notice Update the prices of all the tokens associated with the provided account\n * @param account Address of the account to get associated tokens with\n */\n function updatePrices(address account) public {\n VToken[] memory vTokens = getAssetsIn(account);\n uint256 vTokensCount = vTokens.length;\n\n ResilientOracleInterface oracle_ = oracle;\n\n for (uint256 i; i < vTokensCount; ++i) {\n oracle_.updatePrice(address(vTokens[i]));\n }\n }\n\n /**\n * @notice Checks if a certain action is paused on a market\n * @param market vToken address\n * @param action Action to check\n * @return paused True if the action is paused otherwise false\n */\n function actionPaused(address market, Action action) public view returns (bool) {\n return _actionPaused[market][action];\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 list with the assets the account has entered\n */\n function getAssetsIn(address account) public 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 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 */\n function _addToMarket(VToken vToken, address borrower) internal {\n _checkActionPauseState(address(vToken), Action.ENTER_MARKET);\n Market storage marketToJoin = markets[address(vToken)];\n\n if (!marketToJoin.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n if (marketToJoin.accountMembership[borrower]) {\n // already joined\n return;\n }\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\n /**\n * @notice Internal function to validate that a market hasn't already been added\n * and if it hasn't adds it\n * @param vToken The market to support\n */\n function _addMarket(address vToken) internal {\n uint256 marketsCount = allMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n if (allMarkets[i] == VToken(vToken)) {\n revert MarketAlreadyListed(vToken);\n }\n }\n allMarkets.push(VToken(vToken));\n marketsCount = allMarkets.length;\n _ensureMaxLoops(marketsCount);\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 _setActionPaused(address market, Action action, bool paused) internal {\n require(markets[market].isListed, \"cannot pause a market that is not listed\");\n _actionPaused[market][action] = paused;\n emit ActionPausedMarket(VToken(market), action, paused);\n }\n\n /**\n * @dev Internal function to check that vTokens can be safely redeemed for the underlying asset.\n * @param vToken Address of the vTokens to redeem\n * @param redeemer Account redeeming the tokens\n * @param redeemTokens The number of tokens to redeem\n */\n function _checkRedeemAllowed(address vToken, address redeemer, uint256 redeemTokens) internal {\n Market storage market = markets[vToken];\n\n if (!market.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\n if (!market.accountMembership[redeemer]) {\n return;\n }\n\n // Update the prices of tokens\n updatePrices(redeemer);\n\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n redeemer,\n VToken(vToken),\n redeemTokens,\n 0,\n _getCollateralFactor\n );\n if (snapshot.shortfall > 0) {\n revert InsufficientLiquidity();\n }\n }\n\n /**\n * @notice Get the total collateral, weighted collateral, borrow balance, liquidity, shortfall\n * @param account The account to get the snapshot for\n * @param weight The function to compute the weight of the collateral – either collateral factor or\n * liquidation threshold. Accepts the address of the vToken and returns the weight as Exp.\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\n * without calculating accumulated interest.\n * @return snapshot Account liquidity snapshot\n */\n function _getCurrentLiquiditySnapshot(\n address account,\n function(VToken) internal view returns (Exp memory) weight\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\n return _getHypotheticalLiquiditySnapshot(account, VToken(address(0)), 0, 0, weight);\n }\n\n /**\n * @notice Determine what the supply/borrow balances 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 weight The function to compute the weight of the collateral – either collateral factor or\n liquidation threshold. Accepts the address of the VToken and returns the weight\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\n * without calculating accumulated interest.\n * @return snapshot Account liquidity snapshot\n */\n function _getHypotheticalLiquiditySnapshot(\n address account,\n VToken vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount,\n function(VToken) internal view returns (Exp memory) weight\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\n // For each asset the account is in\n VToken[] memory assets = getAssetsIn(account);\n uint256 assetsCount = assets.length;\n\n for (uint256 i; i < assetsCount; ++i) {\n VToken asset = assets[i];\n\n // Read the balances and exchange rate from the vToken\n (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) = _safeGetAccountSnapshot(\n asset,\n account\n );\n\n // Get the normalized price of the asset\n Exp memory oraclePrice = Exp({ mantissa: _safeGetUnderlyingPrice(asset) });\n\n // Pre-compute conversion factors from vTokens -> usd\n Exp memory vTokenPrice = mul_(Exp({ mantissa: exchangeRateMantissa }), oraclePrice);\n Exp memory weightedVTokenPrice = mul_(weight(asset), vTokenPrice);\n\n // weightedCollateral += weightedVTokenPrice * vTokenBalance\n snapshot.weightedCollateral = mul_ScalarTruncateAddUInt(\n weightedVTokenPrice,\n vTokenBalance,\n snapshot.weightedCollateral\n );\n\n // totalCollateral += vTokenPrice * vTokenBalance\n snapshot.totalCollateral = mul_ScalarTruncateAddUInt(vTokenPrice, vTokenBalance, snapshot.totalCollateral);\n\n // borrows += oraclePrice * borrowBalance\n snapshot.borrows = mul_ScalarTruncateAddUInt(oraclePrice, borrowBalance, snapshot.borrows);\n\n // Calculate effects of interacting with vTokenModify\n if (asset == vTokenModify) {\n // redeem effect\n // effects += tokensToDenom * redeemTokens\n snapshot.effects = mul_ScalarTruncateAddUInt(weightedVTokenPrice, redeemTokens, snapshot.effects);\n\n // borrow effect\n // effects += oraclePrice * borrowAmount\n snapshot.effects = mul_ScalarTruncateAddUInt(oraclePrice, borrowAmount, snapshot.effects);\n }\n }\n\n uint256 borrowPlusEffects = snapshot.borrows + snapshot.effects;\n // These are safe, as the underflow condition is checked first\n unchecked {\n if (snapshot.weightedCollateral > borrowPlusEffects) {\n snapshot.liquidity = snapshot.weightedCollateral - borrowPlusEffects;\n snapshot.shortfall = 0;\n } else {\n snapshot.liquidity = 0;\n snapshot.shortfall = borrowPlusEffects - snapshot.weightedCollateral;\n }\n }\n\n return snapshot;\n }\n\n /**\n * @dev Retrieves price from oracle for an asset and checks it is nonzero\n * @param asset Address for asset to query price\n * @return Underlying price\n */\n function _safeGetUnderlyingPrice(VToken asset) internal view returns (uint256) {\n uint256 oraclePriceMantissa = oracle.getUnderlyingPrice(address(asset));\n if (oraclePriceMantissa == 0) {\n revert PriceError(address(asset));\n }\n return oraclePriceMantissa;\n }\n\n /**\n * @dev Return collateral factor for a market\n * @param asset Address for asset\n * @return Collateral factor as exponential\n */\n function _getCollateralFactor(VToken asset) internal view returns (Exp memory) {\n return Exp({ mantissa: markets[address(asset)].collateralFactorMantissa });\n }\n\n /**\n * @dev Retrieves liquidation threshold for a market as an exponential\n * @param asset Address for asset to liquidation threshold\n * @return Liquidation threshold as exponential\n */\n function _getLiquidationThreshold(VToken asset) internal view returns (Exp memory) {\n return Exp({ mantissa: markets[address(asset)].liquidationThresholdMantissa });\n }\n\n /**\n * @dev Returns supply and borrow balances of user in vToken, reverts on failure\n * @param vToken Market to query\n * @param user Account address\n * @return vTokenBalance Balance of vTokens, the same as vToken.balanceOf(user)\n * @return borrowBalance Borrowed amount, including the interest\n * @return exchangeRateMantissa Stored exchange rate\n */\n function _safeGetAccountSnapshot(\n VToken vToken,\n address user\n ) internal view returns (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) {\n uint256 err;\n (err, vTokenBalance, borrowBalance, exchangeRateMantissa) = vToken.getAccountSnapshot(user);\n if (err != 0) {\n revert SnapshotError(address(vToken), user);\n }\n return (vTokenBalance, borrowBalance, exchangeRateMantissa);\n }\n\n /// @notice Reverts if the call is not from expectedSender\n /// @param expectedSender Expected transaction sender\n function _checkSenderIs(address expectedSender) internal view {\n if (msg.sender != expectedSender) {\n revert UnexpectedSender(expectedSender, msg.sender);\n }\n }\n\n /// @notice Reverts if a certain action is paused on a market\n /// @param market Market to check\n /// @param action Action to check\n function _checkActionPauseState(address market, Action action) private view {\n if (actionPaused(market, action)) {\n revert ActionPaused(market, action);\n }\n }\n}\n" + }, + "contracts/ComptrollerInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.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\n/**\n * @title ComptrollerInterface\n * @author Venus\n * @notice Interface implemented by the `Comptroller` contract.\n */\ninterface ComptrollerInterface {\n /*** Assets You Are In ***/\n\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\n\n function exitMarket(address vToken) external returns (uint256);\n\n /*** Policy Hooks ***/\n\n function preMintHook(address vToken, address minter, uint256 mintAmount) external;\n\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external;\n\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external;\n\n function preRepayHook(address vToken, address borrower) external;\n\n function preLiquidateHook(\n address vTokenBorrowed,\n address vTokenCollateral,\n address borrower,\n uint256 repayAmount,\n bool skipLiquidityCheck\n ) external;\n\n function preSeizeHook(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower\n ) external;\n\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\n\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\n\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\n\n function repayBorrowVerify(\n address vToken,\n address payer,\n address borrower,\n uint repayAmount,\n uint borrowerIndex\n ) external;\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 seizeVerify(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint seizeTokens\n ) external;\n\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\n\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external;\n\n function isComptroller() external view returns (bool);\n\n /*** Liquidity/Liquidation Calculations ***/\n\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 repayAmount\n ) external view returns (uint256, uint256);\n\n function getAllMarkets() external view returns (VToken[] memory);\n\n function actionPaused(address market, Action action) external view returns (bool);\n}\n\n/**\n * @title ComptrollerViewInterface\n * @author Venus\n * @notice Interface implemented by the `Comptroller` contract, including only some util view functions.\n */\ninterface ComptrollerViewInterface {\n function markets(address) external view returns (bool, uint256);\n\n function oracle() external view returns (ResilientOracleInterface);\n\n function getAssetsIn(address) external view returns (VToken[] memory);\n\n function closeFactorMantissa() external view returns (uint256);\n\n function liquidationIncentiveMantissa() external view returns (uint256);\n\n function minLiquidatableCollateral() external view returns (uint256);\n\n function getRewardDistributors() external view returns (RewardsDistributor[] memory);\n\n function getAllMarkets() external view returns (VToken[] memory);\n\n function borrowCaps(address) external view returns (uint256);\n\n function supplyCaps(address) external view returns (uint256);\n\n function approvedDelegates(address user, address delegate) external view returns (bool);\n}\n" + }, + "contracts/ComptrollerStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.sol\";\nimport { IPrime } from \"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\";\nimport { Action } from \"./ComptrollerInterface.sol\";\n\n/**\n * @title ComptrollerStorage\n * @author Venus\n * @notice Storage layout for the `Comptroller` contract.\n */\ncontract ComptrollerStorage {\n struct LiquidationOrder {\n VToken vTokenCollateral;\n VToken vTokenBorrowed;\n uint256 repayAmount;\n }\n\n struct AccountLiquiditySnapshot {\n uint256 totalCollateral;\n uint256 weightedCollateral;\n uint256 borrows;\n uint256 effects;\n uint256 liquidity;\n uint256 shortfall;\n }\n\n struct RewardSpeeds {\n address rewardToken;\n uint256 supplySpeed;\n uint256 borrowSpeed;\n }\n\n struct Market {\n // Whether or not this market is listed\n bool isListed;\n // 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 uint256 collateralFactorMantissa;\n // 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 uint256 liquidationThresholdMantissa;\n // Per-market mapping of \"accounts in this asset\"\n mapping(address => bool) accountMembership;\n }\n\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 Per-account mapping of \"assets you are in\"\n */\n mapping(address => VToken[]) public accountAssets;\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 /// @notice A list of all markets\n VToken[] public allMarkets;\n\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\n mapping(address => uint256) public borrowCaps;\n\n /// @notice Minimal collateral required for regular (non-batch) liquidations\n uint256 public minLiquidatableCollateral;\n\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\n mapping(address => uint256) public supplyCaps;\n\n /// @notice True if a certain action is paused on a certain market\n mapping(address => mapping(Action => bool)) internal _actionPaused;\n\n // List of Reward Distributors added\n RewardsDistributor[] internal rewardsDistributors;\n\n // Used to check if rewards distributor is added\n mapping(address => bool) internal rewardsDistributorExists;\n\n /// @notice Flag indicating whether forced liquidation enabled for a market\n mapping(address => bool) public isForcedLiquidationEnabled;\n\n uint256 internal constant NO_ERROR = 0;\n\n // closeFactorMantissa must be strictly greater than this value\n uint256 internal constant MIN_CLOSE_FACTOR_MANTISSA = 0.05e18; // 0.05\n\n // closeFactorMantissa must not exceed this value\n uint256 internal constant MAX_CLOSE_FACTOR_MANTISSA = 0.9e18; // 0.9\n\n // No collateralFactorMantissa may exceed this value\n uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.95e18; // 0.95\n\n /// Prime token address\n IPrime public prime;\n\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 /**\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[47] private __gap;\n}\n" + }, + "contracts/ErrorReporter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n/**\n * @title TokenErrorReporter\n * @author Venus\n * @notice Errors that can be thrown by the `VToken` contract.\n */\ncontract TokenErrorReporter {\n uint256 public constant NO_ERROR = 0; // support legacy return codes\n\n error TransferNotAllowed();\n\n error MintFreshnessCheck();\n\n error RedeemFreshnessCheck();\n error RedeemTransferOutNotPossible();\n\n error BorrowFreshnessCheck();\n error BorrowCashNotAvailable();\n error DelegateNotApproved();\n\n error RepayBorrowFreshnessCheck();\n\n error HealBorrowUnauthorized();\n error ForceLiquidateBorrowUnauthorized();\n\n error LiquidateFreshnessCheck();\n error LiquidateCollateralFreshnessCheck();\n error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\n error LiquidateLiquidatorIsBorrower();\n error LiquidateCloseAmountIsZero();\n error LiquidateCloseAmountIsUintMax();\n\n error LiquidateSeizeLiquidatorIsBorrower();\n\n error ProtocolSeizeShareTooBig();\n\n error SetReserveFactorFreshCheck();\n error SetReserveFactorBoundsCheck();\n\n error AddReservesFactorFreshCheck(uint256 actualAddAmount);\n\n error ReduceReservesFreshCheck();\n error ReduceReservesCashNotAvailable();\n error ReduceReservesCashValidation();\n\n error SetInterestRateModelFreshCheck();\n}\n" + }, + "contracts/ExponentialNoError.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from \"./lib/constants.sol\";\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 struct Exp {\n uint256 mantissa;\n }\n\n struct Double {\n uint256 mantissa;\n }\n\n uint256 internal constant EXP_SCALE = EXP_SCALE_;\n uint256 internal constant DOUBLE_SCALE = 1e36;\n uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;\n uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;\n\n /**\n * @dev Truncates the given exp to a whole number value.\n * For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15\n */\n function truncate(Exp memory exp) internal pure returns (uint256) {\n // Note: We are not using careful math here as we're performing a division that cannot fail\n return exp.mantissa / EXP_SCALE;\n }\n\n /**\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\n */\n // solhint-disable-next-line func-name-mixedcase\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\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 // solhint-disable-next-line func-name-mixedcase\n function mul_ScalarTruncateAddUInt(Exp memory a, uint256 scalar, uint256 addend) internal pure returns (uint256) {\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 function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\n require(n <= type(uint224).max, errorMessage);\n return uint224(n);\n }\n\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\n require(n <= type(uint32).max, 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_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a + b;\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_(uint256 a, uint256 b) internal pure returns (uint256) {\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) / EXP_SCALE });\n }\n\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\n return Exp({ mantissa: mul_(a.mantissa, b) });\n }\n\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\n return mul_(a, b.mantissa) / EXP_SCALE;\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) / DOUBLE_SCALE });\n }\n\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: mul_(a.mantissa, b) });\n }\n\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\n return mul_(a, b.mantissa) / DOUBLE_SCALE;\n }\n\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a * b;\n }\n\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });\n }\n\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\n return Exp({ mantissa: div_(a.mantissa, b) });\n }\n\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\n return div_(mul_(a, EXP_SCALE), 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, DOUBLE_SCALE), b.mantissa) });\n }\n\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(a.mantissa, b) });\n }\n\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\n return div_(mul_(a, DOUBLE_SCALE), b.mantissa);\n }\n\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a / b;\n }\n\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });\n }\n}\n" + }, + "contracts/InterestRateModel.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n/**\n * @title Compound's InterestRateModel Interface\n * @author Compound\n */\nabstract contract InterestRateModel {\n /**\n * @notice Calculates the current borrow interest rate per slot (block or second)\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 amount of reserves the market has\n * @param badDebt The amount of badDebt in the market\n * @return The borrow rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\n */\n function getBorrowRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) external view virtual returns (uint256);\n\n /**\n * @notice Calculates the current supply interest rate per slot (block or second)\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 amount of reserves the market has\n * @param reserveFactorMantissa The current reserve factor the market has\n * @param badDebt The amount of badDebt in the market\n * @return The supply rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\n */\n function getSupplyRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 reserveFactorMantissa,\n uint256 badDebt\n ) external view virtual returns (uint256);\n\n /**\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\n * @return Always true\n */\n function isInterestRateModel() external pure virtual returns (bool) {\n return true;\n }\n}\n" + }, + "contracts/Lens/PoolLens.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IERC20Metadata } from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { ExponentialNoError } from \"../ExponentialNoError.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { Action, ComptrollerInterface, ComptrollerViewInterface } from \"../ComptrollerInterface.sol\";\nimport { PoolRegistryInterface } from \"../Pool/PoolRegistryInterface.sol\";\nimport { PoolRegistry } from \"../Pool/PoolRegistry.sol\";\nimport { RewardsDistributor } from \"../Rewards/RewardsDistributor.sol\";\nimport { TimeManagerV8 } from \"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\";\n\n/**\n * @title PoolLens\n * @author Venus\n * @notice The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information\n * for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be\n * looked up for specific pools and markets:\n- the vToken balance of a given user;\n- the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address;\n- the vToken address in a pool for a given asset;\n- a list of all pools that support an asset;\n- the underlying asset price of a vToken;\n- the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\n */\ncontract PoolLens is ExponentialNoError, TimeManagerV8 {\n /**\n * @dev Struct for PoolDetails.\n */\n struct PoolData {\n string name;\n address creator;\n address comptroller;\n uint256 blockPosted;\n uint256 timestampPosted;\n string category;\n string logoURL;\n string description;\n address priceOracle;\n uint256 closeFactor;\n uint256 liquidationIncentive;\n uint256 minLiquidatableCollateral;\n VTokenMetadata[] vTokens;\n }\n\n /**\n * @dev Struct for VToken.\n */\n struct VTokenMetadata {\n address vToken;\n uint256 exchangeRateCurrent;\n uint256 supplyRatePerBlockOrTimestamp;\n uint256 borrowRatePerBlockOrTimestamp;\n uint256 reserveFactorMantissa;\n uint256 supplyCaps;\n uint256 borrowCaps;\n uint256 totalBorrows;\n uint256 totalReserves;\n uint256 totalSupply;\n uint256 totalCash;\n bool isListed;\n uint256 collateralFactorMantissa;\n address underlyingAssetAddress;\n uint256 vTokenDecimals;\n uint256 underlyingDecimals;\n uint256 pausedActions;\n }\n\n /**\n * @dev Struct for VTokenBalance.\n */\n struct VTokenBalances {\n address vToken;\n uint256 balanceOf;\n uint256 borrowBalanceCurrent;\n uint256 balanceOfUnderlying;\n uint256 tokenBalance;\n uint256 tokenAllowance;\n }\n\n /**\n * @dev Struct for underlyingPrice of VToken.\n */\n struct VTokenUnderlyingPrice {\n address vToken;\n uint256 underlyingPrice;\n }\n\n /**\n * @dev Struct with pending reward info for a market.\n */\n struct PendingReward {\n address vTokenAddress;\n uint256 amount;\n }\n\n /**\n * @dev Struct with reward distribution totals for a single reward token and distributor.\n */\n struct RewardSummary {\n address distributorAddress;\n address rewardTokenAddress;\n uint256 totalRewards;\n PendingReward[] pendingRewards;\n }\n\n /**\n * @dev Struct used in RewardDistributor to save last updated market state.\n */\n struct RewardTokenState {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block number or timestamp the index was last updated at\n uint256 blockOrTimestamp;\n // The block number or timestamp at which to stop rewards\n uint256 lastRewardingBlockOrTimestamp;\n }\n\n /**\n * @dev Struct with bad debt of a market denominated\n */\n struct BadDebt {\n address vTokenAddress;\n uint256 badDebtUsd;\n }\n\n /**\n * @dev Struct with bad debt total denominated in usd for a pool and an array of BadDebt structs for each market\n */\n struct BadDebtSummary {\n address comptroller;\n uint256 totalBadDebtUsd;\n BadDebt[] badDebts;\n }\n\n /// @notice Address of the core pool comptroller (all markets are returned for this pool, including paused ones)\n address public immutable corePoolComptroller;\n\n /**\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\n * @param blocksPerYear_ The number of blocks per year\n * @param corePoolComptroller_ The address of the core pool comptroller\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor(\n bool timeBased_,\n uint256 blocksPerYear_,\n address corePoolComptroller_\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\n corePoolComptroller = corePoolComptroller_;\n }\n\n /**\n * @notice Queries the user's supply/borrow balances in vTokens\n * @param vTokens The list of vToken addresses\n * @param account The user Account\n * @return A list of structs containing balances data\n */\n function vTokenBalancesAll(VToken[] calldata vTokens, address account) external returns (VTokenBalances[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenBalances[] memory res = new VTokenBalances[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenBalances(vTokens[i], account);\n }\n return res;\n }\n\n /**\n * @notice Queries all pools with addtional details for each of them\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @return Arrays of all Venus pools' data\n */\n function getAllPools(address poolRegistryAddress) external view returns (PoolData[] memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n PoolRegistry.VenusPool[] memory venusPools = poolRegistryInterface.getAllPools();\n uint256 poolLength = venusPools.length;\n\n PoolData[] memory poolDataItems = new PoolData[](poolLength);\n\n for (uint256 i; i < poolLength; ++i) {\n PoolRegistry.VenusPool memory venusPool = venusPools[i];\n PoolData memory poolData = getPoolDataFromVenusPool(poolRegistryAddress, venusPool);\n poolDataItems[i] = poolData;\n }\n\n return poolDataItems;\n }\n\n /**\n * @notice Queries the details of a pool identified by Comptroller address\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param comptroller The Comptroller implementation address\n * @return PoolData structure containing the details of the pool\n */\n function getPoolByComptroller(\n address poolRegistryAddress,\n address comptroller\n ) external view returns (PoolData memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return getPoolDataFromVenusPool(poolRegistryAddress, poolRegistryInterface.getPoolByComptroller(comptroller));\n }\n\n /**\n * @notice Returns vToken holding the specified underlying asset in the specified pool\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param comptroller The pool comptroller\n * @param asset The underlyingAsset of VToken\n * @return Address of the vToken\n */\n function getVTokenForAsset(\n address poolRegistryAddress,\n address comptroller,\n address asset\n ) external view returns (address) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return poolRegistryInterface.getVTokenForAsset(comptroller, asset);\n }\n\n /**\n * @notice Returns all pools that support the specified underlying asset\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param asset The underlying asset of vToken\n * @return A list of Comptroller contracts\n */\n function getPoolsSupportedByAsset(\n address poolRegistryAddress,\n address asset\n ) external view returns (address[] memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return poolRegistryInterface.getPoolsSupportedByAsset(asset);\n }\n\n /**\n * @notice Returns the price data for the underlying assets of the specified vTokens\n * @param vTokens The list of vToken addresses\n * @return An array containing the price data for each asset\n */\n function vTokenUnderlyingPriceAll(\n VToken[] calldata vTokens\n ) external view returns (VTokenUnderlyingPrice[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenUnderlyingPrice[] memory res = new VTokenUnderlyingPrice[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenUnderlyingPrice(vTokens[i]);\n }\n return res;\n }\n\n /**\n * @notice Returns the pending rewards for a user for a given pool.\n * @param account The user account.\n * @param comptrollerAddress address\n * @return Pending rewards array\n */\n function getPendingRewards(\n address account,\n address comptrollerAddress\n ) external view returns (RewardSummary[] memory) {\n VToken[] memory markets = _getMarkets(ComptrollerInterface(comptrollerAddress));\n RewardsDistributor[] memory rewardsDistributors = ComptrollerViewInterface(comptrollerAddress)\n .getRewardDistributors();\n RewardSummary[] memory rewardSummary = new RewardSummary[](rewardsDistributors.length);\n for (uint256 i; i < rewardsDistributors.length; ++i) {\n RewardSummary memory reward;\n reward.distributorAddress = address(rewardsDistributors[i]);\n reward.rewardTokenAddress = address(rewardsDistributors[i].rewardToken());\n reward.totalRewards = rewardsDistributors[i].rewardTokenAccrued(account);\n reward.pendingRewards = _calculateNotDistributedAwards(account, markets, rewardsDistributors[i]);\n rewardSummary[i] = reward;\n }\n return rewardSummary;\n }\n\n /**\n * @notice Returns a summary of a pool's bad debt broken down by market\n *\n * @param comptrollerAddress Address of the comptroller\n *\n * @return badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and\n * a break down of bad debt by market\n */\n function getPoolBadDebt(address comptrollerAddress) external view returns (BadDebtSummary memory) {\n uint256 totalBadDebtUsd;\n\n // Get every listed market in the pool\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\n VToken[] memory markets = _getMarkets(ComptrollerInterface(comptrollerAddress));\n ResilientOracleInterface priceOracle = comptroller.oracle();\n\n BadDebt[] memory badDebts = new BadDebt[](markets.length);\n\n BadDebtSummary memory badDebtSummary;\n badDebtSummary.comptroller = comptrollerAddress;\n badDebtSummary.badDebts = badDebts;\n\n // // Calculate the bad debt is USD per market\n for (uint256 i; i < markets.length; ++i) {\n BadDebt memory badDebt;\n badDebt.vTokenAddress = address(markets[i]);\n badDebt.badDebtUsd =\n (VToken(address(markets[i])).badDebt() * priceOracle.getUnderlyingPrice(address(markets[i]))) /\n EXP_SCALE;\n badDebtSummary.badDebts[i] = badDebt;\n totalBadDebtUsd = totalBadDebtUsd + badDebt.badDebtUsd;\n }\n\n badDebtSummary.totalBadDebtUsd = totalBadDebtUsd;\n\n return badDebtSummary;\n }\n\n /**\n * @notice Queries the user's supply/borrow balances in the specified vToken\n * @param vToken vToken address\n * @param account The user Account\n * @return A struct containing the balances data\n */\n function vTokenBalances(VToken vToken, address account) public returns (VTokenBalances memory) {\n uint256 balanceOf = vToken.balanceOf(account);\n uint256 borrowBalanceCurrent = vToken.borrowBalanceCurrent(account);\n uint256 balanceOfUnderlying = vToken.balanceOfUnderlying(account);\n uint256 tokenBalance;\n uint256 tokenAllowance;\n\n IERC20 underlying = IERC20(vToken.underlying());\n tokenBalance = underlying.balanceOf(account);\n tokenAllowance = underlying.allowance(account, address(vToken));\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 Queries additional information for the pool\n * @param poolRegistryAddress Address of the PoolRegistry\n * @param venusPool The VenusPool Object from PoolRegistry\n * @return Enriched PoolData\n */\n function getPoolDataFromVenusPool(\n address poolRegistryAddress,\n PoolRegistry.VenusPool memory venusPool\n ) public view returns (PoolData memory) {\n // Get tokens in the Pool\n ComptrollerInterface comptrollerInstance = ComptrollerInterface(venusPool.comptroller);\n\n VToken[] memory vTokens = _getMarkets(comptrollerInstance);\n\n VTokenMetadata[] memory vTokenMetadataItems = vTokenMetadataAll(vTokens);\n\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n\n PoolRegistry.VenusPoolMetaData memory venusPoolMetaData = poolRegistryInterface.getVenusPoolMetadata(\n venusPool.comptroller\n );\n\n ComptrollerViewInterface comptrollerViewInstance = ComptrollerViewInterface(venusPool.comptroller);\n\n PoolData memory poolData = PoolData({\n name: venusPool.name,\n creator: venusPool.creator,\n comptroller: venusPool.comptroller,\n blockPosted: venusPool.blockPosted,\n timestampPosted: venusPool.timestampPosted,\n category: venusPoolMetaData.category,\n logoURL: venusPoolMetaData.logoURL,\n description: venusPoolMetaData.description,\n vTokens: vTokenMetadataItems,\n priceOracle: address(comptrollerViewInstance.oracle()),\n closeFactor: comptrollerViewInstance.closeFactorMantissa(),\n liquidationIncentive: comptrollerViewInstance.liquidationIncentiveMantissa(),\n minLiquidatableCollateral: comptrollerViewInstance.minLiquidatableCollateral()\n });\n\n return poolData;\n }\n\n /**\n * @notice Returns the metadata of VToken\n * @param vToken The address of vToken\n * @return VTokenMetadata struct\n */\n function vTokenMetadata(VToken vToken) public view returns (VTokenMetadata memory) {\n uint256 exchangeRateCurrent = vToken.exchangeRateStored();\n address comptrollerAddress = address(vToken.comptroller());\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\n (bool isListed, uint256 collateralFactorMantissa) = comptroller.markets(address(vToken));\n\n address underlyingAssetAddress = vToken.underlying();\n uint256 underlyingDecimals = IERC20Metadata(underlyingAssetAddress).decimals();\n\n uint256 pausedActions;\n for (uint8 i; i <= uint8(type(Action).max); ++i) {\n uint256 paused = ComptrollerInterface(comptrollerAddress).actionPaused(address(vToken), Action(i)) ? 1 : 0;\n pausedActions |= paused << i;\n }\n\n uint256 supplyRatePerBlock;\n\n if (vToken.totalSupply() > 0) {\n supplyRatePerBlock = vToken.supplyRatePerBlock();\n }\n\n return\n VTokenMetadata({\n vToken: address(vToken),\n exchangeRateCurrent: exchangeRateCurrent,\n supplyRatePerBlockOrTimestamp: supplyRatePerBlock,\n borrowRatePerBlockOrTimestamp: vToken.borrowRatePerBlock(),\n reserveFactorMantissa: vToken.reserveFactorMantissa(),\n supplyCaps: comptroller.supplyCaps(address(vToken)),\n borrowCaps: comptroller.borrowCaps(address(vToken)),\n totalBorrows: vToken.totalBorrows(),\n totalReserves: vToken.totalReserves(),\n totalSupply: vToken.totalSupply(),\n totalCash: vToken.getCash(),\n isListed: isListed,\n collateralFactorMantissa: collateralFactorMantissa,\n underlyingAssetAddress: underlyingAssetAddress,\n vTokenDecimals: vToken.decimals(),\n underlyingDecimals: underlyingDecimals,\n pausedActions: pausedActions\n });\n }\n\n /**\n * @notice Returns the metadata of all VTokens\n * @param vTokens The list of vToken addresses\n * @return An array of VTokenMetadata structs\n */\n function vTokenMetadataAll(VToken[] memory vTokens) public view returns (VTokenMetadata[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenMetadata[] memory res = new VTokenMetadata[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenMetadata(vTokens[i]);\n }\n return res;\n }\n\n /**\n * @notice Returns the price data for the underlying asset of the specified vToken\n * @param vToken vToken address\n * @return The price data for each asset\n */\n function vTokenUnderlyingPrice(VToken vToken) public view returns (VTokenUnderlyingPrice memory) {\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(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 Returns markets from a comptroller. For the core pool, all markets are returned.\n * For other pools, markets with zero internalCash are filtered.\n * @param comptroller The comptroller to query\n * @return An array of VToken addresses\n */\n function _getMarkets(ComptrollerInterface comptroller) internal view returns (VToken[] memory) {\n VToken[] memory allMarkets = comptroller.getAllMarkets();\n\n if (address(comptroller) == corePoolComptroller) {\n return allMarkets;\n }\n\n // Single-loop filter: pack active markets to the front of allMarkets\n uint256 count;\n uint256 len = allMarkets.length;\n for (uint256 i; i < len; ++i) {\n if (allMarkets[i].internalCash() > 0) {\n allMarkets[count] = allMarkets[i];\n ++count;\n }\n }\n\n // Trim the array to the active count\n assembly {\n mstore(allMarkets, count)\n }\n\n return allMarkets;\n }\n\n function _calculateNotDistributedAwards(\n address account,\n VToken[] memory markets,\n RewardsDistributor rewardsDistributor\n ) internal view returns (PendingReward[] memory) {\n PendingReward[] memory pendingRewards = new PendingReward[](markets.length);\n\n for (uint256 i; i < markets.length; ++i) {\n // Market borrow and supply state we will modify update in-memory, in order to not modify storage\n RewardTokenState memory borrowState;\n RewardTokenState memory supplyState;\n\n if (isTimeBased) {\n (\n borrowState.index,\n borrowState.blockOrTimestamp,\n borrowState.lastRewardingBlockOrTimestamp\n ) = rewardsDistributor.rewardTokenBorrowStateTimeBased(address(markets[i]));\n (\n supplyState.index,\n supplyState.blockOrTimestamp,\n supplyState.lastRewardingBlockOrTimestamp\n ) = rewardsDistributor.rewardTokenSupplyStateTimeBased(address(markets[i]));\n } else {\n (\n borrowState.index,\n borrowState.blockOrTimestamp,\n borrowState.lastRewardingBlockOrTimestamp\n ) = rewardsDistributor.rewardTokenBorrowState(address(markets[i]));\n (\n supplyState.index,\n supplyState.blockOrTimestamp,\n supplyState.lastRewardingBlockOrTimestamp\n ) = rewardsDistributor.rewardTokenSupplyState(address(markets[i]));\n }\n\n Exp memory marketBorrowIndex = Exp({ mantissa: markets[i].borrowIndex() });\n\n // Update market supply and borrow index in-memory\n updateMarketBorrowIndex(address(markets[i]), rewardsDistributor, borrowState, marketBorrowIndex);\n updateMarketSupplyIndex(address(markets[i]), rewardsDistributor, supplyState);\n\n // Calculate pending rewards\n uint256 borrowReward = calculateBorrowerReward(\n address(markets[i]),\n rewardsDistributor,\n account,\n borrowState,\n marketBorrowIndex\n );\n uint256 supplyReward = calculateSupplierReward(\n address(markets[i]),\n rewardsDistributor,\n account,\n supplyState\n );\n\n PendingReward memory pendingReward;\n pendingReward.vTokenAddress = address(markets[i]);\n pendingReward.amount = borrowReward + supplyReward;\n pendingRewards[i] = pendingReward;\n }\n return pendingRewards;\n }\n\n function updateMarketBorrowIndex(\n address vToken,\n RewardsDistributor rewardsDistributor,\n RewardTokenState memory borrowState,\n Exp memory marketBorrowIndex\n ) internal view {\n uint256 borrowSpeed = rewardsDistributor.rewardTokenBorrowSpeeds(vToken);\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n if (\n borrowState.lastRewardingBlockOrTimestamp > 0 &&\n blockNumberOrTimestamp > borrowState.lastRewardingBlockOrTimestamp\n ) {\n blockNumberOrTimestamp = borrowState.lastRewardingBlockOrTimestamp;\n }\n\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, borrowState.blockOrTimestamp);\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\n // Remove the total earned interest rate since the opening of the market from total borrows\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, borrowSpeed);\n Double memory ratio = borrowAmount > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\n } else if (deltaBlocksOrTimestamp > 0) {\n borrowState.blockOrTimestamp = blockNumberOrTimestamp;\n }\n }\n\n function updateMarketSupplyIndex(\n address vToken,\n RewardsDistributor rewardsDistributor,\n RewardTokenState memory supplyState\n ) internal view {\n uint256 supplySpeed = rewardsDistributor.rewardTokenSupplySpeeds(vToken);\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n if (\n supplyState.lastRewardingBlockOrTimestamp > 0 &&\n blockNumberOrTimestamp > supplyState.lastRewardingBlockOrTimestamp\n ) {\n blockNumberOrTimestamp = supplyState.lastRewardingBlockOrTimestamp;\n }\n\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, supplyState.blockOrTimestamp);\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\n uint256 supplyTokens = VToken(vToken).totalSupply();\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, supplySpeed);\n Double memory ratio = supplyTokens > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\n } else if (deltaBlocksOrTimestamp > 0) {\n supplyState.blockOrTimestamp = blockNumberOrTimestamp;\n }\n }\n\n function calculateBorrowerReward(\n address vToken,\n RewardsDistributor rewardsDistributor,\n address borrower,\n RewardTokenState memory borrowState,\n Exp memory marketBorrowIndex\n ) internal view returns (uint256) {\n Double memory borrowIndex = Double({ mantissa: borrowState.index });\n Double memory borrowerIndex = Double({\n mantissa: rewardsDistributor.rewardTokenBorrowerIndex(vToken, borrower)\n });\n if (borrowerIndex.mantissa == 0 && borrowIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\n // Covers the case where users borrowed tokens before the market's borrow state index was set\n borrowerIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\n }\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\n return borrowerDelta;\n }\n\n function calculateSupplierReward(\n address vToken,\n RewardsDistributor rewardsDistributor,\n address supplier,\n RewardTokenState memory supplyState\n ) internal view returns (uint256) {\n Double memory supplyIndex = Double({ mantissa: supplyState.index });\n Double memory supplierIndex = Double({\n mantissa: rewardsDistributor.rewardTokenSupplierIndex(vToken, supplier)\n });\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\n // Covers the case where users supplied tokens before the market's supply state index was set\n supplierIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\n }\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\n return supplierDelta;\n }\n}\n" + }, + "contracts/lib/constants.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\n/// @dev The approximate number of seconds per year\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\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" + }, + "contracts/lib/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 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" + }, + "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" + }, + "contracts/Pool/PoolRegistry.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\n\nimport { PoolRegistryInterface } from \"./PoolRegistryInterface.sol\";\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { ensureNonzeroAddress } from \"../lib/validators.sol\";\n\n/**\n * @title PoolRegistry\n * @author Venus\n * @notice The Isolated Pools architecture centers around the `PoolRegistry` contract. The `PoolRegistry` maintains a directory of isolated lending\n * pools and can perform actions like creating and registering new pools, adding new markets to existing pools, setting and updating the pool's required\n * metadata, and providing the getter methods to get information on the pools.\n *\n * Isolated lending has three main components: PoolRegistry, pools, and markets. The PoolRegistry is responsible for managing pools.\n * It can create new pools, update pool metadata and manage markets within pools. PoolRegistry contains getter methods to get the details of\n * any existing pool like `getVTokenForAsset` and `getPoolsSupportedByAsset`. It also contains methods for updating pool metadata (`updatePoolMetadata`)\n * and setting pool name (`setPoolName`).\n *\n * The directory of pools is managed through two mappings: `_poolByComptroller` which is a hashmap with the comptroller address as the key and `VenusPool` as\n * the value and `_poolsByID` which is an array of comptroller addresses. Individual pools can be accessed by calling `getPoolByComptroller` with the pool's\n * comptroller address. `_poolsByID` is used to iterate through all of the pools.\n *\n * PoolRegistry also contains a map of asset addresses called `_supportedPools` that maps to an array of assets suppored by each pool. This array of pools by\n * asset is retrieved by calling `getPoolsSupportedByAsset`.\n *\n * PoolRegistry registers new isolated pools in the directory with the `createRegistryPool` method. Isolated pools are composed of independent markets with\n * specific assets and custom risk management configurations according to their markets.\n */\ncontract PoolRegistry is Ownable2StepUpgradeable, AccessControlledV8, PoolRegistryInterface {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n struct AddMarketInput {\n VToken vToken;\n uint256 collateralFactor;\n uint256 liquidationThreshold;\n uint256 initialSupply;\n address vTokenReceiver;\n uint256 supplyCap;\n uint256 borrowCap;\n }\n\n uint256 internal constant MAX_POOL_NAME_LENGTH = 100;\n\n /**\n * @notice Maps pool's comptroller address to metadata.\n */\n mapping(address => VenusPoolMetaData) public metadata;\n\n /**\n * @dev Maps pool ID to pool's comptroller address\n */\n mapping(uint256 => address) private _poolsByID;\n\n /**\n * @dev Total number of pools created.\n */\n uint256 private _numberOfPools;\n\n /**\n * @dev Maps comptroller address to Venus pool Index.\n */\n mapping(address => VenusPool) private _poolByComptroller;\n\n /**\n * @dev Maps pool's comptroller address to asset to vToken.\n */\n mapping(address => mapping(address => address)) private _vTokens;\n\n /**\n * @dev Maps asset to list of supported pools.\n */\n mapping(address => address[]) private _supportedPools;\n\n /**\n * @notice Emitted when a new Venus pool is added to the directory.\n */\n event PoolRegistered(address indexed comptroller, VenusPool pool);\n\n /**\n * @notice Emitted when a pool name is set.\n */\n event PoolNameSet(address indexed comptroller, string oldName, string newName);\n\n /**\n * @notice Emitted when a pool metadata is updated.\n */\n event PoolMetadataUpdated(\n address indexed comptroller,\n VenusPoolMetaData oldMetadata,\n VenusPoolMetaData newMetadata\n );\n\n /**\n * @notice Emitted when a Market is added to the pool.\n */\n event MarketAdded(address indexed comptroller, address indexed vTokenAddress);\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the deployer to owner\n * @param accessControlManager_ AccessControlManager contract address\n */\n function initialize(address accessControlManager_) external initializer {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n }\n\n /**\n * @notice Adds a new Venus pool to the directory\n * @dev Price oracle must be configured before adding a pool\n * @param name The name of the pool\n * @param comptroller Pool's Comptroller contract\n * @param closeFactor The pool's close factor (scaled by 1e18)\n * @param liquidationIncentive The pool's liquidation incentive (scaled by 1e18)\n * @param minLiquidatableCollateral Minimal collateral for regular (non-batch) liquidations flow\n * @return index The index of the registered Venus pool\n * @custom:error ZeroAddressNotAllowed is thrown when Comptroller address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\n */\n function addPool(\n string calldata name,\n Comptroller comptroller,\n uint256 closeFactor,\n uint256 liquidationIncentive,\n uint256 minLiquidatableCollateral\n ) external virtual returns (uint256 index) {\n _checkAccessAllowed(\"addPool(string,address,uint256,uint256,uint256)\");\n // Input validation\n ensureNonzeroAddress(address(comptroller));\n ensureNonzeroAddress(address(comptroller.oracle()));\n\n uint256 poolId = _registerPool(name, address(comptroller));\n\n // Set Venus pool parameters\n comptroller.setCloseFactor(closeFactor);\n comptroller.setLiquidationIncentive(liquidationIncentive);\n comptroller.setMinLiquidatableCollateral(minLiquidatableCollateral);\n\n return poolId;\n }\n\n /**\n * @notice Add a market to an existing pool and then mint to provide initial supply\n * @param input The structure describing the parameters for adding a market to a pool\n * @custom:error ZeroAddressNotAllowed is thrown when vToken address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when vTokenReceiver address is zero\n */\n function addMarket(AddMarketInput memory input) external {\n _checkAccessAllowed(\"addMarket(AddMarketInput)\");\n ensureNonzeroAddress(address(input.vToken));\n ensureNonzeroAddress(input.vTokenReceiver);\n require(input.initialSupply > 0, \"PoolRegistry: initialSupply is zero\");\n\n VToken vToken = input.vToken;\n address vTokenAddress = address(vToken);\n address comptrollerAddress = address(vToken.comptroller());\n Comptroller comptroller = Comptroller(comptrollerAddress);\n address underlyingAddress = vToken.underlying();\n IERC20Upgradeable underlying = IERC20Upgradeable(underlyingAddress);\n\n require(_poolByComptroller[comptrollerAddress].creator != address(0), \"PoolRegistry: Pool not registered\");\n // solhint-disable-next-line reason-string\n require(\n _vTokens[comptrollerAddress][underlyingAddress] == address(0),\n \"PoolRegistry: Market already added for asset comptroller combination\"\n );\n\n comptroller.supportMarket(vToken);\n comptroller.setCollateralFactor(vToken, input.collateralFactor, input.liquidationThreshold);\n\n uint256[] memory newSupplyCaps = new uint256[](1);\n uint256[] memory newBorrowCaps = new uint256[](1);\n VToken[] memory vTokens = new VToken[](1);\n\n newSupplyCaps[0] = input.supplyCap;\n newBorrowCaps[0] = input.borrowCap;\n vTokens[0] = vToken;\n\n comptroller.setMarketSupplyCaps(vTokens, newSupplyCaps);\n comptroller.setMarketBorrowCaps(vTokens, newBorrowCaps);\n\n _vTokens[comptrollerAddress][underlyingAddress] = vTokenAddress;\n _supportedPools[underlyingAddress].push(comptrollerAddress);\n\n uint256 amountToSupply = _transferIn(underlying, msg.sender, input.initialSupply);\n underlying.forceApprove(vTokenAddress, 0);\n underlying.forceApprove(vTokenAddress, amountToSupply);\n vToken.mintBehalf(input.vTokenReceiver, amountToSupply);\n\n emit MarketAdded(comptrollerAddress, vTokenAddress);\n }\n\n /**\n * @notice Modify existing Venus pool name\n * @param comptroller Pool's Comptroller\n * @param name New pool name\n */\n function setPoolName(address comptroller, string calldata name) external {\n _checkAccessAllowed(\"setPoolName(address,string)\");\n _ensureValidName(name);\n VenusPool storage pool = _poolByComptroller[comptroller];\n string memory oldName = pool.name;\n pool.name = name;\n emit PoolNameSet(comptroller, oldName, name);\n }\n\n /**\n * @notice Update metadata of an existing pool\n * @param comptroller Pool's Comptroller\n * @param metadata_ New pool metadata\n */\n function updatePoolMetadata(address comptroller, VenusPoolMetaData calldata metadata_) external {\n _checkAccessAllowed(\"updatePoolMetadata(address,VenusPoolMetaData)\");\n VenusPoolMetaData memory oldMetadata = metadata[comptroller];\n metadata[comptroller] = metadata_;\n emit PoolMetadataUpdated(comptroller, oldMetadata, metadata_);\n }\n\n /**\n * @notice Returns arrays of all Venus pools' data\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\n * @return A list of all pools within PoolRegistry, with details for each pool\n */\n function getAllPools() external view override returns (VenusPool[] memory) {\n uint256 numberOfPools_ = _numberOfPools; // storage load to save gas\n VenusPool[] memory _pools = new VenusPool[](numberOfPools_);\n for (uint256 i = 1; i <= numberOfPools_; ++i) {\n address comptroller = _poolsByID[i];\n _pools[i - 1] = (_poolByComptroller[comptroller]);\n }\n return _pools;\n }\n\n /**\n * @param comptroller The comptroller proxy address associated to the pool\n * @return Returns Venus pool\n */\n function getPoolByComptroller(address comptroller) external view override returns (VenusPool memory) {\n return _poolByComptroller[comptroller];\n }\n\n /**\n * @param comptroller comptroller of Venus pool\n * @return Returns Metadata of Venus pool\n */\n function getVenusPoolMetadata(address comptroller) external view override returns (VenusPoolMetaData memory) {\n return metadata[comptroller];\n }\n\n function getVTokenForAsset(address comptroller, address asset) external view override returns (address) {\n return _vTokens[comptroller][asset];\n }\n\n function getPoolsSupportedByAsset(address asset) external view override returns (address[] memory) {\n return _supportedPools[asset];\n }\n\n /**\n * @dev Adds a new Venus pool to the directory (without checking msg.sender).\n * @param name The name of the pool\n * @param comptroller The pool's Comptroller proxy contract address\n * @return The index of the registered Venus pool\n */\n function _registerPool(string calldata name, address comptroller) internal returns (uint256) {\n VenusPool storage storedPool = _poolByComptroller[comptroller];\n\n require(storedPool.creator == address(0), \"PoolRegistry: Pool already exists in the directory.\");\n _ensureValidName(name);\n\n ++_numberOfPools;\n uint256 numberOfPools_ = _numberOfPools; // cache on stack to save storage read gas\n\n VenusPool memory pool = VenusPool(name, msg.sender, comptroller, block.number, block.timestamp);\n\n _poolsByID[numberOfPools_] = comptroller;\n _poolByComptroller[comptroller] = pool;\n\n emit PoolRegistered(comptroller, pool);\n return numberOfPools_;\n }\n\n function _transferIn(IERC20Upgradeable token, address from, uint256 amount) internal returns (uint256) {\n uint256 balanceBefore = token.balanceOf(address(this));\n token.safeTransferFrom(from, address(this), amount);\n uint256 balanceAfter = token.balanceOf(address(this));\n return balanceAfter - balanceBefore;\n }\n\n function _ensureValidName(string calldata name) internal pure {\n require(bytes(name).length <= MAX_POOL_NAME_LENGTH, \"Pool's name is too large\");\n }\n}\n" + }, + "contracts/Pool/PoolRegistryInterface.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 /**\n * @notice Struct for a Venus interest rate pool metadata.\n */\n struct VenusPoolMetaData {\n string category;\n string logoURL;\n string description;\n }\n\n /// @notice Get all pools in PoolRegistry\n function getAllPools() external view returns (VenusPool[] memory);\n\n /// @notice Get a pool by comptroller address\n function getPoolByComptroller(address comptroller) external view returns (VenusPool memory);\n\n /// @notice Get the address of the VToken contract in the Pool where the underlying token is the provided 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 /// @notice Get the metadata of a Pool by comptroller address\n function getVenusPoolMetadata(address comptroller) external view returns (VenusPoolMetaData memory);\n}\n" + }, + "contracts/Rewards/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\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 { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { TimeManagerV8 } from \"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\";\n\nimport { ExponentialNoError } from \"../ExponentialNoError.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { MaxLoopsLimitHelper } from \"../MaxLoopsLimitHelper.sol\";\nimport { RewardsDistributorStorage } from \"./RewardsDistributorStorage.sol\";\n\n/**\n * @title `RewardsDistributor`\n * @author Venus\n * @notice Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol.\n * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward\n * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool.\n * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward\n * token to be released each slot (block or second) for borrowers and suppliers, which is distributed based on a user’s percentage of the borrows or supplies\n * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting\n * their contributor reward token speed, which similarly allocates a fixed amount of reward token per slot (block or second).\n *\n * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed\n * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized\n * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\n */\ncontract RewardsDistributor is\n ExponentialNoError,\n Ownable2StepUpgradeable,\n AccessControlledV8,\n MaxLoopsLimitHelper,\n RewardsDistributorStorage,\n TimeManagerV8\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice The initial REWARD TOKEN index for a market\n uint224 public constant INITIAL_INDEX = 1e36;\n\n /// @notice Emitted when REWARD TOKEN is distributed to a supplier\n event DistributedSupplierRewardToken(\n VToken indexed vToken,\n address indexed supplier,\n uint256 rewardTokenDelta,\n uint256 rewardTokenTotal,\n uint256 rewardTokenSupplyIndex\n );\n\n /// @notice Emitted when REWARD TOKEN is distributed to a borrower\n event DistributedBorrowerRewardToken(\n VToken indexed vToken,\n address indexed borrower,\n uint256 rewardTokenDelta,\n uint256 rewardTokenTotal,\n uint256 rewardTokenBorrowIndex\n );\n\n /// @notice Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\n event RewardTokenSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /// @notice Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\n event RewardTokenBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /// @notice Emitted when REWARD TOKEN is granted by admin\n event RewardTokenGranted(address indexed recipient, uint256 amount);\n\n /// @notice Emitted when a new REWARD TOKEN speed is set for a contributor\n event ContributorRewardTokenSpeedUpdated(address indexed contributor, uint256 newSpeed);\n\n /// @notice Emitted when a market is initialized\n event MarketInitialized(address indexed vToken);\n\n /// @notice Emitted when a reward token supply index is updated\n event RewardTokenSupplyIndexUpdated(address indexed vToken);\n\n /// @notice Emitted when a reward token borrow index is updated\n event RewardTokenBorrowIndexUpdated(address indexed vToken, Exp marketBorrowIndex);\n\n /// @notice Emitted when a reward for contributor is updated\n event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued);\n\n /// @notice Emitted when a reward token last rewarding block for supply is updated\n event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\n\n /// @notice Emitted when a reward token last rewarding block for borrow is updated\n event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\n\n /// @notice Emitted when a reward token last rewarding timestamp for supply is updated\n event SupplyLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\n\n /// @notice Emitted when a reward token last rewarding timestamp for borrow is updated\n event BorrowLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\n\n modifier onlyComptroller() {\n require(address(comptroller) == msg.sender, \"Only comptroller can call this function\");\n _;\n }\n\n /**\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\n * @param blocksPerYear_ The number of blocks per year\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /**\n * @notice RewardsDistributor initializer\n * @dev Initializes the deployer to owner\n * @param comptroller_ Comptroller to attach the reward distributor to\n * @param rewardToken_ Reward token to distribute\n * @param loopsLimit_ Maximum number of iterations for the loops in this contract\n * @param accessControlManager_ AccessControlManager contract address\n */\n function initialize(\n Comptroller comptroller_,\n IERC20Upgradeable rewardToken_,\n uint256 loopsLimit_,\n address accessControlManager_\n ) external initializer {\n comptroller = comptroller_;\n rewardToken = rewardToken_;\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n\n _setMaxLoopsLimit(loopsLimit_);\n }\n\n /**\n * @notice Initializes the market state for a specific vToken\n * @param vToken The address of the vToken to be initialized\n * @custom:event MarketInitialized emits on success\n * @custom:access Only Comptroller\n */\n function initializeMarket(address vToken) external onlyComptroller {\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n isTimeBased\n ? _initializeMarketTimestampBased(vToken, blockNumberOrTimestamp)\n : _initializeMarketBlockBased(vToken, safe32(blockNumberOrTimestamp, \"block number exceeds 32 bits\"));\n\n emit MarketInitialized(vToken);\n }\n\n /*** Reward Token Distribution ***/\n\n /**\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them\n * Borrowers will begin to accrue after the first interaction with the protocol.\n * @dev This function should only be called when the user has a borrow position in the market\n * (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook)\n * We avoid an external call to check if they are in the market to save gas because this function is called in many places\n * @param vToken The market in which the borrower is interacting\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\n * @param marketBorrowIndex The current global borrow index of vToken\n */\n function distributeBorrowerRewardToken(\n address vToken,\n address borrower,\n Exp memory marketBorrowIndex\n ) external onlyComptroller {\n _distributeBorrowerRewardToken(vToken, borrower, marketBorrowIndex);\n }\n\n function updateRewardTokenSupplyIndex(address vToken) external onlyComptroller {\n _updateRewardTokenSupplyIndex(vToken);\n }\n\n /**\n * @notice Transfer REWARD TOKEN to the recipient\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\n * @param recipient The address of the recipient to transfer REWARD TOKEN to\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\n */\n function grantRewardToken(address recipient, uint256 amount) external onlyOwner {\n uint256 amountLeft = _grantRewardToken(recipient, amount);\n require(amountLeft == 0, \"insufficient rewardToken for grant\");\n emit RewardTokenGranted(recipient, amount);\n }\n\n function updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) external onlyComptroller {\n _updateRewardTokenBorrowIndex(vToken, marketBorrowIndex);\n }\n\n /**\n * @notice Set REWARD TOKEN borrow and supply speeds for the specified markets\n * @param vTokens The markets whose REWARD TOKEN speed to update\n * @param supplySpeeds New supply-side REWARD TOKEN speed for the corresponding market\n * @param borrowSpeeds New borrow-side REWARD TOKEN speed for the corresponding market\n */\n function setRewardTokenSpeeds(\n VToken[] memory vTokens,\n uint256[] memory supplySpeeds,\n uint256[] memory borrowSpeeds\n ) external {\n _checkAccessAllowed(\"setRewardTokenSpeeds(address[],uint256[],uint256[])\");\n uint256 numTokens = vTokens.length;\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \"invalid setRewardTokenSpeeds\");\n\n for (uint256 i; i < numTokens; ++i) {\n _setRewardTokenSpeed(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\n }\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding block for the specified markets, used when contract is block based\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\n * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market\n * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market\n */\n function setLastRewardingBlocks(\n VToken[] calldata vTokens,\n uint32[] calldata supplyLastRewardingBlocks,\n uint32[] calldata borrowLastRewardingBlocks\n ) external {\n _checkAccessAllowed(\"setLastRewardingBlocks(address[],uint32[],uint32[])\");\n require(!isTimeBased, \"Block-based operation only\");\n\n uint256 numTokens = vTokens.length;\n require(\n numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length,\n \"RewardsDistributor::setLastRewardingBlocks invalid input\"\n );\n\n for (uint256 i; i < numTokens; ) {\n _setLastRewardingBlock(vTokens[i], supplyLastRewardingBlocks[i], borrowLastRewardingBlocks[i]);\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding block timestamp for the specified markets, used when contract is time based\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\n * @param supplyLastRewardingBlockTimestamps New supply-side REWARD TOKEN last rewarding block timestamp for the corresponding market\n * @param borrowLastRewardingBlockTimestamps New borrow-side REWARD TOKEN last rewarding block timestamp for the corresponding market\n */\n function setLastRewardingBlockTimestamps(\n VToken[] calldata vTokens,\n uint256[] calldata supplyLastRewardingBlockTimestamps,\n uint256[] calldata borrowLastRewardingBlockTimestamps\n ) external {\n _checkAccessAllowed(\"setLastRewardingBlockTimestamps(address[],uint256[],uint256[])\");\n require(isTimeBased, \"Time-based operation only\");\n\n uint256 numTokens = vTokens.length;\n require(\n numTokens == supplyLastRewardingBlockTimestamps.length &&\n numTokens == borrowLastRewardingBlockTimestamps.length,\n \"RewardsDistributor::setLastRewardingBlockTimestamps invalid input\"\n );\n\n for (uint256 i; i < numTokens; ) {\n _setLastRewardingBlockTimestamp(\n vTokens[i],\n supplyLastRewardingBlockTimestamps[i],\n borrowLastRewardingBlockTimestamps[i]\n );\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Set REWARD TOKEN speed for a single contributor\n * @param contributor The contributor whose REWARD TOKEN speed to update\n * @param rewardTokenSpeed New REWARD TOKEN speed for contributor\n */\n function setContributorRewardTokenSpeed(address contributor, uint256 rewardTokenSpeed) external onlyOwner {\n // note that REWARD TOKEN speed could be set to 0 to halt liquidity rewards for a contributor\n updateContributorRewards(contributor);\n if (rewardTokenSpeed == 0) {\n // release storage\n delete lastContributorBlock[contributor];\n } else {\n lastContributorBlock[contributor] = getBlockNumberOrTimestamp();\n }\n rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed;\n\n emit ContributorRewardTokenSpeedUpdated(contributor, rewardTokenSpeed);\n }\n\n function distributeSupplierRewardToken(address vToken, address supplier) external onlyComptroller {\n _distributeSupplierRewardToken(vToken, supplier);\n }\n\n /**\n * @notice Claim all the rewardToken accrued by holder in all markets\n * @param holder The address to claim REWARD TOKEN for\n */\n function claimRewardToken(address holder) external {\n return claimRewardToken(holder, comptroller.getAllMarkets());\n }\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) external onlyOwner {\n _setMaxLoopsLimit(limit);\n }\n\n /**\n * @notice Calculate additional accrued REWARD TOKEN for a contributor since last accrual\n * @param contributor The address to calculate contributor rewards for\n */\n function updateContributorRewards(address contributor) public {\n uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor];\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, lastContributorBlock[contributor]);\n if (deltaBlocksOrTimestamp > 0 && rewardTokenSpeed > 0) {\n uint256 newAccrued = mul_(deltaBlocksOrTimestamp, rewardTokenSpeed);\n uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued);\n\n rewardTokenAccrued[contributor] = contributorAccrued;\n lastContributorBlock[contributor] = blockNumberOrTimestamp;\n\n emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]);\n }\n }\n\n /**\n * @notice Claim all the rewardToken accrued by holder in the specified markets\n * @param holder The address to claim REWARD TOKEN for\n * @param vTokens The list of markets to claim REWARD TOKEN in\n */\n function claimRewardToken(address holder, VToken[] memory vTokens) public {\n uint256 vTokensCount = vTokens.length;\n\n _ensureMaxLoops(vTokensCount);\n\n for (uint256 i; i < vTokensCount; ++i) {\n VToken vToken = vTokens[i];\n require(comptroller.isMarketListed(vToken), \"market must be listed\");\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\n _distributeBorrowerRewardToken(address(vToken), holder, borrowIndex);\n _updateRewardTokenSupplyIndex(address(vToken));\n _distributeSupplierRewardToken(address(vToken), holder);\n }\n rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]);\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding block for a single market.\n * @param vToken market's whose reward token last rewarding block to be updated\n * @param supplyLastRewardingBlock New supply-side REWARD TOKEN last rewarding block for market\n * @param borrowLastRewardingBlock New borrow-side REWARD TOKEN last rewarding block for market\n */\n function _setLastRewardingBlock(\n VToken vToken,\n uint32 supplyLastRewardingBlock,\n uint32 borrowLastRewardingBlock\n ) internal {\n require(comptroller.isMarketListed(vToken), \"rewardToken market is not listed\");\n\n uint256 blockNumber = getBlockNumberOrTimestamp();\n\n require(supplyLastRewardingBlock > blockNumber, \"setting last rewarding block in the past is not allowed\");\n require(borrowLastRewardingBlock > blockNumber, \"setting last rewarding block in the past is not allowed\");\n\n uint32 currentSupplyLastRewardingBlock = rewardTokenSupplyState[address(vToken)].lastRewardingBlock;\n uint32 currentBorrowLastRewardingBlock = rewardTokenBorrowState[address(vToken)].lastRewardingBlock;\n\n require(\n currentSupplyLastRewardingBlock == 0 || currentSupplyLastRewardingBlock > blockNumber,\n \"this RewardsDistributor is already locked\"\n );\n require(\n currentBorrowLastRewardingBlock == 0 || currentBorrowLastRewardingBlock > blockNumber,\n \"this RewardsDistributor is already locked\"\n );\n\n if (currentSupplyLastRewardingBlock != supplyLastRewardingBlock) {\n rewardTokenSupplyState[address(vToken)].lastRewardingBlock = supplyLastRewardingBlock;\n emit SupplyLastRewardingBlockUpdated(address(vToken), supplyLastRewardingBlock);\n }\n\n if (currentBorrowLastRewardingBlock != borrowLastRewardingBlock) {\n rewardTokenBorrowState[address(vToken)].lastRewardingBlock = borrowLastRewardingBlock;\n emit BorrowLastRewardingBlockUpdated(address(vToken), borrowLastRewardingBlock);\n }\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding timestamp for a single market.\n * @param vToken market's whose reward token last rewarding timestamp to be updated\n * @param supplyLastRewardingBlockTimestamp New supply-side REWARD TOKEN last rewarding timestamp for market\n * @param borrowLastRewardingBlockTimestamp New borrow-side REWARD TOKEN last rewarding timestamp for market\n */\n function _setLastRewardingBlockTimestamp(\n VToken vToken,\n uint256 supplyLastRewardingBlockTimestamp,\n uint256 borrowLastRewardingBlockTimestamp\n ) internal {\n require(comptroller.isMarketListed(vToken), \"rewardToken market is not listed\");\n\n uint256 blockTimestamp = getBlockNumberOrTimestamp();\n\n require(\n supplyLastRewardingBlockTimestamp > blockTimestamp,\n \"setting last rewarding timestamp in the past is not allowed\"\n );\n require(\n borrowLastRewardingBlockTimestamp > blockTimestamp,\n \"setting last rewarding timestamp in the past is not allowed\"\n );\n\n uint256 currentSupplyLastRewardingBlockTimestamp = rewardTokenSupplyStateTimeBased[address(vToken)]\n .lastRewardingTimestamp;\n uint256 currentBorrowLastRewardingBlockTimestamp = rewardTokenBorrowStateTimeBased[address(vToken)]\n .lastRewardingTimestamp;\n\n require(\n currentSupplyLastRewardingBlockTimestamp == 0 || currentSupplyLastRewardingBlockTimestamp > blockTimestamp,\n \"this RewardsDistributor is already locked\"\n );\n require(\n currentBorrowLastRewardingBlockTimestamp == 0 || currentBorrowLastRewardingBlockTimestamp > blockTimestamp,\n \"this RewardsDistributor is already locked\"\n );\n\n if (currentSupplyLastRewardingBlockTimestamp != supplyLastRewardingBlockTimestamp) {\n rewardTokenSupplyStateTimeBased[address(vToken)].lastRewardingTimestamp = supplyLastRewardingBlockTimestamp;\n emit SupplyLastRewardingBlockTimestampUpdated(address(vToken), supplyLastRewardingBlockTimestamp);\n }\n\n if (currentBorrowLastRewardingBlockTimestamp != borrowLastRewardingBlockTimestamp) {\n rewardTokenBorrowStateTimeBased[address(vToken)].lastRewardingTimestamp = borrowLastRewardingBlockTimestamp;\n emit BorrowLastRewardingBlockTimestampUpdated(address(vToken), borrowLastRewardingBlockTimestamp);\n }\n }\n\n /**\n * @notice Set REWARD TOKEN speed for a single market.\n * @param vToken market's whose reward token rate to be updated\n * @param supplySpeed New supply-side REWARD TOKEN speed for market\n * @param borrowSpeed New borrow-side REWARD TOKEN speed for market\n */\n function _setRewardTokenSpeed(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\n require(comptroller.isMarketListed(vToken), \"rewardToken market is not listed\");\n\n if (rewardTokenSupplySpeeds[address(vToken)] != supplySpeed) {\n // Supply speed updated so let's update supply state to ensure that\n // 1. REWARD TOKEN accrued properly for the old speed, and\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\n _updateRewardTokenSupplyIndex(address(vToken));\n\n // Update speed and emit event\n rewardTokenSupplySpeeds[address(vToken)] = supplySpeed;\n emit RewardTokenSupplySpeedUpdated(vToken, supplySpeed);\n }\n\n if (rewardTokenBorrowSpeeds[address(vToken)] != borrowSpeed) {\n // Borrow speed updated so let's update borrow state to ensure that\n // 1. REWARD TOKEN accrued properly for the old speed, and\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\n\n // Update speed and emit event\n rewardTokenBorrowSpeeds[address(vToken)] = borrowSpeed;\n emit RewardTokenBorrowSpeedUpdated(vToken, borrowSpeed);\n }\n }\n\n /**\n * @notice Calculate REWARD TOKEN 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 REWARD TOKEN to\n */\n function _distributeSupplierRewardToken(address vToken, address supplier) internal {\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\n\n uint256 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\n uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier];\n\n // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN\n rewardTokenSupplierIndex[vToken][supplier] = supplyIndex;\n\n if (supplierIndex == 0 && supplyIndex >= INITIAL_INDEX) {\n // Covers the case where users supplied tokens before the market's supply state index was set.\n // Rewards the user with REWARD TOKEN accrued from the start of when supplier rewards were first\n // set for the market.\n supplierIndex = INITIAL_INDEX;\n }\n\n // Calculate change in the cumulative sum of the REWARD TOKEN per vToken accrued\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\n\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\n\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerVToken\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\n\n uint256 supplierAccrued = add_(rewardTokenAccrued[supplier], supplierDelta);\n rewardTokenAccrued[supplier] = supplierAccrued;\n\n emit DistributedSupplierRewardToken(VToken(vToken), supplier, supplierDelta, supplierAccrued, supplyIndex);\n }\n\n /**\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them.\n * @param vToken The market in which the borrower is interacting\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\n * @param marketBorrowIndex The current global borrow index of vToken\n */\n function _distributeBorrowerRewardToken(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\n\n uint256 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\n uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower];\n\n // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN\n rewardTokenBorrowerIndex[vToken][borrower] = borrowIndex;\n\n if (borrowerIndex == 0 && borrowIndex >= INITIAL_INDEX) {\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\n // Rewards the user with REWARD TOKEN accrued from the start of when borrower rewards were first\n // set for the market.\n borrowerIndex = INITIAL_INDEX;\n }\n\n // Calculate change in the cumulative sum of the REWARD TOKEN per borrowed unit accrued\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\n\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\n\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerBorrowedUnit\n if (borrowerAmount != 0) {\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\n\n uint256 borrowerAccrued = add_(rewardTokenAccrued[borrower], borrowerDelta);\n rewardTokenAccrued[borrower] = borrowerAccrued;\n\n emit DistributedBorrowerRewardToken(VToken(vToken), borrower, borrowerDelta, borrowerAccrued, borrowIndex);\n }\n }\n\n /**\n * @notice Transfer REWARD TOKEN to the user.\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all.\n * @param user The address of the user to transfer REWARD TOKEN to\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\n * @return The amount of REWARD TOKEN which was NOT transferred to the user\n */\n function _grantRewardToken(address user, uint256 amount) internal returns (uint256) {\n uint256 rewardTokenRemaining = rewardToken.balanceOf(address(this));\n if (amount > 0 && amount <= rewardTokenRemaining) {\n rewardToken.safeTransfer(user, amount);\n return 0;\n }\n return amount;\n }\n\n /**\n * @notice Accrue REWARD TOKEN to the market by updating the supply index\n * @param vToken The market whose supply index to update\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\n */\n function _updateRewardTokenSupplyIndex(address vToken) internal {\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\n\n uint256 supplySpeed = rewardTokenSupplySpeeds[vToken];\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n if (!isTimeBased) {\n safe32(blockNumberOrTimestamp, \"block number exceeds 32 bits\");\n }\n\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\n ? supplyStateTimeBased.lastRewardingTimestamp\n : uint256(supplyState.lastRewardingBlock);\n\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\n }\n\n uint256 deltaBlocksOrTimestamp = sub_(\n blockNumberOrTimestamp,\n (isTimeBased ? supplyStateTimeBased.timestamp : uint256(supplyState.block))\n );\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\n uint256 supplyTokens = VToken(vToken).totalSupply();\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, supplySpeed);\n Double memory ratio = supplyTokens > 0\n ? fraction(accruedSinceUpdate, supplyTokens)\n : Double({ mantissa: 0 });\n uint224 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\n uint224 index = safe224(\n add_(Double({ mantissa: supplyIndex }), ratio).mantissa,\n \"new index exceeds 224 bits\"\n );\n\n if (isTimeBased) {\n supplyStateTimeBased.index = index;\n supplyStateTimeBased.timestamp = blockNumberOrTimestamp;\n } else {\n supplyState.index = index;\n supplyState.block = uint32(blockNumberOrTimestamp);\n }\n } else if (deltaBlocksOrTimestamp > 0) {\n isTimeBased ? supplyStateTimeBased.timestamp = blockNumberOrTimestamp : supplyState.block = uint32(\n blockNumberOrTimestamp\n );\n }\n\n emit RewardTokenSupplyIndexUpdated(vToken);\n }\n\n /**\n * @notice Accrue REWARD TOKEN to the market by updating the borrow index\n * @param vToken The market whose borrow index to update\n * @param marketBorrowIndex The current global borrow index of vToken\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\n */\n function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\n\n uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken];\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n if (!isTimeBased) {\n safe32(blockNumberOrTimestamp, \"block number exceeds 32 bits\");\n }\n\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\n ? borrowStateTimeBased.lastRewardingTimestamp\n : uint256(borrowState.lastRewardingBlock);\n\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\n }\n\n uint256 deltaBlocksOrTimestamp = sub_(\n blockNumberOrTimestamp,\n (isTimeBased ? borrowStateTimeBased.timestamp : uint256(borrowState.block))\n );\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, borrowSpeed);\n Double memory ratio = borrowAmount > 0\n ? fraction(accruedSinceUpdate, borrowAmount)\n : Double({ mantissa: 0 });\n uint224 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\n uint224 index = safe224(\n add_(Double({ mantissa: borrowIndex }), ratio).mantissa,\n \"new index exceeds 224 bits\"\n );\n\n if (isTimeBased) {\n borrowStateTimeBased.index = index;\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\n } else {\n borrowState.index = index;\n borrowState.block = uint32(blockNumberOrTimestamp);\n }\n } else if (deltaBlocksOrTimestamp > 0) {\n if (isTimeBased) {\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\n } else {\n borrowState.block = uint32(blockNumberOrTimestamp);\n }\n }\n\n emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex);\n }\n\n /**\n * @notice Initializes the market state for a specific vToken called when contract is block-based\n * @param vToken The address of the vToken to be initialized\n * @param blockNumber current block number\n */\n function _initializeMarketBlockBased(address vToken, uint32 blockNumber) internal {\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n RewardToken storage borrowState = rewardTokenBorrowState[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 = INITIAL_INDEX;\n }\n\n if (borrowState.index == 0) {\n // Initialize borrow state index with default value\n borrowState.index = INITIAL_INDEX;\n }\n\n /*\n * Update market state block numbers\n */\n supplyState.block = borrowState.block = blockNumber;\n }\n\n /**\n * @notice Initializes the market state for a specific vToken called when contract is time-based\n * @param vToken The address of the vToken to be initialized\n * @param blockTimestamp current block timestamp\n */\n function _initializeMarketTimestampBased(address vToken, uint256 blockTimestamp) internal {\n TimeBasedRewardToken storage supplyState = rewardTokenSupplyStateTimeBased[vToken];\n TimeBasedRewardToken storage borrowState = rewardTokenBorrowStateTimeBased[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 = INITIAL_INDEX;\n }\n\n if (borrowState.index == 0) {\n // Initialize borrow state index with default value\n borrowState.index = INITIAL_INDEX;\n }\n\n /*\n * Update market state block timestamp\n */\n supplyState.timestamp = borrowState.timestamp = blockTimestamp;\n }\n}\n" + }, + "contracts/Rewards/RewardsDistributorStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\nimport { Comptroller } from \"../Comptroller.sol\";\n\n/**\n * @title RewardsDistributorStorage\n * @author Venus\n * @dev Storage for RewardsDistributor\n */\ncontract RewardsDistributorStorage {\n struct RewardToken {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block number the index was last updated at\n uint32 block;\n // The block number at which to stop rewards\n uint32 lastRewardingBlock;\n }\n\n struct TimeBasedRewardToken {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block timestamp the index was last updated at\n uint256 timestamp;\n // The block timestamp at which to stop rewards\n uint256 lastRewardingTimestamp;\n }\n\n /// @notice The REWARD TOKEN market supply state for each market\n mapping(address => RewardToken) public rewardTokenSupplyState;\n\n /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\n mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex;\n\n /// @notice The REWARD TOKEN accrued but not yet transferred to each user\n mapping(address => uint256) public rewardTokenAccrued;\n\n /// @notice The rate at which rewardToken is distributed to the corresponding borrow market per slot (block or second)\n mapping(address => uint256) public rewardTokenBorrowSpeeds;\n\n /// @notice The rate at which rewardToken is distributed to the corresponding supply market per slot (block or second)\n mapping(address => uint256) public rewardTokenSupplySpeeds;\n\n /// @notice The REWARD TOKEN market borrow state for each market\n mapping(address => RewardToken) public rewardTokenBorrowState;\n\n /// @notice The portion of REWARD TOKEN that each contributor receives per slot (block or second)\n mapping(address => uint256) public rewardTokenContributorSpeeds;\n\n /// @notice Last slot (block or second) at which a contributor's REWARD TOKEN rewards have been allocated\n mapping(address => uint256) public lastContributorBlock;\n\n /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\n mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex;\n\n Comptroller internal comptroller;\n\n IERC20Upgradeable public rewardToken;\n\n /// @notice The REWARD TOKEN market supply state for each market\n mapping(address => TimeBasedRewardToken) public rewardTokenSupplyStateTimeBased;\n\n /// @notice The REWARD TOKEN market borrow state for each market\n mapping(address => TimeBasedRewardToken) public rewardTokenBorrowStateTimeBased;\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[37] private __gap;\n}\n" + }, + "contracts/VToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\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 { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { IProtocolShareReserve } from \"@venusprotocol/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\";\n\nimport { VTokenInterface } from \"./VTokenInterfaces.sol\";\nimport { ComptrollerInterface, ComptrollerViewInterface } from \"./ComptrollerInterface.sol\";\nimport { TokenErrorReporter } from \"./ErrorReporter.sol\";\nimport { InterestRateModel } from \"./InterestRateModel.sol\";\nimport { ExponentialNoError } from \"./ExponentialNoError.sol\";\nimport { TimeManagerV8 } from \"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\";\nimport { ensureNonzeroAddress } from \"./lib/validators.sol\";\n\n/**\n * @title VToken\n * @author Venus\n * @notice Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview,\n * each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of\n * the pool. The main actions a user regularly interacts with in a market are:\n\n- mint/redeem of vTokens;\n- transfer of vTokens;\n- borrow/repay a loan on an underlying asset;\n- liquidate a borrow or liquidate/heal an account.\n\n * A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`.\n * The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted\n * `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken`\n * as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that\n * a user may borrow up to a portion of their collateral determined by the market’s collateral factor. However, if their borrowed amount exceeds an amount\n * calculated using the market’s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also\n * pay off interest accrued on the borrow.\n * \n * The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller`\n * and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a\n * total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`.\n * Both functions settle all of an account’s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of\n * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\n */\ncontract VToken is\n Ownable2StepUpgradeable,\n AccessControlledV8,\n VTokenInterface,\n ExponentialNoError,\n TokenErrorReporter,\n TimeManagerV8\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5%\n\n // Maximum fraction of interest that can be set aside for reserves\n uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18;\n\n // Maximum borrow rate that can ever be applied per slot(block or second)\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n uint256 internal immutable MAX_BORROW_RATE_MANTISSA;\n\n /**\n * Reentrancy Guard **\n */\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 * @param timeBased_ A boolean indicating whether the contract is based on time or block.\n * @param blocksPerYear_ The number of blocks per year\n * @param maxBorrowRateMantissa_ The maximum value of borrowing rate mantissa\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor(\n bool timeBased_,\n uint256 blocksPerYear_,\n uint256 maxBorrowRateMantissa_\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n require(maxBorrowRateMantissa_ <= 1e18, \"Max borrow rate must be <= 1e18\");\n\n MAX_BORROW_RATE_MANTISSA = maxBorrowRateMantissa_;\n _disableInitializers();\n }\n\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_ ERC-20 name of this token\n * @param symbol_ ERC-20 symbol of this token\n * @param decimals_ ERC-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param accessControlManager_ AccessControlManager contract address\n * @param riskManagement Addresses of risk & income related contracts\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\n * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\n */\n function initialize(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address admin_,\n address accessControlManager_,\n RiskManagementInit memory riskManagement,\n uint256 reserveFactorMantissa_\n ) external initializer {\n ensureNonzeroAddress(admin_);\n\n // Initialize the market\n _initialize(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_,\n accessControlManager_,\n riskManagement,\n reserveFactorMantissa_\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 * @return success True if the transfer succeeded, reverts otherwise\n * @custom:event Emits Transfer event on success\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\n * @custom:access Not restricted\n */\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\n _transferTokens(msg.sender, msg.sender, dst, amount);\n return true;\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 success True if the transfer succeeded, reverts otherwise\n * @custom:event Emits Transfer event on success\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\n * @custom:access Not restricted\n */\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\n _transferTokens(msg.sender, src, dst, amount);\n return true;\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 (uint256.max means infinite)\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function approve(address spender, uint256 amount) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n transferAllowances[src][spender] = amount;\n emit Approval(src, spender, amount);\n return true;\n }\n\n /**\n * @notice Increase approval for `spender`\n * @param spender The address of the account which may transfer tokens\n * @param addedValue The number of additional tokens spender can transfer\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function increaseAllowance(address spender, uint256 addedValue) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n uint256 newAllowance = transferAllowances[src][spender];\n newAllowance += addedValue;\n transferAllowances[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n return true;\n }\n\n /**\n * @notice Decreases approval for `spender`\n * @param spender The address of the account which may transfer tokens\n * @param subtractedValue The number of tokens to remove from total approval\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n uint256 currentAllowance = transferAllowances[src][spender];\n require(currentAllowance >= subtractedValue, \"decreased allowance below zero\");\n unchecked {\n currentAllowance -= subtractedValue;\n }\n\n transferAllowances[src][spender] = currentAllowance;\n\n emit Approval(src, spender, currentAllowance);\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 amount The amount of underlying owned by `owner`\n */\n function balanceOfUnderlying(address owner) external override returns (uint256) {\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\n return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\n }\n\n /**\n * @notice Returns the current total borrows plus accrued interest\n * @return totalBorrows The total borrows with interest\n */\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\n accrueInterest();\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 borrowBalance The calculated balance\n */\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\n accrueInterest();\n return _borrowBalanceStored(account);\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function mint(uint256 mintAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _mintFresh(msg.sender, msg.sender, mintAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param minter User whom the supply will be attributed to\n * @param mintAmount The amount of the underlying asset to supply\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when minter address is zero\n */\n function mintBehalf(address minter, uint256 mintAmount) external override nonReentrant returns (uint256) {\n ensureNonzeroAddress(minter);\n\n accrueInterest();\n\n _mintFresh(msg.sender, minter, mintAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\n * @custom:access Not restricted\n */\n function redeem(uint256 redeemTokens) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _redeemFresh(msg.sender, msg.sender, redeemTokens, 0);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function redeemBehalf(address redeemer, uint256 redeemTokens) external override nonReentrant returns (uint256) {\n _ensureSenderIsDelegateOf(redeemer);\n\n accrueInterest();\n\n _redeemFresh(redeemer, msg.sender, redeemTokens, 0);\n return NO_ERROR;\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 receive from redeeming vTokens\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n */\n function redeemUnderlying(uint256 redeemAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _redeemFresh(msg.sender, msg.sender, 0, redeemAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function redeemUnderlyingBehalf(\n address redeemer,\n uint256 redeemAmount\n ) external override nonReentrant returns (uint256) {\n _ensureSenderIsDelegateOf(redeemer);\n\n accrueInterest();\n\n _redeemFresh(redeemer, msg.sender, 0, redeemAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Borrow event; may emit AccrueInterest\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\n * @custom:access Not restricted\n */\n function borrow(uint256 borrowAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _borrowFresh(msg.sender, msg.sender, borrowAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:error DelegateNotApproved is thrown if caller is not approved delegate\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\n * @custom:event Emits Borrow event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function borrowBehalf(address borrower, uint256 borrowAmount) external override returns (uint256) {\n _ensureSenderIsDelegateOf(borrower);\n accrueInterest();\n\n _borrowFresh(borrower, msg.sender, borrowAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function repayBorrow(uint256 repayAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _repayBorrowFresh(msg.sender, msg.sender, repayAmount);\n return NO_ERROR;\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, or type(uint256).max for the full outstanding amount\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _repayBorrowFresh(msg.sender, borrower, repayAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\n * @custom:access Not restricted\n */\n function liquidateBorrow(\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) external override returns (uint256) {\n _liquidateBorrow(msg.sender, borrower, repayAmount, vTokenCollateral, false);\n return NO_ERROR;\n }\n\n /**\n * @notice sets protocol share accumulated from liquidations\n * @dev must be equal or less than liquidation incentive - 1\n * @param newProtocolSeizeShareMantissa_ new protocol share mantissa\n * @custom:event Emits NewProtocolSeizeShare event on success\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:error ProtocolSeizeShareTooBig is thrown when the new seize share is too high\n * @custom:access Controlled by AccessControlManager\n */\n function setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa_) external {\n _checkAccessAllowed(\"setProtocolSeizeShare(uint256)\");\n uint256 liquidationIncentive = ComptrollerViewInterface(address(comptroller)).liquidationIncentiveMantissa();\n if (newProtocolSeizeShareMantissa_ + MANTISSA_ONE > liquidationIncentive) {\n revert ProtocolSeizeShareTooBig();\n }\n\n uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\n protocolSeizeShareMantissa = newProtocolSeizeShareMantissa_;\n emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa_);\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 * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\n * @custom:event Emits NewReserveFactor event; may emit AccrueInterest\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:error SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\n * @custom:access Controlled by AccessControlManager\n */\n function setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant {\n _checkAccessAllowed(\"setReserveFactor(uint256)\");\n\n accrueInterest();\n _setReserveFactorFresh(newReserveFactorMantissa);\n }\n\n /**\n * @notice Accrues interest and reduces reserves by transferring to the protocol reserve contract\n * @dev Gracefully return if reserves already reduced in accrueInterest\n * @param reduceAmount Amount of reduction to reserves\n * @custom:event Emits ReservesReduced event; may emit AccrueInterest\n * @custom:error ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash\n * @custom:error ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\n * @custom:access Not restricted\n */\n function reduceReserves(uint256 reduceAmount) external override nonReentrant {\n accrueInterest();\n if (reduceReservesBlockNumber == getBlockNumberOrTimestamp()) return;\n _reduceReservesFresh(reduceAmount);\n }\n\n /**\n * @notice The sender adds to reserves.\n * @param addAmount The amount of underlying token to add as reserves\n * @custom:event Emits ReservesAdded event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function addReserves(uint256 addAmount) external override nonReentrant {\n accrueInterest();\n _addReservesFresh(addAmount);\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 * @custom:event Emits NewMarketInterestRateModel event; may emit AccrueInterest\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:access Controlled by AccessControlManager\n */\n function setInterestRateModel(InterestRateModel newInterestRateModel) external override {\n _checkAccessAllowed(\"setInterestRateModel(address)\");\n\n accrueInterest();\n _setInterestRateModelFresh(newInterestRateModel);\n }\n\n /**\n * @notice Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially\n * \"forgiving\" the borrower. Healing is a situation that should rarely happen. However, some pools\n * may list risky assets or be configured improperly – we want to still handle such cases gracefully.\n * We assume that Comptroller does the seizing, so this function is only available to Comptroller.\n * @dev This function does not call any Comptroller hooks (like \"healAllowed\"), because we assume\n * the Comptroller does all the necessary checks before calling this function.\n * @param payer account who repays the debt\n * @param borrower account to heal\n * @param repayAmount amount to repay\n * @custom:event Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\n * @custom:error HealBorrowUnauthorized is thrown when the request does not come from Comptroller\n * @custom:access Only Comptroller\n */\n function healBorrow(address payer, address borrower, uint256 repayAmount) external override nonReentrant {\n if (repayAmount != 0) {\n comptroller.preRepayHook(address(this), borrower);\n }\n\n if (msg.sender != address(comptroller)) {\n revert HealBorrowUnauthorized();\n }\n\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n uint256 totalBorrowsNew = totalBorrows;\n\n uint256 actualRepayAmount;\n if (repayAmount != 0) {\n // _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\n // We violate checks-effects-interactions here to account for tokens that take transfer fees\n actualRepayAmount = _doTransferIn(payer, repayAmount);\n totalBorrowsNew = totalBorrowsNew - actualRepayAmount;\n emit RepayBorrow(\n payer,\n borrower,\n actualRepayAmount,\n accountBorrowsPrev - actualRepayAmount,\n totalBorrowsNew\n );\n }\n\n // The transaction will fail if trying to repay too much\n uint256 badDebtDelta = accountBorrowsPrev - actualRepayAmount;\n if (badDebtDelta != 0) {\n uint256 badDebtOld = badDebt;\n uint256 badDebtNew = badDebtOld + badDebtDelta;\n totalBorrowsNew = totalBorrowsNew - badDebtDelta;\n badDebt = badDebtNew;\n\n // We treat healing as \"repayment\", where vToken is the payer\n emit RepayBorrow(address(this), borrower, badDebtDelta, 0, totalBorrowsNew);\n emit BadDebtIncreased(borrower, badDebtDelta, badDebtOld, badDebtNew);\n }\n\n accountBorrows[borrower].principal = 0;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n emit HealBorrow(payer, borrower, repayAmount);\n }\n\n /**\n * @notice The extended version of liquidations, callable only by Comptroller. May skip\n * the close factor check. The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\n * @custom:error ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\n * @custom:access Only Comptroller\n */\n function forceLiquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) external override {\n if (msg.sender != address(comptroller)) {\n revert ForceLiquidateBorrowUnauthorized();\n }\n _liquidateBorrow(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\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 * @custom:event Emits Transfer, ReservesAdded events\n * @custom:error LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:access Not restricted\n */\n function seize(address liquidator, address borrower, uint256 seizeTokens) external override nonReentrant {\n _seize(msg.sender, liquidator, borrower, seizeTokens);\n }\n\n /**\n * @notice Updates bad debt\n * @dev Called only when bad debt is recovered from auction. Updates internal cash balance.\n * @param recoveredAmount_ The amount of bad debt recovered\n * @custom:event Emits BadDebtRecovered event\n * @custom:access Only Shortfall contract\n */\n function badDebtRecovered(uint256 recoveredAmount_) external {\n require(msg.sender == shortfall, \"only shortfall contract can update bad debt\");\n require(recoveredAmount_ <= badDebt, \"more than bad debt recovered from auction\");\n\n uint256 badDebtOld = badDebt;\n uint256 badDebtNew = badDebtOld - recoveredAmount_;\n badDebt = badDebtNew;\n internalCash += recoveredAmount_;\n\n emit BadDebtRecovered(badDebtOld, badDebtNew);\n }\n\n /**\n * @notice Sets protocol share reserve contract address\n * @param protocolShareReserve_ The address of the protocol share reserve contract\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\n * @custom:access Only Governance\n */\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\n _setProtocolShareReserve(protocolShareReserve_);\n }\n\n /**\n * @notice Sets shortfall contract address\n * @param shortfall_ The address of the shortfall contract\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\n * @custom:access Only Governance\n */\n function setShortfallContract(address shortfall_) external onlyOwner {\n _setShortfallContract(shortfall_);\n }\n\n /**\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\n * @param token The address of the ERC-20 token to sweep\n * @custom:access Only Governance\n */\n function sweepToken(IERC20Upgradeable token) external override {\n require(msg.sender == owner(), \"VToken::sweepToken: only admin can sweep tokens\");\n require(address(token) != underlying, \"VToken::sweepToken: can not sweep underlying token\");\n uint256 balance = token.balanceOf(address(this));\n token.safeTransfer(owner(), balance);\n\n emit SweepToken(address(token));\n }\n\n /**\n * @notice Sync internalCash with the actual underlying token balance\n * @dev Used for one-time migration after upgrade to initialize internalCash\n * @custom:event Emits CashSynced\n * @custom:access Controlled by AccessControlManager\n */\n function syncCash() external override nonReentrant {\n _checkAccessAllowed(\"syncCash()\");\n uint256 oldInternalCash = internalCash;\n uint256 actualCash = IERC20Upgradeable(underlying).balanceOf(address(this));\n internalCash = actualCash;\n emit CashSynced(oldInternalCash, actualCash);\n }\n\n /**\n * @notice A public function to set new threshold of slot(block or second) difference after which funds will be sent to the protocol share reserve\n * @param _newReduceReservesBlockOrTimestampDelta slot(block or second) difference value\n * @custom:access Only Governance\n */\n function setReduceReservesBlockDelta(uint256 _newReduceReservesBlockOrTimestampDelta) external {\n _checkAccessAllowed(\"setReduceReservesBlockDelta(uint256)\");\n require(_newReduceReservesBlockOrTimestampDelta > 0, \"Invalid Input\");\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, _newReduceReservesBlockOrTimestampDelta);\n reduceReservesBlockDelta = _newReduceReservesBlockOrTimestampDelta;\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 amount 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 amount 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 error Always NO_ERROR for compatibility with Venus core tooling\n * @return vTokenBalance User's balance of vTokens\n * @return borrowBalance Amount owed in terms of underlying\n * @return exchangeRate Stored exchange rate\n */\n function getAccountSnapshot(\n address account\n )\n external\n view\n override\n returns (uint256 error, uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRate)\n {\n return (NO_ERROR, accountTokens[account], _borrowBalanceStored(account), _exchangeRateStored());\n }\n\n /**\n * @notice Get the internally tracked cash balance of this vToken in the underlying asset\n * @return cash The quantity of underlying asset tracked internally by this contract\n */\n function getCash() external view override returns (uint256) {\n return _getCashPrior();\n }\n\n /**\n * @notice Returns the current per slot(block or second) borrow interest rate for this vToken\n * @return rate The borrow interest rate per slot(block or second), scaled by 1e18\n */\n function borrowRatePerBlock() external view override returns (uint256) {\n return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt);\n }\n\n /**\n * @notice Returns the current per-slot(block or second) supply interest rate for this v\n * @return rate The supply interest rate per slot(block or second), scaled by 1e18\n */\n function supplyRatePerBlock() external view override returns (uint256) {\n return\n interestRateModel.getSupplyRate(\n _getCashPrior(),\n totalBorrows,\n totalReserves,\n reserveFactorMantissa,\n badDebt\n );\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 borrowBalance The calculated balance\n */\n function borrowBalanceStored(address account) external view override returns (uint256) {\n return _borrowBalanceStored(account);\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 exchangeRate Calculated exchange rate scaled by 1e18\n */\n function exchangeRateStored() external view override returns (uint256) {\n return _exchangeRateStored();\n }\n\n /**\n * @notice Accrue interest then return the up-to-date exchange rate\n * @return exchangeRate Calculated exchange rate scaled by 1e18\n */\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\n accrueInterest();\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 slot(block or second)\n * up to the current slot(block or second) and writes new checkpoint to storage and\n * reduce spread reserves to protocol share reserve\n * if currentSlot - reduceReservesBlockNumber >= slotDelta\n * @return Always NO_ERROR\n * @custom:event Emits AccrueInterest event on success\n * @custom:access Not restricted\n */\n function accrueInterest() public virtual override returns (uint256) {\n /* Remember the initial block number or timestamp */\n uint256 currentSlotNumber = getBlockNumberOrTimestamp();\n uint256 accrualSlotNumberPrior = accrualBlockNumber;\n\n /* Short-circuit accumulating 0 interest */\n if (accrualSlotNumberPrior == currentSlotNumber) {\n return NO_ERROR;\n }\n\n /* Read the previous values out of storage */\n uint256 cashPrior = _getCashPrior();\n uint256 borrowsPrior = totalBorrows;\n uint256 reservesPrior = totalReserves;\n uint256 borrowIndexPrior = borrowIndex;\n\n /* Calculate the current borrow interest rate */\n uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt);\n require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, \"borrow rate is absurdly high\");\n\n /* Calculate the number of slots elapsed since the last accrual */\n uint256 slotDelta = currentSlotNumber - accrualSlotNumberPrior;\n\n /*\n * Calculate the interest accumulated into borrows and reserves and the new index:\n * simpleInterestFactor = borrowRate * slotDelta\n * interestAccumulated = simpleInterestFactor * totalBorrows\n * totalBorrowsNew = interestAccumulated + totalBorrows\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\n */\n\n Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), slotDelta);\n uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\n uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;\n uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\n Exp({ mantissa: reserveFactorMantissa }),\n interestAccumulated,\n reservesPrior\n );\n uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the previously calculated values into storage */\n accrualBlockNumber = currentSlotNumber;\n borrowIndex = borrowIndexNew;\n totalBorrows = totalBorrowsNew;\n totalReserves = totalReservesNew;\n\n if (currentSlotNumber - reduceReservesBlockNumber >= reduceReservesBlockDelta) {\n reduceReservesBlockNumber = currentSlotNumber;\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 NO_ERROR;\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 or timestamp\n * @param payer The address of the account which is sending the assets for supply\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 */\n function _mintFresh(address payer, address minter, uint256 mintAmount) internal {\n /* Fail if mint not allowed */\n comptroller.preMintHook(address(this), minter, mintAmount);\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert MintFreshnessCheck();\n }\n\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\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 * `_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 uint256 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 uint256 mintTokens = div_(actualMintAmount, exchangeRate);\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 * And write them into storage\n */\n totalSupply = totalSupply + mintTokens;\n uint256 balanceAfter = accountTokens[minter] + mintTokens;\n accountTokens[minter] = balanceAfter;\n\n /* We emit a Mint event, and a Transfer event */\n emit Mint(minter, actualMintAmount, mintTokens, balanceAfter);\n emit Transfer(address(0), minter, mintTokens);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.mintVerify(address(this), minter, actualMintAmount, mintTokens);\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 Comptroller.updateDelegate)\n * @dev Assumes interest has already been accrued up to the current slot(block or second)\n * @param redeemer The address of the account which is redeeming the tokens\n * @param receiver The receiver of the underlying 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 */\n function _redeemFresh(address redeemer, address receiver, uint256 redeemTokensIn, uint256 redeemAmountIn) internal {\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \"one of redeemTokensIn or redeemAmountIn must be zero\");\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert RedeemFreshnessCheck();\n }\n\n /* exchangeRate = invoke Exchange Rate Stored() */\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\n\n uint256 redeemTokens;\n uint256 redeemAmount;\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 */\n redeemTokens = redeemTokensIn;\n } else {\n /*\n * We get the current exchange rate and calculate the amount to be redeemed:\n * redeemTokens = redeemAmountIn / exchangeRate\n */\n redeemTokens = div_(redeemAmountIn, exchangeRate);\n\n uint256 _redeemAmount = mul_(redeemTokens, exchangeRate);\n if (_redeemAmount != 0 && _redeemAmount != redeemAmountIn) redeemTokens++; // round up\n }\n\n // redeemAmount = exchangeRate * redeemTokens\n redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokens);\n\n // Revert if amount is zero\n if (redeemAmount == 0) {\n revert(\"redeemAmount is zero\");\n }\n\n /* Fail if redeem not allowed */\n comptroller.preRedeemHook(address(this), redeemer, redeemTokens);\n\n /* Fail gracefully if protocol has insufficient cash */\n if (_getCashPrior() - totalReserves < redeemAmount) {\n revert RedeemTransferOutNotPossible();\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We write the previously calculated values into storage.\n * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\n */\n totalSupply = totalSupply - redeemTokens;\n uint256 balanceAfter = accountTokens[redeemer] - redeemTokens;\n accountTokens[redeemer] = balanceAfter;\n\n /*\n * We invoke _doTransferOut for the receiver and the redeemAmount.\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 _doTransferOut(receiver, redeemAmount);\n\n /* We emit a Transfer event, and a Redeem event */\n emit Transfer(redeemer, address(this), redeemTokens);\n emit Redeem(redeemer, redeemAmount, redeemTokens, balanceAfter);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.redeemVerify(address(this), redeemer, redeemAmount, redeemTokens);\n }\n\n /**\n * @notice Users or their delegates borrow assets from the protocol\n * @param borrower User who borrows the assets\n * @param receiver The receiver of the tokens, if called by a delegate\n * @param borrowAmount The amount of the underlying asset to borrow\n */\n function _borrowFresh(address borrower, address receiver, uint256 borrowAmount) internal {\n /* Fail if borrow not allowed */\n comptroller.preBorrowHook(address(this), borrower, borrowAmount);\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert BorrowFreshnessCheck();\n }\n\n /* Fail gracefully if protocol has insufficient underlying cash */\n if (_getCashPrior() - totalReserves < borrowAmount) {\n revert BorrowCashNotAvailable();\n }\n\n /*\n * We calculate the new borrower and total borrow balances, failing on overflow:\n * accountBorrowNew = accountBorrow + borrowAmount\n * totalBorrowsNew = totalBorrows + borrowAmount\n */\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;\n uint256 totalBorrowsNew = totalBorrows + borrowAmount;\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We write the previously calculated values into storage.\n * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\n `*/\n accountBorrows[borrower].principal = accountBorrowsNew;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n /*\n * We invoke _doTransferOut for the receiver and the borrowAmount.\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, accountBorrowsNew, totalBorrowsNew);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\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 underlying tokens being returned, or type(uint256).max for the full outstanding amount\n * @return (uint) the actual repayment amount.\n */\n function _repayBorrowFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256) {\n /* Fail if repayBorrow not allowed */\n comptroller.preRepayHook(address(this), borrower);\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert RepayBorrowFreshnessCheck();\n }\n\n /* We fetch the amount the borrower owes, with accumulated interest */\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n\n uint256 repayAmountFinal = repayAmount >= accountBorrowsPrev ? accountBorrowsPrev : 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 * 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 uint256 actualRepayAmount = _doTransferIn(payer, repayAmountFinal);\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 uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\n uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;\n\n /* We write the previously calculated values into storage */\n accountBorrows[borrower].principal = accountBorrowsNew;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n /* We emit a RepayBorrow event */\n emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.repayBorrowVerify(address(this), payer, borrower, actualRepayAmount, borrowIndex);\n\n return actualRepayAmount;\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n */\n function _liquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) internal nonReentrant {\n accrueInterest();\n\n uint256 error = vTokenCollateral.accrueInterest();\n if (error != NO_ERROR) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\n revert LiquidateAccrueCollateralInterestFailed(error);\n }\n\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\n }\n\n /**\n * @notice The liquidator liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n */\n function _liquidateBorrowFresh(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) internal {\n /* Fail if liquidate not allowed */\n comptroller.preLiquidateHook(\n address(this),\n address(vTokenCollateral),\n borrower,\n repayAmount,\n skipLiquidityCheck\n );\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert LiquidateFreshnessCheck();\n }\n\n /* Verify vTokenCollateral market's slot(block or second) number equals current slot(block or second) number */\n if (vTokenCollateral.accrualBlockNumber() != getBlockNumberOrTimestamp()) {\n revert LiquidateCollateralFreshnessCheck();\n }\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n revert LiquidateLiquidatorIsBorrower();\n }\n\n /* Fail if repayAmount = 0 */\n if (repayAmount == 0) {\n revert LiquidateCloseAmountIsZero();\n }\n\n /* Fail if repayAmount = type(uint256).max */\n if (repayAmount == type(uint256).max) {\n revert LiquidateCloseAmountIsUintMax();\n }\n\n /* Fail if repayBorrow fails */\n uint256 actualRepayAmount = _repayBorrowFresh(liquidator, borrower, repayAmount);\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.liquidateCalculateSeizeTokens(\n address(this),\n address(vTokenCollateral),\n actualRepayAmount\n );\n require(amountSeizeError == 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, call _seize internally to avoid re-entrancy, otherwise make an external call\n if (address(vTokenCollateral) == address(this)) {\n _seize(address(this), liquidator, borrower, seizeTokens);\n } else {\n vTokenCollateral.seize(liquidator, borrower, seizeTokens);\n }\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\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 * It's absolutely critical to use msg.sender as the seizer vToken and not a parameter.\n * @param seizerContract The contract seizing the collateral (either borrowed vToken or Comptroller)\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 */\n function _seize(address seizerContract, address liquidator, address borrower, uint256 seizeTokens) internal {\n /* Fail if seize not allowed */\n comptroller.preSeizeHook(address(this), seizerContract, liquidator, borrower);\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n revert LiquidateSeizeLiquidatorIsBorrower();\n }\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 uint256 liquidationIncentiveMantissa = ComptrollerViewInterface(address(comptroller))\n .liquidationIncentiveMantissa();\n uint256 numerator = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));\n uint256 protocolSeizeTokens = div_(numerator, Exp({ mantissa: liquidationIncentiveMantissa }));\n uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\n uint256 protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the calculated values into storage */\n totalSupply = totalSupply - protocolSeizeTokens;\n accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\n accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\n\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\n _doTransferOut(protocolShareReserve, protocolSeizeAmount);\n\n // Update the pool asset's state in the protocol share reserve for the above transfer.\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\n address(comptroller),\n underlying,\n IProtocolShareReserve.IncomeType.LIQUIDATION\n );\n\n /* Emit a Transfer event */\n emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\n emit ProtocolSeize(borrower, protocolShareReserve, protocolSeizeAmount);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.seizeVerify(address(this), seizerContract, liquidator, borrower, seizeTokens);\n }\n\n function _setComptroller(ComptrollerInterface newComptroller) internal {\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\n /**\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\n * @dev Admin function to set a new reserve factor\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\n */\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal {\n // Verify market's slot(block or second) number equals current slot(block or second) number\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert SetReserveFactorFreshCheck();\n }\n\n // Check newReserveFactor ≤ maxReserveFactor\n if (newReserveFactorMantissa > MAX_RESERVE_FACTOR_MANTISSA) {\n revert SetReserveFactorBoundsCheck();\n }\n\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\n reserveFactorMantissa = newReserveFactorMantissa;\n\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\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 actualAddAmount The actual amount added, excluding the potential token fees\n */\n function _addReservesFresh(uint256 addAmount) internal returns (uint256) {\n // totalReserves + actualAddAmount\n uint256 totalReservesNew;\n uint256 actualAddAmount;\n\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert AddReservesFactorFreshCheck(actualAddAmount);\n }\n\n actualAddAmount = _doTransferIn(msg.sender, addAmount);\n totalReservesNew = totalReserves + actualAddAmount;\n totalReserves = totalReservesNew;\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\n\n return actualAddAmount;\n }\n\n /**\n * @notice Reduces reserves by transferring to the protocol reserve contract\n * @dev Requires fresh interest accrual\n * @param reduceAmount Amount of reduction to reserves\n */\n function _reduceReservesFresh(uint256 reduceAmount) internal {\n if (reduceAmount == 0) {\n return;\n }\n // totalReserves - reduceAmount\n uint256 totalReservesNew;\n\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert ReduceReservesFreshCheck();\n }\n\n // Fail gracefully if protocol has insufficient underlying cash\n if (_getCashPrior() < reduceAmount) {\n revert ReduceReservesCashNotAvailable();\n }\n\n // Check reduceAmount ≤ reserves[n] (totalReserves)\n if (reduceAmount > totalReserves) {\n revert ReduceReservesCashValidation();\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 // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\n _doTransferOut(protocolShareReserve, reduceAmount);\n\n // Update the pool asset's state in the protocol share reserve for the above transfer.\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\n address(comptroller),\n underlying,\n IProtocolShareReserve.IncomeType.SPREAD\n );\n\n emit SpreadReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\n }\n\n /**\n * @notice updates the interest rate model (*requires fresh interest accrual)\n * @dev Admin function to update the interest rate model\n * @param newInterestRateModel the new interest rate model to use\n */\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal {\n // Used to store old model for use in the event that is emitted on success\n InterestRateModel oldInterestRateModel;\n\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert SetInterestRateModelFreshCheck();\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\n /**\n * Safe Token **\n */\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 returns (uint256) {\n IERC20Upgradeable token = IERC20Upgradeable(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 * @param to Receiver of the underlying tokens\n * @param amount Amount of underlying to transfer\n */\n function _doTransferOut(address to, uint256 amount) internal virtual {\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\n internalCash -= amount;\n token.safeTransfer(to, amount);\n }\n\n /**\n * @notice Transfer `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 */\n function _transferTokens(address spender, address src, address dst, uint256 tokens) internal {\n /* Fail if transfer not allowed */\n comptroller.preTransferHook(address(this), src, dst, tokens);\n\n /* Do not allow self-transfers */\n if (src == dst) {\n revert TransferNotAllowed();\n }\n\n /* Get the allowance, infinite for the account owner */\n uint256 startingAllowance;\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 uint256 allowanceNew = startingAllowance - tokens;\n uint256 srcTokensNew = accountTokens[src] - tokens;\n uint256 dstTokensNew = accountTokens[dst] + tokens;\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n\n accountTokens[src] = srcTokensNew;\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\n /**\n * @notice Initialize the 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_ ERC-20 name of this token\n * @param symbol_ ERC-20 symbol of this token\n * @param decimals_ ERC-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param accessControlManager_ AccessControlManager contract address\n * @param riskManagement Addresses of risk & income related contracts\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\n */\n function _initialize(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address admin_,\n address accessControlManager_,\n RiskManagementInit memory riskManagement,\n uint256 reserveFactorMantissa_\n ) internal onlyInitializing {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\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 _setComptroller(comptroller_);\n\n // Initialize slot(block or second) number and borrow index (slot(block or second) number mocks depend on comptroller being set)\n accrualBlockNumber = getBlockNumberOrTimestamp();\n borrowIndex = MANTISSA_ONE;\n\n // Set the interest rate model (depends on slot(block or second) number / borrow index)\n _setInterestRateModelFresh(interestRateModel_);\n\n _setReserveFactorFresh(reserveFactorMantissa_);\n\n name = name_;\n symbol = symbol_;\n decimals = decimals_;\n _setShortfallContract(riskManagement.shortfall);\n _setProtocolShareReserve(riskManagement.protocolShareReserve);\n protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA;\n\n // Set underlying and sanity check it\n underlying = underlying_;\n IERC20Upgradeable(underlying).totalSupply();\n\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\n _notEntered = true;\n _transferOwnership(admin_);\n }\n\n function _setShortfallContract(address shortfall_) internal {\n ensureNonzeroAddress(shortfall_);\n address oldShortfall = shortfall;\n shortfall = shortfall_;\n emit NewShortfallContract(oldShortfall, shortfall_);\n }\n\n function _setProtocolShareReserve(address payable protocolShareReserve_) internal {\n ensureNonzeroAddress(protocolShareReserve_);\n address oldProtocolShareReserve = address(protocolShareReserve);\n protocolShareReserve = protocolShareReserve_;\n emit NewProtocolShareReserve(oldProtocolShareReserve, address(protocolShareReserve_));\n }\n\n function _ensureSenderIsDelegateOf(address user) internal view {\n if (!ComptrollerViewInterface(address(comptroller)).approvedDelegates(user, msg.sender)) {\n revert DelegateNotApproved();\n }\n }\n\n /**\n * @notice Gets the internally tracked cash balance of this market\n * @dev Returns the internalCash state variable, which is updated on transfers in/out\n * @return The quantity of underlying tokens tracked internally by this contract\n */\n function _getCashPrior() internal view virtual returns (uint256) {\n return internalCash;\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 borrowBalance the calculated balance\n */\n function _borrowBalanceStored(address account) internal view returns (uint256) {\n /* Get borrowBalance and borrowIndex */\n BorrowSnapshot memory 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 0;\n }\n\n /* Calculate new borrow balance using the interest index:\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\n */\n uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;\n\n return principalTimesIndex / borrowSnapshot.interestIndex;\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 exchangeRate Calculated exchange rate scaled by 1e18\n */\n function _exchangeRateStored() internal view virtual returns (uint256) {\n uint256 _totalSupply = totalSupply;\n if (_totalSupply == 0) {\n /*\n * If there are no tokens minted:\n * exchangeRate = initialExchangeRate\n */\n return initialExchangeRateMantissa;\n }\n /*\n * Otherwise:\n * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply\n */\n uint256 totalCash = _getCashPrior();\n uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;\n uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply;\n\n return exchangeRate;\n }\n}\n" + }, + "contracts/VTokenInterfaces.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\nimport { ComptrollerInterface } from \"./ComptrollerInterface.sol\";\nimport { InterestRateModel } from \"./InterestRateModel.sol\";\n\n/**\n * @title VTokenStorage\n * @author Venus\n * @notice Storage layout used by the `VToken` contract\n */\n// solhint-disable-next-line max-states-count\ncontract VTokenStorage {\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 uint256 principal;\n uint256 interestIndex;\n }\n\n /**\n * @dev Guard variable for re-entrancy checks\n */\n bool internal _notEntered;\n\n /**\n * @notice Underlying asset for this VToken\n */\n address public underlying;\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 Protocol share Reserve contract address\n */\n address payable public protocolShareReserve;\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 InterestRateModel public interestRateModel;\n\n // Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\n uint256 internal initialExchangeRateMantissa;\n\n /**\n * @notice Fraction of interest currently set aside for reserves\n */\n uint256 public reserveFactorMantissa;\n\n /**\n * @notice Slot(block or second) number that interest was last accrued at\n */\n uint256 public accrualBlockNumber;\n\n /**\n * @notice Accumulator of the total earned interest rate since the opening of the market\n */\n uint256 public borrowIndex;\n\n /**\n * @notice Total amount of outstanding borrows of the underlying in this market\n */\n uint256 public totalBorrows;\n\n /**\n * @notice Total amount of reserves of the underlying held in this market\n */\n uint256 public totalReserves;\n\n /**\n * @notice Total number of tokens in circulation\n */\n uint256 public totalSupply;\n\n /**\n * @notice Total bad debt of the market\n */\n uint256 public badDebt;\n\n // Official record of token balances for each account\n mapping(address => uint256) internal accountTokens;\n\n // Approved token transfer amounts on behalf of others\n mapping(address => mapping(address => uint256)) internal transferAllowances;\n\n // Mapping of account addresses to outstanding borrow balances\n mapping(address => BorrowSnapshot) internal accountBorrows;\n\n /**\n * @notice Share of seized collateral that is added to reserves\n */\n uint256 public protocolSeizeShareMantissa;\n\n /**\n * @notice Storage of Shortfall contract address\n */\n address public shortfall;\n\n /**\n * @notice delta slot (block or second) after which reserves will be reduced\n */\n uint256 public reduceReservesBlockDelta;\n\n /**\n * @notice last slot (block or second) number at which reserves were reduced\n */\n uint256 public reduceReservesBlockNumber;\n\n /**\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\n * @dev Updated via _doTransferIn(), _doTransferOut(), syncCash(), and badDebtRecovered(). Must be initialized via syncCash() 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[47] private __gap;\n}\n\n/**\n * @title VTokenInterface\n * @author Venus\n * @notice Interface implemented by the `VToken` contract\n */\nabstract contract VTokenInterface is VTokenStorage {\n struct RiskManagementInit {\n address shortfall;\n address payable protocolShareReserve;\n }\n\n /*** Market Events ***/\n\n /**\n * @notice Event emitted when interest is accrued\n */\n event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\n\n /**\n * @notice Event emitted when tokens are minted\n */\n event Mint(address indexed minter, uint256 mintAmount, uint256 mintTokens, uint256 accountBalance);\n\n /**\n * @notice Event emitted when tokens are redeemed\n */\n event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens, uint256 accountBalance);\n\n /**\n * @notice Event emitted when underlying is borrowed\n */\n event Borrow(address indexed borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\n\n /**\n * @notice Event emitted when a borrow is repaid\n */\n event RepayBorrow(\n address indexed payer,\n address indexed borrower,\n uint256 repayAmount,\n uint256 accountBorrows,\n uint256 totalBorrows\n );\n\n /**\n * @notice Event emitted when bad debt is accumulated on a market\n * @param borrower borrower to \"forgive\"\n * @param badDebtDelta amount of new bad debt recorded\n * @param badDebtOld previous bad debt value\n * @param badDebtNew new bad debt value\n */\n event BadDebtIncreased(address indexed borrower, uint256 badDebtDelta, uint256 badDebtOld, uint256 badDebtNew);\n\n /**\n * @notice Event emitted when bad debt is recovered via an auction\n * @param badDebtOld previous bad debt value\n * @param badDebtNew new bad debt value\n */\n event BadDebtRecovered(uint256 badDebtOld, uint256 badDebtNew);\n\n /**\n * @notice Event emitted when a borrow is liquidated\n */\n event LiquidateBorrow(\n address indexed liquidator,\n address indexed borrower,\n uint256 repayAmount,\n address indexed vTokenCollateral,\n uint256 seizeTokens\n );\n\n /*** Admin Events ***/\n\n /**\n * @notice Event emitted when comptroller is changed\n */\n event NewComptroller(ComptrollerInterface indexed oldComptroller, ComptrollerInterface indexed newComptroller);\n\n /**\n * @notice Event emitted when shortfall contract address is changed\n */\n event NewShortfallContract(address indexed oldShortfall, address indexed newShortfall);\n\n /**\n * @notice Event emitted when protocol share reserve contract address is changed\n */\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\n\n /**\n * @notice Event emitted when interestRateModel is changed\n */\n event NewMarketInterestRateModel(\n InterestRateModel indexed oldInterestRateModel,\n InterestRateModel indexed newInterestRateModel\n );\n\n /**\n * @notice Event emitted when protocol seize share is changed\n */\n event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\n\n /**\n * @notice Event emitted when the reserve factor is changed\n */\n event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\n\n /**\n * @notice Event emitted when the reserves are added\n */\n event ReservesAdded(address indexed benefactor, uint256 addAmount, uint256 newTotalReserves);\n\n /**\n * @notice Event emitted when the spread reserves are reduced\n */\n event SpreadReservesReduced(address indexed protocolShareReserve, uint256 reduceAmount, uint256 newTotalReserves);\n\n /**\n * @notice EIP20 Transfer event\n */\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n /**\n * @notice EIP20 Approval event\n */\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /**\n * @notice Event emitted when healing the borrow\n */\n event HealBorrow(address indexed payer, address indexed borrower, uint256 repayAmount);\n\n /**\n * @notice Event emitted when tokens are swept\n */\n event SweepToken(address indexed token);\n\n /**\n * @notice Event emitted when reduce reserves slot (block or second) delta is changed\n */\n event NewReduceReservesBlockDelta(\n uint256 oldReduceReservesBlockOrTimestampDelta,\n uint256 newReduceReservesBlockOrTimestampDelta\n );\n\n /**\n * @notice Event emitted when liquidation reserves are reduced\n */\n event ProtocolSeize(address indexed from, address indexed to, uint256 amount);\n\n /**\n * @notice Event emitted when internalCash is synced with actual token balance\n */\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\n\n /*** User Interface ***/\n\n function mint(uint256 mintAmount) external virtual returns (uint256);\n\n function mintBehalf(address minter, uint256 mintAllowed) external virtual returns (uint256);\n\n function redeem(uint256 redeemTokens) external virtual returns (uint256);\n\n function redeemBehalf(address redeemer, uint256 redeemTokens) external virtual returns (uint256);\n\n function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);\n\n function redeemUnderlyingBehalf(address redeemer, uint256 redeemAmount) external virtual returns (uint256);\n\n function borrow(uint256 borrowAmount) external virtual returns (uint256);\n\n function borrowBehalf(address borrwwer, uint256 borrowAmount) external virtual returns (uint256);\n\n function repayBorrow(uint256 repayAmount) external virtual returns (uint256);\n\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);\n\n function liquidateBorrow(\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) external virtual returns (uint256);\n\n function healBorrow(address payer, address borrower, uint256 repayAmount) external virtual;\n\n function forceLiquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipCloseFactorCheck\n ) external virtual;\n\n function seize(address liquidator, address borrower, uint256 seizeTokens) external virtual;\n\n function transfer(address dst, uint256 amount) external virtual returns (bool);\n\n function transferFrom(address src, address dst, uint256 amount) external virtual returns (bool);\n\n function accrueInterest() external virtual returns (uint256);\n\n function sweepToken(IERC20Upgradeable token) external virtual;\n\n /*** Admin Functions ***/\n\n function setReserveFactor(uint256 newReserveFactorMantissa) external virtual;\n\n function reduceReserves(uint256 reduceAmount) external virtual;\n\n function exchangeRateCurrent() external virtual returns (uint256);\n\n function borrowBalanceCurrent(address account) external virtual returns (uint256);\n\n function setInterestRateModel(InterestRateModel newInterestRateModel) external virtual;\n\n function addReserves(uint256 addAmount) external virtual;\n\n function syncCash() external virtual;\n\n function totalBorrowsCurrent() external virtual returns (uint256);\n\n function balanceOfUnderlying(address owner) external virtual returns (uint256);\n\n function approve(address spender, uint256 amount) external virtual returns (bool);\n\n function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool);\n\n function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool);\n\n function allowance(address owner, address spender) external view virtual returns (uint256);\n\n function balanceOf(address owner) external view virtual returns (uint256);\n\n function getAccountSnapshot(address account) external view virtual returns (uint256, uint256, uint256, uint256);\n\n function borrowRatePerBlock() external view virtual returns (uint256);\n\n function supplyRatePerBlock() external view virtual returns (uint256);\n\n function borrowBalanceStored(address account) external view virtual returns (uint256);\n\n function exchangeRateStored() external view virtual returns (uint256);\n\n function getCash() external view virtual returns (uint256);\n\n /**\n * @notice Indicator that this is a VToken contract (for inspection)\n * @return Always true\n */\n function isVToken() external pure virtual returns (bool) {\n return true;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200, + "details": { + "yul": true + } + }, + "evmVersion": "paris", + "outputSelection": { + "*": { + "*": [ + "storageLayout", + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} diff --git a/deployments/opmainnet_addresses.json b/deployments/opmainnet_addresses.json index 91dd1509c..0ba75afab 100644 --- a/deployments/opmainnet_addresses.json +++ b/deployments/opmainnet_addresses.json @@ -10,7 +10,7 @@ "JumpRateModelV2_base0bps_slope350bps_jump25000bps_kink8000bps_timeBased": "0x365B3a4dA73D000E06d250F86e4Fb1d7a2F63e57", "JumpRateModelV2_base0bps_slope687bps_jump25000bps_kink8000bps_timeBased": "0x8AB36EBdBd4873bd1613Cc77D21A0bE29a34EFD9", "NativeTokenGateway_vWETH_Core": "0x5B1b7465cfDE450e267b562792b434277434413c", - "PoolLens": "0x142160A2E699e33af337741f157D96aAd6bC72aA", + "PoolLens": "0x10f849a22f16DF086EF44B97ef8DF8D78B8Ac74E", "PoolRegistry": "0x147780799840d541C1d7c998F0cbA996d11D62bb", "PoolRegistry_Implementation": "0x6a166fcd39BA9c4ACc1b98eC45Adcdc4926E7967", "PoolRegistry_Proxy": "0x147780799840d541C1d7c998F0cbA996d11D62bb", diff --git a/deployments/unichainmainnet.json b/deployments/unichainmainnet.json index 088135298..1dad34cb6 100644 --- a/deployments/unichainmainnet.json +++ b/deployments/unichainmainnet.json @@ -5732,7 +5732,7 @@ ] }, "PoolLens": { - "address": "0xe192aeDBDBd235DBF33Ea1444f2B908Ea3E78419", + "address": "0x667fcCdAdF4fAFe22DbE80440A43d180f64d469a", "abi": [ { "inputs": [ @@ -5745,6 +5745,11 @@ "internalType": "uint256", "name": "blocksPerYear_", "type": "uint256" + }, + { + "internalType": "address", + "name": "corePoolComptroller_", + "type": "address" } ], "stateMutability": "nonpayable", @@ -5773,6 +5778,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "corePoolComptroller", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { diff --git a/deployments/unichainmainnet/PoolLens.json b/deployments/unichainmainnet/PoolLens.json index 9867f2158..19b3b533b 100644 --- a/deployments/unichainmainnet/PoolLens.json +++ b/deployments/unichainmainnet/PoolLens.json @@ -1,5 +1,5 @@ { - "address": "0xe192aeDBDBd235DBF33Ea1444f2B908Ea3E78419", + "address": "0x667fcCdAdF4fAFe22DbE80440A43d180f64d469a", "abi": [ { "inputs": [ @@ -12,6 +12,11 @@ "internalType": "uint256", "name": "blocksPerYear_", "type": "uint256" + }, + { + "internalType": "address", + "name": "corePoolComptroller_", + "type": "address" } ], "stateMutability": "nonpayable", @@ -40,6 +45,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "corePoolComptroller", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -1168,28 +1186,28 @@ "type": "function" } ], - "transactionHash": "0xcc976e82c80224391fb76a9f7bddadf2713b234009c22e57b6192701f4623188", + "transactionHash": "0x5f52f0e496c7e1910755338e7c6b5c10b175c027a710fa057df541da8aba2aa9", "receipt": { "to": null, - "from": "0x92054EdBb53eCC4f2A1787e92f479CE10392A658", - "contractAddress": "0xe192aeDBDBd235DBF33Ea1444f2B908Ea3E78419", - "transactionIndex": 1, - "gasUsed": "3524220", + "from": "0x916fEb0881f0ae2dbFA6F3e3088200075F197458", + "contractAddress": "0x667fcCdAdF4fAFe22DbE80440A43d180f64d469a", + "transactionIndex": 3, + "gasUsed": "3593126", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x1c7c16079cacfb758871bcbf08397a1d54f9aa90d09924ce04c72094c89ceffa", - "transactionHash": "0xcc976e82c80224391fb76a9f7bddadf2713b234009c22e57b6192701f4623188", + "blockHash": "0xf3c3d9413f0543bd06d35f7541bf57c153be03db8e6e2b22ed1fd75428993c01", + "transactionHash": "0x5f52f0e496c7e1910755338e7c6b5c10b175c027a710fa057df541da8aba2aa9", "logs": [], - "blockNumber": 8116995, - "cumulativeGasUsed": "3568146", + "blockNumber": 44213253, + "cumulativeGasUsed": "3755506", "status": 1, "byzantium": true }, - "args": [true, 0], - "numDeployments": 1, - "solcInputHash": "bf6504e8406cd8d7763a8de7cdacad9c", - "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"timeBased_\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"blocksPerYear_\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidBlocksPerYear\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTimeBasedConfiguration\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"blocksOrSecondsPerYear\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"}],\"name\":\"getAllPools\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockNumberOrTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getPendingRewards\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"distributorAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"rewardTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalRewards\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.PendingReward[]\",\"name\":\"pendingRewards\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.RewardSummary[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getPoolBadDebt\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalBadDebtUsd\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"badDebtUsd\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.BadDebt[]\",\"name\":\"badDebts\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.BadDebtSummary\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolByComptroller\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolRegistryInterface.VenusPool\",\"name\":\"venusPool\",\"type\":\"tuple\"}],\"name\":\"getPoolDataFromVenusPool\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getPoolsSupportedByAsset\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getVTokenForAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isTimeBased\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"vTokenBalances\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalanceCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balanceOfUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenAllowance\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenBalances\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"vTokenBalancesAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalanceCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balanceOfUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenAllowance\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenBalances[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"vTokenMetadata\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"vTokenMetadataAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"vTokenUnderlyingPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"underlyingPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenUnderlyingPrice\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"vTokenUnderlyingPriceAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"underlyingPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenUnderlyingPrice[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"params\":{\"blocksPerYear_\":\"The number of blocks per year\",\"timeBased_\":\"A boolean indicating whether the contract is based on time or block.\"}},\"getAllPools(address)\":{\"details\":\"This function is not designed to be called in a transaction: it is too gas-intensive\",\"params\":{\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"Arrays of all Venus pools' data\"}},\"getBlockNumberOrTimestamp()\":{\"details\":\"Function to simply retrieve block number or block timestamp\",\"returns\":{\"_0\":\"Current block number or block timestamp\"}},\"getPendingRewards(address,address)\":{\"params\":{\"account\":\"The user account.\",\"comptrollerAddress\":\"address\"},\"returns\":{\"_0\":\"Pending rewards array\"}},\"getPoolBadDebt(address)\":{\"params\":{\"comptrollerAddress\":\"Address of the comptroller\"},\"returns\":{\"_0\":\"badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and a break down of bad debt by market\"}},\"getPoolByComptroller(address,address)\":{\"params\":{\"comptroller\":\"The Comptroller implementation address\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"PoolData structure containing the details of the pool\"}},\"getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))\":{\"params\":{\"poolRegistryAddress\":\"Address of the PoolRegistry\",\"venusPool\":\"The VenusPool Object from PoolRegistry\"},\"returns\":{\"_0\":\"Enriched PoolData\"}},\"getPoolsSupportedByAsset(address,address)\":{\"params\":{\"asset\":\"The underlying asset of vToken\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"A list of Comptroller contracts\"}},\"getVTokenForAsset(address,address,address)\":{\"params\":{\"asset\":\"The underlyingAsset of VToken\",\"comptroller\":\"The pool comptroller\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"Address of the vToken\"}},\"vTokenBalances(address,address)\":{\"params\":{\"account\":\"The user Account\",\"vToken\":\"vToken address\"},\"returns\":{\"_0\":\"A struct containing the balances data\"}},\"vTokenBalancesAll(address[],address)\":{\"params\":{\"account\":\"The user Account\",\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"A list of structs containing balances data\"}},\"vTokenMetadata(address)\":{\"params\":{\"vToken\":\"The address of vToken\"},\"returns\":{\"_0\":\"VTokenMetadata struct\"}},\"vTokenMetadataAll(address[])\":{\"params\":{\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"An array of VTokenMetadata structs\"}},\"vTokenUnderlyingPrice(address)\":{\"params\":{\"vToken\":\"vToken address\"},\"returns\":{\"_0\":\"The price data for each asset\"}},\"vTokenUnderlyingPriceAll(address[])\":{\"params\":{\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"An array containing the price data for each asset\"}}},\"title\":\"PoolLens\",\"version\":1},\"userdoc\":{\"errors\":{\"InvalidBlocksPerYear()\":[{\"notice\":\"Thrown when blocks per year is invalid\"}],\"InvalidTimeBasedConfiguration()\":[{\"notice\":\"Thrown when time based but blocks per year is provided\"}]},\"kind\":\"user\",\"methods\":{\"blocksOrSecondsPerYear()\":{\"notice\":\"Stores blocksPerYear if isTimeBased is true else secondsPerYear is stored\"},\"getAllPools(address)\":{\"notice\":\"Queries all pools with addtional details for each of them\"},\"getPendingRewards(address,address)\":{\"notice\":\"Returns the pending rewards for a user for a given pool.\"},\"getPoolBadDebt(address)\":{\"notice\":\"Returns a summary of a pool's bad debt broken down by market\"},\"getPoolByComptroller(address,address)\":{\"notice\":\"Queries the details of a pool identified by Comptroller address\"},\"getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))\":{\"notice\":\"Queries additional information for the pool\"},\"getPoolsSupportedByAsset(address,address)\":{\"notice\":\"Returns all pools that support the specified underlying asset\"},\"getVTokenForAsset(address,address,address)\":{\"notice\":\"Returns vToken holding the specified underlying asset in the specified pool\"},\"isTimeBased()\":{\"notice\":\"Acknowledges if a contract is time based or not\"},\"vTokenBalances(address,address)\":{\"notice\":\"Queries the user's supply/borrow balances in the specified vToken\"},\"vTokenBalancesAll(address[],address)\":{\"notice\":\"Queries the user's supply/borrow balances in vTokens\"},\"vTokenMetadata(address)\":{\"notice\":\"Returns the metadata of VToken\"},\"vTokenMetadataAll(address[])\":{\"notice\":\"Returns the metadata of all VTokens\"},\"vTokenUnderlyingPrice(address)\":{\"notice\":\"Returns the price data for the underlying asset of the specified vToken\"},\"vTokenUnderlyingPriceAll(address[])\":{\"notice\":\"Returns the price data for the underlying assets of the specified vTokens\"}},\"notice\":\"The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be looked up for specific pools and markets: - the vToken balance of a given user; - the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address; - the vToken address in a pool for a given asset; - a list of all pools that support an asset; - the underlying asset price of a vToken; - the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Lens/PoolLens.sol\":\"PoolLens\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"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\",\"keccak256\":\"0x9140dabc466abab21b48b72dbda26736b1183a310d0e677d3719d201df026510\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x359a1ab89b46b9aba7bcad3fb651924baf4893d15153049b9976b0fc9be1358e\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x07e881de3b9f6d2c07909f193f24b96c7fe4ea60013260f3f25aecd8bab3c2f8\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x75097e35253e7fb282ee4d7f27a80eaacfa759923185bf17302a89cbc059c5ef\",\"license\":\"MIT\"},\"@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\"},\"@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 private _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\",\"keccak256\":\"0x0dcf283925f4dddc23ca0ee71d2cb96a9dd6e4cf08061b69fde1697ea39dc514\",\"license\":\"BSD-3-Clause\"},\"@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/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface IProtocolShareReserve {\\n /// @notice it represents the type of vToken income\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION\\n }\\n\\n function updateAssetsState(\\n address comptroller,\\n address asset,\\n IncomeType incomeType\\n ) external;\\n}\\n\",\"keccak256\":\"0x5fddc5b63fdd850b3b5c83576cda50dcb27a205dbb1a23af17d9da0d9f04fa0a\",\"license\":\"BSD-3-Clause\"},\"@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\",\"keccak256\":\"0x57a2bbb9b8e02b1c0a5c0e305fef1328a22db56c3d4b148c362010a6e767243c\",\"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\"},\"@venusprotocol/venus-protocol/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\",\"keccak256\":\"0xd112f60183416ad796093b4a83a80ddc1b8b655965f02ae55ca82e2a0c68f97d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/venus-protocol/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\",\"keccak256\":\"0x5285c875114db2ea2be0b81b65722d5761806217022db733323c4e03365a95e7\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IPrime } from \\\"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\\\";\\n\\nimport { ComptrollerInterface, Action } from \\\"./ComptrollerInterface.sol\\\";\\nimport { ComptrollerStorage } from \\\"./ComptrollerStorage.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"./MaxLoopsLimitHelper.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title Comptroller\\n * @author Venus\\n * @notice The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating,\\n * and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts\\n * with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows\\n * or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing\\n * liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow,\\n * as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the\\n * markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market\\u2019s corresponding liquidation threshold,\\n * the borrow is eligible for liquidation.\\n *\\n * The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed\\n * the `minLiquidatableCollateral` for the `Comptroller`:\\n *\\n * - `healAccount()`: This function is called to seize all of a given user\\u2019s collateral, requiring the `msg.sender` repay a certain percentage\\n * of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed\\n * 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt\\n * and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool.\\n * - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation\\n * incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic\\n * verifying that the repay amount does not exceed the close factor.\\n */\\ncontract Comptroller is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n ComptrollerStorage,\\n ComptrollerInterface,\\n ExponentialNoError,\\n MaxLoopsLimitHelper\\n{\\n // PoolRegistry, immutable to save on gas\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable poolRegistry;\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(VToken indexed vToken, address indexed account);\\n\\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(VToken vToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa);\\n\\n /// @notice Emitted when liquidation threshold is changed by admin\\n event NewLiquidationThreshold(\\n VToken vToken,\\n uint256 oldLiquidationThresholdMantissa,\\n uint256 newLiquidationThresholdMantissa\\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 an action is paused on a market\\n event ActionPausedMarket(VToken vToken, Action action, bool pauseState);\\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 the collateral threshold (in USD) for non-batch liquidations is changed\\n event NewMinLiquidatableCollateral(uint256 oldMinLiquidatableCollateral, uint256 newMinLiquidatableCollateral);\\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 a rewards distributor is added\\n event NewRewardsDistributor(address indexed rewardsDistributor, address indexed rewardToken);\\n\\n /// @notice Emitted when a market is supported\\n event MarketSupported(VToken vToken);\\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 a market\\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\\n\\n /// @notice Emitted when a market is unlisted\\n event MarketUnlisted(address indexed vToken);\\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 Thrown when collateral factor exceeds the upper bound\\n error InvalidCollateralFactor();\\n\\n /// @notice Thrown when liquidation threshold exceeds the collateral factor\\n error InvalidLiquidationThreshold();\\n\\n /// @notice Thrown when the action is only available to specific sender, but the real sender was different\\n error UnexpectedSender(address expectedSender, address actualSender);\\n\\n /// @notice Thrown when the oracle returns an invalid price for some asset\\n error PriceError(address vToken);\\n\\n /// @notice Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\\n error SnapshotError(address vToken, address user);\\n\\n /// @notice Thrown when the market is not listed\\n error MarketNotListed(address market);\\n\\n /// @notice Thrown when a market has an unexpected comptroller\\n error ComptrollerMismatch();\\n\\n /// @notice Thrown when user is not member of market\\n error MarketNotCollateral(address vToken, address user);\\n\\n /// @notice Thrown when borrow action is not paused\\n error BorrowActionNotPaused();\\n\\n /// @notice Thrown when mint action is not paused\\n error MintActionNotPaused();\\n\\n /// @notice Thrown when redeem action is not paused\\n error RedeemActionNotPaused();\\n\\n /// @notice Thrown when repay action is not paused\\n error RepayActionNotPaused();\\n\\n /// @notice Thrown when seize action is not paused\\n error SeizeActionNotPaused();\\n\\n /// @notice Thrown when exit market action is not paused\\n error ExitMarketActionNotPaused();\\n\\n /// @notice Thrown when transfer action is not paused\\n error TransferActionNotPaused();\\n\\n /// @notice Thrown when enter market action is not paused\\n error EnterMarketActionNotPaused();\\n\\n /// @notice Thrown when liquidate action is not paused\\n error LiquidateActionNotPaused();\\n\\n /// @notice Thrown when borrow cap is not zero\\n error BorrowCapIsNotZero();\\n\\n /// @notice Thrown when supply cap is not zero\\n error SupplyCapIsNotZero();\\n\\n /// @notice Thrown when collateral factor is not zero\\n error CollateralFactorIsNotZero();\\n\\n /**\\n * @notice Thrown during the liquidation if user's total collateral amount is lower than\\n * a predefined threshold. In this case only batch liquidations (either liquidateAccount\\n * or healAccount) are available.\\n */\\n error MinimalCollateralViolated(uint256 expectedGreaterThan, uint256 actual);\\n error CollateralExceedsThreshold(uint256 expectedLessThanOrEqualTo, uint256 actual);\\n error InsufficientCollateral(uint256 collateralToSeize, uint256 availableCollateral);\\n\\n /// @notice Thrown when the account doesn't have enough liquidity to redeem or borrow\\n error InsufficientLiquidity();\\n\\n /// @notice Thrown when trying to liquidate a healthy account\\n error InsufficientShortfall();\\n\\n /// @notice Thrown when trying to repay more than allowed by close factor\\n error TooMuchRepay();\\n\\n /// @notice Thrown if the user is trying to exit a market in which they have an outstanding debt\\n error NonzeroBorrowBalance();\\n\\n /// @notice Thrown when trying to perform an action that is paused\\n error ActionPaused(address market, Action action);\\n\\n /// @notice Thrown when trying to add a market that is already listed\\n error MarketAlreadyListed(address market);\\n\\n /// @notice Thrown if the supply cap is exceeded\\n error SupplyCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if the borrow cap is exceeded\\n error BorrowCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if delegate approval status is already set to the requested value\\n error DelegationStatusUnchanged();\\n\\n /// @param poolRegistry_ Pool registry address\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n constructor(address poolRegistry_) {\\n ensureNonzeroAddress(poolRegistry_);\\n\\n poolRegistry = poolRegistry_;\\n _disableInitializers();\\n }\\n\\n /**\\n * @param loopLimit Limit for the loops can iterate to avoid the DOS\\n * @param accessControlManager Access control manager contract address\\n */\\n function initialize(uint256 loopLimit, address accessControlManager) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager);\\n\\n _setMaxLoopsLimit(loopLimit);\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation; enabling them to be used as collateral\\n * @param vTokens The list of addresses of the vToken markets to be enabled\\n * @return errors An array of NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketEntered is emitted for each market on success\\n * @custom:error ActionPaused error is thrown if entering any of the markets is paused\\n * @custom:error MarketNotListed error is thrown if any of the markets is not listed\\n * @custom:access Not restricted\\n */\\n function enterMarkets(address[] memory vTokens) external override returns (uint256[] memory) {\\n uint256 len = vTokens.length;\\n\\n uint256[] memory results = new uint256[](len);\\n for (uint256 i; i < len; ++i) {\\n VToken vToken = VToken(vTokens[i]);\\n\\n _addToMarket(vToken, msg.sender);\\n results[i] = NO_ERROR;\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Unlist a market by setting isListed to false\\n * @dev Checks if all actions are paused, borrow/supply caps is set to 0 and collateral factor is to 0.\\n * @param market The address of the market (token) to unlist\\n * @return uint256 Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketUnlisted is emitted on success\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error BorrowActionNotPaused error is thrown if borrow action is not paused\\n * @custom:error MintActionNotPaused error is thrown if mint action is not paused\\n * @custom:error RedeemActionNotPaused error is thrown if redeem action is not paused\\n * @custom:error RepayActionNotPaused error is thrown if repay action is not paused\\n * @custom:error EnterMarketActionNotPaused error is thrown if enter market action is not paused\\n * @custom:error LiquidateActionNotPaused error is thrown if liquidate action is not paused\\n * @custom:error BorrowCapIsNotZero error is thrown if borrow cap is not zero\\n * @custom:error SupplyCapIsNotZero error is thrown if supply cap is not zero\\n * @custom:error CollateralFactorIsNotZero error is thrown if collateral factor is not zero\\n */\\n function unlistMarket(address market) external returns (uint256) {\\n _checkAccessAllowed(\\\"unlistMarket(address)\\\");\\n\\n Market storage _market = markets[market];\\n\\n if (!_market.isListed) {\\n revert MarketNotListed(market);\\n }\\n\\n if (!actionPaused(market, Action.BORROW)) {\\n revert BorrowActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.MINT)) {\\n revert MintActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.REDEEM)) {\\n revert RedeemActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.REPAY)) {\\n revert RepayActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.SEIZE)) {\\n revert SeizeActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.ENTER_MARKET)) {\\n revert EnterMarketActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.LIQUIDATE)) {\\n revert LiquidateActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.TRANSFER)) {\\n revert TransferActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.EXIT_MARKET)) {\\n revert ExitMarketActionNotPaused();\\n }\\n\\n if (borrowCaps[market] != 0) {\\n revert BorrowCapIsNotZero();\\n }\\n\\n if (supplyCaps[market] != 0) {\\n revert SupplyCapIsNotZero();\\n }\\n\\n if (_market.collateralFactorMantissa != 0) {\\n revert CollateralFactorIsNotZero();\\n }\\n\\n _market.isListed = false;\\n emit MarketUnlisted(market);\\n\\n return NO_ERROR;\\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 * @custom:event DelegateUpdated emits on success\\n * @custom:error ZeroAddressNotAllowed is thrown when delegate address is zero\\n * @custom:error DelegationStatusUnchanged is thrown if approval status is already set to the requested value\\n * @custom:access Not restricted\\n */\\n function updateDelegate(address delegate, bool approved) external {\\n ensureNonzeroAddress(delegate);\\n if (approvedDelegates[msg.sender][delegate] == approved) {\\n revert DelegationStatusUnchanged();\\n }\\n\\n approvedDelegates[msg.sender][delegate] = approved;\\n emit DelegateUpdated(msg.sender, delegate, approved);\\n }\\n\\n /**\\n * @notice Removes asset from sender's account liquidity calculation; disabling them as collateral\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketExited is emitted on success\\n * @custom:error ActionPaused error is thrown if exiting the market is paused\\n * @custom:error NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function exitMarket(address vTokenAddress) external override returns (uint256) {\\n _checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\\n VToken vToken = VToken(vTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\\n (uint256 tokensHeld, uint256 amountOwed, ) = _safeGetAccountSnapshot(vToken, msg.sender);\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n revert NonzeroBorrowBalance();\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n _checkRedeemAllowed(vTokenAddress, msg.sender, tokensHeld);\\n\\n Market storage marketToExit = markets[address(vToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return 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 // load into memory for faster iteration\\n VToken[] memory userAssetList = accountAssets[msg.sender];\\n uint256 len = userAssetList.length;\\n\\n uint256 assetIndex = len;\\n for (uint256 i; i < len; ++i) {\\n if (userAssetList[i] == vToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n VToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.pop();\\n\\n emit MarketExited(vToken, msg.sender);\\n\\n return NO_ERROR;\\n }\\n\\n /*** Policy Hooks ***/\\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 * @custom:error ActionPaused error is thrown if supplying to this market is paused\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\\n * @custom:access Not restricted\\n */\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external override {\\n _checkActionPauseState(vToken, Action.MINT);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n uint256 supplyCap = supplyCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (supplyCap != type(uint256).max) {\\n uint256 vTokenSupply = VToken(vToken).totalSupply();\\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\\n if (nextTotalSupply > supplyCap) {\\n revert SupplyCapExceeded(vToken, supplyCap);\\n }\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, minter);\\n }\\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external override {\\n _checkActionPauseState(vToken, Action.REDEEM);\\n\\n _checkRedeemAllowed(vToken, redeemer, redeemTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, redeemer);\\n }\\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 if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(redeemer, vToken);\\n }\\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 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 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 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 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 * @custom:error ActionPaused error is thrown if borrowing is paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if there is not enough collateral to borrow\\n * @custom:error BorrowCapExceeded is thrown if the borrow cap will be exceeded should this borrow succeed\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted if vToken is enabled as collateral, otherwise only vToken\\n */\\n /// disable-eslint\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external override {\\n _checkActionPauseState(vToken, Action.BORROW);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (!markets[vToken].accountMembership[borrower]) {\\n // only vTokens may call borrowAllowed if borrower not in market\\n _checkSenderIs(vToken);\\n\\n // attempt to add borrower to the market or revert\\n _addToMarket(VToken(msg.sender), borrower);\\n }\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (oracle.getUnderlyingPrice(vToken) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 borrowCap = borrowCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (borrowCap != type(uint256).max) {\\n uint256 totalBorrows = VToken(vToken).totalBorrows();\\n uint256 badDebt = VToken(vToken).badDebt();\\n uint256 nextTotalBorrows = totalBorrows + borrowAmount + badDebt;\\n if (nextTotalBorrows > borrowCap) {\\n revert BorrowCapExceeded(vToken, borrowCap);\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n borrower,\\n VToken(vToken),\\n 0,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\n }\\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 borrower The account which would borrowed the asset\\n * @custom:error ActionPaused error is thrown if repayments are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:access Not restricted\\n */\\n function preRepayHook(address vToken, address borrower) external override {\\n _checkActionPauseState(vToken, Action.REPAY);\\n\\n oracle.updatePrice(vToken);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\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 borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n * @param skipLiquidityCheck Allows the borrow to be liquidated regardless of the account liquidity\\n * @custom:error ActionPaused error is thrown if liquidations are paused in this market\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor\\n * @custom:error MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations\\n * @custom:error InsufficientShortfall is thrown when trying to liquidate a healthy account\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n */\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external override {\\n // Pause Action.LIQUIDATE on BORROWED TOKEN to prevent liquidating it.\\n // If we want to pause liquidating to vTokenCollateral, we should pause\\n // Action.SEIZE on it\\n _checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(address(vTokenBorrowed));\\n }\\n if (!markets[vTokenCollateral].isListed) {\\n revert MarketNotListed(address(vTokenCollateral));\\n }\\n\\n uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\\n\\n /* Allow accounts to be liquidated if it is a forced liquidation */\\n if (skipLiquidityCheck || isForcedLiquidationEnabled[vTokenBorrowed]) {\\n if (repayAmount > borrowBalance) {\\n revert TooMuchRepay();\\n }\\n return;\\n }\\n\\n /* The borrower must have shortfall and collateral > threshold in order to be liquidatable */\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral <= minLiquidatableCollateral) {\\n /* The liquidator should use either liquidateAccount or healAccount */\\n revert MinimalCollateralViolated(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint256 maxClose = mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance);\\n if (repayAmount > maxClose) {\\n revert TooMuchRepay();\\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 seizerContract Contract that tries to seize the asset (either borrowed vToken or Comptroller)\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @custom:error ActionPaused error is thrown if seizing this type of collateral is paused\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error ComptrollerMismatch error is when seizer contract or seized asset belong to different pools\\n * @custom:access Not restricted\\n */\\n function preSeizeHook(\\n address vTokenCollateral,\\n address seizerContract,\\n address liquidator,\\n address borrower\\n ) external override {\\n // Pause Action.SEIZE on COLLATERAL to prevent seizing it.\\n // If we want to pause liquidating vTokenBorrowed, we should pause\\n // Action.LIQUIDATE on it\\n _checkActionPauseState(vTokenCollateral, Action.SEIZE);\\n\\n Market storage market = markets[vTokenCollateral];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(vTokenCollateral);\\n }\\n\\n if (seizerContract == address(this)) {\\n // If Comptroller is the seizer, just check if collateral's comptroller\\n // is equal to the current address\\n if (address(VToken(vTokenCollateral).comptroller()) != address(this)) {\\n revert ComptrollerMismatch();\\n }\\n } else {\\n // If the seizer is not the Comptroller, check that the seizer is a\\n // listed market, and that the markets' comptrollers match\\n if (!markets[seizerContract].isListed) {\\n revert MarketNotListed(seizerContract);\\n }\\n if (VToken(vTokenCollateral).comptroller() != VToken(seizerContract).comptroller()) {\\n revert ComptrollerMismatch();\\n }\\n }\\n\\n if (!market.accountMembership[borrower]) {\\n revert MarketNotCollateral(vTokenCollateral, borrower);\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vTokenCollateral);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, borrower);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, liquidator);\\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external override {\\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 _checkRedeemAllowed(vToken, src, transferTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, src);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, dst);\\n }\\n }\\n\\n /*** Pool-level operations ***/\\n\\n /**\\n * @notice Seizes all the remaining collateral, makes msg.sender repay the existing\\n * borrows, and treats the rest of the debt as bad debt (for each market).\\n * The sender has to repay a certain percentage of the debt, computed as\\n * collateral / (borrows * liquidationIncentive).\\n * @param user account to heal\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for healing\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function healAccount(address user) external {\\n VToken[] memory userAssets = getAssetsIn(user);\\n uint256 userAssetsCount = userAssets.length;\\n\\n address liquidator = msg.sender;\\n {\\n ResilientOracleInterface oracle_ = oracle;\\n // We need all user's markets to be fresh for the computations to be correct\\n for (uint256 i; i < userAssetsCount; ++i) {\\n userAssets[i].accrueInterest();\\n oracle_.updatePrice(address(userAssets[i]));\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(user, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n // percentage = collateral / (borrows * liquidation incentive)\\n Exp memory collateral = Exp({ mantissa: snapshot.totalCollateral });\\n Exp memory scaledBorrows = mul_(\\n Exp({ mantissa: snapshot.borrows }),\\n Exp({ mantissa: liquidationIncentiveMantissa })\\n );\\n\\n Exp memory percentage = div_(collateral, scaledBorrows);\\n if (lessThanExp(Exp({ mantissa: MANTISSA_ONE }), percentage)) {\\n revert CollateralExceedsThreshold(scaledBorrows.mantissa, collateral.mantissa);\\n }\\n\\n for (uint256 i; i < userAssetsCount; ++i) {\\n VToken market = userAssets[i];\\n\\n (uint256 tokens, uint256 borrowBalance, ) = _safeGetAccountSnapshot(market, user);\\n uint256 repaymentAmount = mul_ScalarTruncate(percentage, borrowBalance);\\n\\n // Seize the entire collateral\\n if (tokens != 0) {\\n market.seize(liquidator, user, tokens);\\n }\\n // Repay a certain percentage of the borrow, forgive the rest\\n if (borrowBalance != 0) {\\n market.healBorrow(liquidator, user, repaymentAmount);\\n }\\n }\\n }\\n\\n /**\\n * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than\\n * a predefined threshold, and the account collateral can be seized to cover all borrows. If\\n * the collateral is higher than the threshold, use regular liquidations. If the collateral is\\n * below the threshold, and the account is insolvent, use healAccount.\\n * @param borrower the borrower address\\n * @param orders an array of liquidation orders\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation\\n * @custom:error InsufficientCollateral error is thrown when there is not enough collateral to cover the debt\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function liquidateAccount(address borrower, LiquidationOrder[] calldata orders) external {\\n // We will accrue interest and update the oracle prices later during the liquidation\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n // You should use the regular vToken.liquidateBorrow(...) call\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n uint256 collateralToSeize = mul_ScalarTruncate(\\n Exp({ mantissa: liquidationIncentiveMantissa }),\\n snapshot.borrows\\n );\\n if (collateralToSeize >= snapshot.totalCollateral) {\\n // There is not enough collateral to seize. Use healBorrow to repay some part of the borrow\\n // and record bad debt.\\n revert InsufficientCollateral(collateralToSeize, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n uint256 ordersCount = orders.length;\\n\\n _ensureMaxLoops(ordersCount / 2);\\n\\n for (uint256 i; i < ordersCount; ++i) {\\n if (!markets[address(orders[i].vTokenBorrowed)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenBorrowed));\\n }\\n if (!markets[address(orders[i].vTokenCollateral)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenCollateral));\\n }\\n\\n LiquidationOrder calldata order = orders[i];\\n order.vTokenBorrowed.forceLiquidateBorrow(\\n msg.sender,\\n borrower,\\n order.repayAmount,\\n order.vTokenCollateral,\\n true\\n );\\n }\\n\\n VToken[] memory borrowMarkets = getAssetsIn(borrower);\\n uint256 marketsCount = borrowMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower);\\n require(borrowBalance == 0, \\\"Nonzero borrow balance after liquidation\\\");\\n }\\n }\\n\\n /**\\n * @notice Sets the closeFactor to use when liquidating borrows\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @custom:event Emits NewCloseFactor on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCloseFactor(uint256 newCloseFactorMantissa) external {\\n _checkAccessAllowed(\\\"setCloseFactor(uint256)\\\");\\n require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, \\\"Close factor greater than maximum close factor\\\");\\n require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, \\\"Close factor smaller than minimum close factor\\\");\\n\\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev This function is restricted by the AccessControlManager\\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 * @custom:event Emits NewCollateralFactor when collateral factor is updated\\n * and NewLiquidationThreshold when liquidation threshold is updated\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InvalidCollateralFactor error is thrown when collateral factor is too high\\n * @custom:error InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor\\n * @custom:error PriceError is thrown when the oracle returns an invalid price for the asset\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCollateralFactor(\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external {\\n _checkAccessAllowed(\\\"setCollateralFactor(address,uint256,uint256)\\\");\\n\\n // Verify market is listed\\n Market storage market = markets[address(vToken)];\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Check collateral factor <= 0.9\\n if (newCollateralFactorMantissa > MAX_COLLATERAL_FACTOR_MANTISSA) {\\n revert InvalidCollateralFactor();\\n }\\n\\n // Ensure that liquidation threshold <= 1\\n if (newLiquidationThresholdMantissa > MANTISSA_ONE) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // Ensure that liquidation threshold >= CF\\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n }\\n\\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\\n emit NewLiquidationThreshold(vToken, oldLiquidationThresholdMantissa, newLiquidationThresholdMantissa);\\n }\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev This function is restricted by the AccessControlManager\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @custom:event Emits NewLiquidationIncentive on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external {\\n require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, \\\"liquidation incentive should be greater than 1e18\\\");\\n\\n _checkAccessAllowed(\\\"setLiquidationIncentive(uint256)\\\");\\n\\n // Save current value for use in log\\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\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\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Only callable by the PoolRegistry\\n * @param vToken The address of the market (token) to list\\n * @custom:error MarketAlreadyListed is thrown if the market is already listed in this pool\\n * @custom:access Only PoolRegistry\\n */\\n function supportMarket(VToken vToken) external {\\n _checkSenderIs(poolRegistry);\\n\\n if (markets[address(vToken)].isListed) {\\n revert MarketAlreadyListed(address(vToken));\\n }\\n\\n require(vToken.isVToken(), \\\"Comptroller: Invalid vToken\\\"); // Sanity check to make sure its really a VToken\\n\\n Market storage newMarket = markets[address(vToken)];\\n newMarket.isListed = true;\\n newMarket.collateralFactorMantissa = 0;\\n newMarket.liquidationThresholdMantissa = 0;\\n\\n _addMarket(address(vToken));\\n\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n rewardsDistributors[i].initializeMarket(address(vToken));\\n }\\n\\n emit MarketSupported(vToken);\\n }\\n\\n /**\\n * @notice Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A borrow cap of type(uint256).max corresponds to unlimited borrowing.\\n * @dev Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed\\n until the total borrows amount goes below the new borrow cap\\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 type(uint256).max corresponds to unlimited borrowing.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\\n _checkAccessAllowed(\\\"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 _ensureMaxLoops(numMarkets);\\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 * @notice Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A supply cap of type(uint256).max corresponds to unlimited supply.\\n * @dev Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed\\n until the total supplies amount goes below the new supply cap\\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 type(uint256).max corresponds to unlimited supply.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\\n _checkAccessAllowed(\\\"setMarketSupplyCaps(address[],uint256[])\\\");\\n uint256 vTokensCount = vTokens.length;\\n\\n require(vTokensCount != 0, \\\"invalid number of markets\\\");\\n require(vTokensCount == newSupplyCaps.length, \\\"invalid number of markets\\\");\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Pause/unpause specified actions\\n * @dev This function is restricted by the AccessControlManager\\n * @param marketsList Markets to pause/unpause the actions on\\n * @param actionsList List of action ids to pause/unpause\\n * @param paused The new paused state (true=paused, false=unpaused)\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setActionsPaused(VToken[] calldata marketsList, Action[] calldata actionsList, bool paused) external {\\n _checkAccessAllowed(\\\"setActionsPaused(address[],uint256[],bool)\\\");\\n\\n uint256 marketsCount = marketsList.length;\\n uint256 actionsCount = actionsList.length;\\n\\n _ensureMaxLoops(marketsCount * actionsCount);\\n\\n for (uint256 marketIdx; marketIdx < marketsCount; ++marketIdx) {\\n for (uint256 actionIdx; actionIdx < actionsCount; ++actionIdx) {\\n _setActionPaused(address(marketsList[marketIdx]), actionsList[actionIdx], paused);\\n }\\n }\\n }\\n\\n /**\\n * @notice Set the given collateral threshold for non-batch liquidations. Regular liquidations\\n * will fail if the collateral amount is less than this threshold. Liquidators should use batch\\n * operations like liquidateAccount or healAccount.\\n * @dev This function is restricted by the AccessControlManager\\n * @param newMinLiquidatableCollateral The new min liquidatable collateral (in USD).\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external {\\n _checkAccessAllowed(\\\"setMinLiquidatableCollateral(uint256)\\\");\\n\\n uint256 oldMinLiquidatableCollateral = minLiquidatableCollateral;\\n minLiquidatableCollateral = newMinLiquidatableCollateral;\\n emit NewMinLiquidatableCollateral(oldMinLiquidatableCollateral, newMinLiquidatableCollateral);\\n }\\n\\n /**\\n * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor\\n * contracts with the same rewardToken, and there could be overlaping among them considering the last reward slot (block or second)\\n * @dev Only callable by the admin\\n * @param _rewardsDistributor Address of the RewardDistributor contract to add\\n * @custom:access Only Governance\\n * @custom:event Emits NewRewardsDistributor with distributor address\\n */\\n function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner {\\n require(!rewardsDistributorExists[address(_rewardsDistributor)], \\\"already exists\\\");\\n\\n uint256 rewardsDistributorsLen = rewardsDistributors.length;\\n _ensureMaxLoops(rewardsDistributorsLen + 1);\\n\\n rewardsDistributors.push(_rewardsDistributor);\\n rewardsDistributorExists[address(_rewardsDistributor)] = true;\\n\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n _rewardsDistributor.initializeMarket(address(allMarkets[i]));\\n }\\n\\n emit NewRewardsDistributor(address(_rewardsDistributor), address(_rewardsDistributor.rewardToken()));\\n }\\n\\n /**\\n * @notice Sets a new price oracle for the Comptroller\\n * @dev Only callable by the admin\\n * @param newOracle Address of the new price oracle to set\\n * @custom:event Emits NewPriceOracle on success\\n * @custom:error ZeroAddressNotAllowed is thrown when the new oracle address is zero\\n */\\n function setPriceOracle(ResilientOracleInterface newOracle) external onlyOwner {\\n ensureNonzeroAddress(address(newOracle));\\n\\n ResilientOracleInterface oldOracle = oracle;\\n oracle = newOracle;\\n emit NewPriceOracle(oldOracle, newOracle);\\n }\\n\\n /**\\n * @notice Set the for loop iteration limit to avoid DOS\\n * @param limit Limit for the max loops can execute at a time\\n */\\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Sets the prime token contract for the comptroller\\n * @param _prime Address of the Prime contract\\n */\\n function setPrimeToken(IPrime _prime) external onlyOwner {\\n ensureNonzeroAddress(address(_prime));\\n\\n emit NewPrimeToken(prime, _prime);\\n prime = _prime;\\n }\\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 * @param vTokenBorrowed Borrowed vToken\\n * @param enable Whether to enable forced liquidations\\n */\\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\\n _checkAccessAllowed(\\\"setForcedLiquidation(address,bool)\\\");\\n ensureNonzeroAddress(vTokenBorrowed);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(vTokenBorrowed);\\n }\\n\\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to liquidation threshold requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of liquidation threshold requirements,\\n * @return shortfall Account shortfall below liquidation threshold requirements\\n */\\n function getAccountLiquidity(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getLiquidationThreshold);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to collateral requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of collateral requirements,\\n * @return shortfall Account shortfall below collateral requirements\\n */\\n function getBorrowingPower(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getCollateralFactor);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Hypothetical account liquidity in excess of collateral requirements,\\n * @return shortfall 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 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n account,\\n VToken(vTokenModify),\\n redeemTokens,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\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 markets The list of market addresses\\n */\\n function getAllMarkets() external view override returns (VToken[] memory) {\\n return allMarkets;\\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 /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns whether the given account is entered in a given market\\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 market specified, 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 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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return tokensToSeize Number of vTokenCollateral tokens to be seized in a liquidation\\n * @custom:error PriceError if the oracle returns an invalid price\\n */\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view override returns (uint256 error, uint256 tokensToSeize) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint256 priceBorrowedMantissa = _safeGetUnderlyingPrice(VToken(vTokenBorrowed));\\n uint256 priceCollateralMantissa = _safeGetUnderlyingPrice(VToken(vTokenCollateral));\\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 uint256 exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint256 seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n\\n numerator = mul_(Exp({ mantissa: liquidationIncentiveMantissa }), Exp({ mantissa: priceBorrowedMantissa }));\\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\\n ratio = div_(numerator, denominator);\\n\\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\\n\\n return (NO_ERROR, seizeTokens);\\n }\\n\\n /**\\n * @notice Returns reward speed given a vToken\\n * @param vToken The vToken to get the reward speeds for\\n * @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors\\n */\\n function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {\\n uint256 rewardsDistributorsLength = rewardsDistributors.length;\\n rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);\\n for (uint256 i; i < rewardsDistributorsLength; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n address rewardToken = address(rewardsDistributor.rewardToken());\\n rewardSpeeds[i] = RewardSpeeds({\\n rewardToken: rewardToken,\\n supplySpeed: rewardsDistributor.rewardTokenSupplySpeeds(vToken),\\n borrowSpeed: rewardsDistributor.rewardTokenBorrowSpeeds(vToken)\\n });\\n }\\n return rewardSpeeds;\\n }\\n\\n /**\\n * @notice Return all reward distributors for this pool\\n * @return Array of RewardDistributor addresses\\n */\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory) {\\n return rewardsDistributors;\\n }\\n\\n /**\\n * @notice A marker method that returns true for a valid Comptroller contract\\n * @return Always true\\n */\\n function isComptroller() external pure override returns (bool) {\\n return true;\\n }\\n\\n /**\\n * @notice Update the prices of all the tokens associated with the provided account\\n * @param account Address of the account to get associated tokens with\\n */\\n function updatePrices(address account) public {\\n VToken[] memory vTokens = getAssetsIn(account);\\n uint256 vTokensCount = vTokens.length;\\n\\n ResilientOracleInterface oracle_ = oracle;\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n oracle_.updatePrice(address(vTokens[i]));\\n }\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param market vToken address\\n * @param action Action to check\\n * @return paused True if the action is paused otherwise false\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][action];\\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 list with the assets the account has entered\\n */\\n function getAssetsIn(address account) public 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 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 */\\n function _addToMarket(VToken vToken, address borrower) internal {\\n _checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = markets[address(vToken)];\\n\\n if (!marketToJoin.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return;\\n }\\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\\n /**\\n * @notice Internal function to validate that a market hasn't already been added\\n * and if it hasn't adds it\\n * @param vToken The market to support\\n */\\n function _addMarket(address vToken) internal {\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n if (allMarkets[i] == VToken(vToken)) {\\n revert MarketAlreadyListed(vToken);\\n }\\n }\\n allMarkets.push(VToken(vToken));\\n marketsCount = allMarkets.length;\\n _ensureMaxLoops(marketsCount);\\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 _setActionPaused(address market, Action action, bool paused) internal {\\n require(markets[market].isListed, \\\"cannot pause a market that is not listed\\\");\\n _actionPaused[market][action] = paused;\\n emit ActionPausedMarket(VToken(market), action, paused);\\n }\\n\\n /**\\n * @dev Internal function to check that vTokens can be safely redeemed for the underlying asset.\\n * @param vToken Address of the vTokens to redeem\\n * @param redeemer Account redeeming the tokens\\n * @param redeemTokens The number of tokens to redeem\\n */\\n function _checkRedeemAllowed(address vToken, address redeemer, uint256 redeemTokens) internal {\\n Market storage market = markets[vToken];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!market.accountMembership[redeemer]) {\\n return;\\n }\\n\\n // Update the prices of tokens\\n updatePrices(redeemer);\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n _getCollateralFactor\\n );\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n }\\n\\n /**\\n * @notice Get the total collateral, weighted collateral, borrow balance, liquidity, shortfall\\n * @param account The account to get the snapshot for\\n * @param weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n * liquidation threshold. Accepts the address of the vToken and returns the weight as Exp.\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getCurrentLiquiditySnapshot(\\n address account,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n return _getHypotheticalLiquiditySnapshot(account, VToken(address(0)), 0, 0, weight);\\n }\\n\\n /**\\n * @notice Determine what the supply/borrow balances 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 weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n liquidation threshold. Accepts the address of the VToken and returns the weight\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getHypotheticalLiquiditySnapshot(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n // For each asset the account is in\\n VToken[] memory assets = getAssetsIn(account);\\n uint256 assetsCount = assets.length;\\n\\n for (uint256 i; i < assetsCount; ++i) {\\n VToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the vToken\\n (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) = _safeGetAccountSnapshot(\\n asset,\\n account\\n );\\n\\n // Get the normalized price of the asset\\n Exp memory oraclePrice = Exp({ mantissa: _safeGetUnderlyingPrice(asset) });\\n\\n // Pre-compute conversion factors from vTokens -> usd\\n Exp memory vTokenPrice = mul_(Exp({ mantissa: exchangeRateMantissa }), oraclePrice);\\n Exp memory weightedVTokenPrice = mul_(weight(asset), vTokenPrice);\\n\\n // weightedCollateral += weightedVTokenPrice * vTokenBalance\\n snapshot.weightedCollateral = mul_ScalarTruncateAddUInt(\\n weightedVTokenPrice,\\n vTokenBalance,\\n snapshot.weightedCollateral\\n );\\n\\n // totalCollateral += vTokenPrice * vTokenBalance\\n snapshot.totalCollateral = mul_ScalarTruncateAddUInt(vTokenPrice, vTokenBalance, snapshot.totalCollateral);\\n\\n // borrows += oraclePrice * borrowBalance\\n snapshot.borrows = mul_ScalarTruncateAddUInt(oraclePrice, borrowBalance, snapshot.borrows);\\n\\n // Calculate effects of interacting with vTokenModify\\n if (asset == vTokenModify) {\\n // redeem effect\\n // effects += tokensToDenom * redeemTokens\\n snapshot.effects = mul_ScalarTruncateAddUInt(weightedVTokenPrice, redeemTokens, snapshot.effects);\\n\\n // borrow effect\\n // effects += oraclePrice * borrowAmount\\n snapshot.effects = mul_ScalarTruncateAddUInt(oraclePrice, borrowAmount, snapshot.effects);\\n }\\n }\\n\\n uint256 borrowPlusEffects = snapshot.borrows + snapshot.effects;\\n // These are safe, as the underflow condition is checked first\\n unchecked {\\n if (snapshot.weightedCollateral > borrowPlusEffects) {\\n snapshot.liquidity = snapshot.weightedCollateral - borrowPlusEffects;\\n snapshot.shortfall = 0;\\n } else {\\n snapshot.liquidity = 0;\\n snapshot.shortfall = borrowPlusEffects - snapshot.weightedCollateral;\\n }\\n }\\n\\n return snapshot;\\n }\\n\\n /**\\n * @dev Retrieves price from oracle for an asset and checks it is nonzero\\n * @param asset Address for asset to query price\\n * @return Underlying price\\n */\\n function _safeGetUnderlyingPrice(VToken asset) internal view returns (uint256) {\\n uint256 oraclePriceMantissa = oracle.getUnderlyingPrice(address(asset));\\n if (oraclePriceMantissa == 0) {\\n revert PriceError(address(asset));\\n }\\n return oraclePriceMantissa;\\n }\\n\\n /**\\n * @dev Return collateral factor for a market\\n * @param asset Address for asset\\n * @return Collateral factor as exponential\\n */\\n function _getCollateralFactor(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].collateralFactorMantissa });\\n }\\n\\n /**\\n * @dev Retrieves liquidation threshold for a market as an exponential\\n * @param asset Address for asset to liquidation threshold\\n * @return Liquidation threshold as exponential\\n */\\n function _getLiquidationThreshold(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].liquidationThresholdMantissa });\\n }\\n\\n /**\\n * @dev Returns supply and borrow balances of user in vToken, reverts on failure\\n * @param vToken Market to query\\n * @param user Account address\\n * @return vTokenBalance Balance of vTokens, the same as vToken.balanceOf(user)\\n * @return borrowBalance Borrowed amount, including the interest\\n * @return exchangeRateMantissa Stored exchange rate\\n */\\n function _safeGetAccountSnapshot(\\n VToken vToken,\\n address user\\n ) internal view returns (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) {\\n uint256 err;\\n (err, vTokenBalance, borrowBalance, exchangeRateMantissa) = vToken.getAccountSnapshot(user);\\n if (err != 0) {\\n revert SnapshotError(address(vToken), user);\\n }\\n return (vTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /// @notice Reverts if the call is not from expectedSender\\n /// @param expectedSender Expected transaction sender\\n function _checkSenderIs(address expectedSender) internal view {\\n if (msg.sender != expectedSender) {\\n revert UnexpectedSender(expectedSender, msg.sender);\\n }\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n /// @param market Market to check\\n /// @param action Action to check\\n function _checkActionPauseState(address market, Action action) private view {\\n if (actionPaused(market, action)) {\\n revert ActionPaused(market, action);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7c6e1c6264e4681f82a9ac1bcd9155197a930033291ee5561ad97a56006f5e9c\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.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\\n/**\\n * @title ComptrollerInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract.\\n */\\ninterface ComptrollerInterface {\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\\n\\n function exitMarket(address vToken) external returns (uint256);\\n\\n /*** Policy Hooks ***/\\n\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external;\\n\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external;\\n\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external;\\n\\n function preRepayHook(address vToken, address borrower) external;\\n\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external;\\n\\n function preSeizeHook(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower\\n ) external;\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\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 seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external;\\n\\n function isComptroller() external view returns (bool);\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 repayAmount\\n ) external view returns (uint256, uint256);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n}\\n\\n/**\\n * @title ComptrollerViewInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract, including only some util view functions.\\n */\\ninterface ComptrollerViewInterface {\\n function markets(address) external view returns (bool, uint256);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function closeFactorMantissa() external view returns (uint256);\\n\\n function liquidationIncentiveMantissa() external view returns (uint256);\\n\\n function minLiquidatableCollateral() external view returns (uint256);\\n\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function borrowCaps(address) external view returns (uint256);\\n\\n function supplyCaps(address) external view returns (uint256);\\n\\n function approvedDelegates(address user, address delegate) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xcbf7f9977472650c61345b7cbde23e81f626e1f8863bab4c6ce3dacfc7604919\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { IPrime } from \\\"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\\\";\\nimport { Action } from \\\"./ComptrollerInterface.sol\\\";\\n\\n/**\\n * @title ComptrollerStorage\\n * @author Venus\\n * @notice Storage layout for the `Comptroller` contract.\\n */\\ncontract ComptrollerStorage {\\n struct LiquidationOrder {\\n VToken vTokenCollateral;\\n VToken vTokenBorrowed;\\n uint256 repayAmount;\\n }\\n\\n struct AccountLiquiditySnapshot {\\n uint256 totalCollateral;\\n uint256 weightedCollateral;\\n uint256 borrows;\\n uint256 effects;\\n uint256 liquidity;\\n uint256 shortfall;\\n }\\n\\n struct RewardSpeeds {\\n address rewardToken;\\n uint256 supplySpeed;\\n uint256 borrowSpeed;\\n }\\n\\n struct Market {\\n // Whether or not this market is listed\\n bool isListed;\\n // 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 uint256 collateralFactorMantissa;\\n // 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 uint256 liquidationThresholdMantissa;\\n // Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n }\\n\\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 Per-account mapping of \\\"assets you are in\\\"\\n */\\n mapping(address => VToken[]) public accountAssets;\\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 /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\\n mapping(address => uint256) public borrowCaps;\\n\\n /// @notice Minimal collateral required for regular (non-batch) liquidations\\n uint256 public minLiquidatableCollateral;\\n\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\\n mapping(address => uint256) public supplyCaps;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(Action => bool)) internal _actionPaused;\\n\\n // List of Reward Distributors added\\n RewardsDistributor[] internal rewardsDistributors;\\n\\n // Used to check if rewards distributor is added\\n mapping(address => bool) internal rewardsDistributorExists;\\n\\n /// @notice Flag indicating whether forced liquidation enabled for a market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n\\n uint256 internal constant NO_ERROR = 0;\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant MIN_CLOSE_FACTOR_MANTISSA = 0.05e18; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant MAX_CLOSE_FACTOR_MANTISSA = 0.9e18; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.95e18; // 0.95\\n\\n /// Prime token address\\n IPrime public prime;\\n\\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 /**\\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[47] private __gap;\\n}\\n\",\"keccak256\":\"0x4df44cb65ac152bac2be4b4545430e703005a74a55b72e144100b16421bd8bfd\",\"license\":\"BSD-3-Clause\"},\"contracts/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title TokenErrorReporter\\n * @author Venus\\n * @notice Errors that can be thrown by the `VToken` contract.\\n */\\ncontract TokenErrorReporter {\\n uint256 public constant NO_ERROR = 0; // support legacy return codes\\n\\n error TransferNotAllowed();\\n\\n error MintFreshnessCheck();\\n\\n error RedeemFreshnessCheck();\\n error RedeemTransferOutNotPossible();\\n\\n error BorrowFreshnessCheck();\\n error BorrowCashNotAvailable();\\n error DelegateNotApproved();\\n\\n error RepayBorrowFreshnessCheck();\\n\\n error HealBorrowUnauthorized();\\n error ForceLiquidateBorrowUnauthorized();\\n\\n error LiquidateFreshnessCheck();\\n error LiquidateCollateralFreshnessCheck();\\n error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\\n error LiquidateLiquidatorIsBorrower();\\n error LiquidateCloseAmountIsZero();\\n error LiquidateCloseAmountIsUintMax();\\n\\n error LiquidateSeizeLiquidatorIsBorrower();\\n\\n error ProtocolSeizeShareTooBig();\\n\\n error SetReserveFactorFreshCheck();\\n error SetReserveFactorBoundsCheck();\\n\\n error AddReservesFactorFreshCheck(uint256 actualAddAmount);\\n\\n error ReduceReservesFreshCheck();\\n error ReduceReservesCashNotAvailable();\\n error ReduceReservesCashValidation();\\n\\n error SetInterestRateModelFreshCheck();\\n}\\n\",\"keccak256\":\"0x7a7ced1caaac2d9242659ebd50b99f308c725ce958ac9e11f7ada404b1d97a7b\",\"license\":\"BSD-3-Clause\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from \\\"./lib/constants.sol\\\";\\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 struct Exp {\\n uint256 mantissa;\\n }\\n\\n struct Double {\\n uint256 mantissa;\\n }\\n\\n uint256 internal constant EXP_SCALE = EXP_SCALE_;\\n uint256 internal constant DOUBLE_SCALE = 1e36;\\n uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;\\n uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint256) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / EXP_SCALE;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\\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 // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint256 scalar, uint256 addend) internal pure returns (uint256) {\\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 function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\\n require(n <= type(uint224).max, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\\n require(n <= type(uint32).max, 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_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a + b;\\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_(uint256 a, uint256 b) internal pure returns (uint256) {\\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) / EXP_SCALE });\\n }\\n\\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / EXP_SCALE;\\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) / DOUBLE_SCALE });\\n }\\n\\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / DOUBLE_SCALE;\\n }\\n\\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a * b;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return div_(mul_(a, EXP_SCALE), 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, DOUBLE_SCALE), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return div_(mul_(a, DOUBLE_SCALE), b.mantissa);\\n }\\n\\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a / b;\\n }\\n\\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });\\n }\\n}\\n\",\"keccak256\":\"0x8afbe8a24fe3539c124e718681ed3dcebd24c40dd53095786c0155998213b9b0\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModel.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\nabstract contract InterestRateModel {\\n /**\\n * @notice Calculates the current borrow interest rate per slot (block or second)\\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 amount of reserves the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per slot (block or second)\\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 amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\\n * @return Always true\\n */\\n function isInterestRateModel() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xc4fda1ab75ebe4b187b707c4f10c58780f343cf343c537f641dc75d3cd28ab51\",\"license\":\"BSD-3-Clause\"},\"contracts/Lens/PoolLens.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { IERC20Metadata } from \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Action, ComptrollerInterface, ComptrollerViewInterface } from \\\"../ComptrollerInterface.sol\\\";\\nimport { PoolRegistryInterface } from \\\"../Pool/PoolRegistryInterface.sol\\\";\\nimport { PoolRegistry } from \\\"../Pool/PoolRegistry.sol\\\";\\nimport { RewardsDistributor } from \\\"../Rewards/RewardsDistributor.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\n\\n/**\\n * @title PoolLens\\n * @author Venus\\n * @notice The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information\\n * for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be\\n * looked up for specific pools and markets:\\n- the vToken balance of a given user;\\n- the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address;\\n- the vToken address in a pool for a given asset;\\n- a list of all pools that support an asset;\\n- the underlying asset price of a vToken;\\n- the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\\n */\\ncontract PoolLens is ExponentialNoError, TimeManagerV8 {\\n /**\\n * @dev Struct for PoolDetails.\\n */\\n struct PoolData {\\n string name;\\n address creator;\\n address comptroller;\\n uint256 blockPosted;\\n uint256 timestampPosted;\\n string category;\\n string logoURL;\\n string description;\\n address priceOracle;\\n uint256 closeFactor;\\n uint256 liquidationIncentive;\\n uint256 minLiquidatableCollateral;\\n VTokenMetadata[] vTokens;\\n }\\n\\n /**\\n * @dev Struct for VToken.\\n */\\n struct VTokenMetadata {\\n address vToken;\\n uint256 exchangeRateCurrent;\\n uint256 supplyRatePerBlockOrTimestamp;\\n uint256 borrowRatePerBlockOrTimestamp;\\n uint256 reserveFactorMantissa;\\n uint256 supplyCaps;\\n uint256 borrowCaps;\\n uint256 totalBorrows;\\n uint256 totalReserves;\\n uint256 totalSupply;\\n uint256 totalCash;\\n bool isListed;\\n uint256 collateralFactorMantissa;\\n address underlyingAssetAddress;\\n uint256 vTokenDecimals;\\n uint256 underlyingDecimals;\\n uint256 pausedActions;\\n }\\n\\n /**\\n * @dev Struct for VTokenBalance.\\n */\\n struct VTokenBalances {\\n address vToken;\\n uint256 balanceOf;\\n uint256 borrowBalanceCurrent;\\n uint256 balanceOfUnderlying;\\n uint256 tokenBalance;\\n uint256 tokenAllowance;\\n }\\n\\n /**\\n * @dev Struct for underlyingPrice of VToken.\\n */\\n struct VTokenUnderlyingPrice {\\n address vToken;\\n uint256 underlyingPrice;\\n }\\n\\n /**\\n * @dev Struct with pending reward info for a market.\\n */\\n struct PendingReward {\\n address vTokenAddress;\\n uint256 amount;\\n }\\n\\n /**\\n * @dev Struct with reward distribution totals for a single reward token and distributor.\\n */\\n struct RewardSummary {\\n address distributorAddress;\\n address rewardTokenAddress;\\n uint256 totalRewards;\\n PendingReward[] pendingRewards;\\n }\\n\\n /**\\n * @dev Struct used in RewardDistributor to save last updated market state.\\n */\\n struct RewardTokenState {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number or timestamp the index was last updated at\\n uint256 blockOrTimestamp;\\n // The block number or timestamp at which to stop rewards\\n uint256 lastRewardingBlockOrTimestamp;\\n }\\n\\n /**\\n * @dev Struct with bad debt of a market denominated\\n */\\n struct BadDebt {\\n address vTokenAddress;\\n uint256 badDebtUsd;\\n }\\n\\n /**\\n * @dev Struct with bad debt total denominated in usd for a pool and an array of BadDebt structs for each market\\n */\\n struct BadDebtSummary {\\n address comptroller;\\n uint256 totalBadDebtUsd;\\n BadDebt[] badDebts;\\n }\\n\\n /**\\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) {}\\n\\n /**\\n * @notice Queries the user's supply/borrow balances in vTokens\\n * @param vTokens The list of vToken addresses\\n * @param account The user Account\\n * @return A list of structs containing balances data\\n */\\n function vTokenBalancesAll(VToken[] calldata vTokens, address account) external returns (VTokenBalances[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenBalances[] memory res = new VTokenBalances[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenBalances(vTokens[i], account);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Queries all pools with addtional details for each of them\\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @return Arrays of all Venus pools' data\\n */\\n function getAllPools(address poolRegistryAddress) external view returns (PoolData[] memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n PoolRegistry.VenusPool[] memory venusPools = poolRegistryInterface.getAllPools();\\n uint256 poolLength = venusPools.length;\\n\\n PoolData[] memory poolDataItems = new PoolData[](poolLength);\\n\\n for (uint256 i; i < poolLength; ++i) {\\n PoolRegistry.VenusPool memory venusPool = venusPools[i];\\n PoolData memory poolData = getPoolDataFromVenusPool(poolRegistryAddress, venusPool);\\n poolDataItems[i] = poolData;\\n }\\n\\n return poolDataItems;\\n }\\n\\n /**\\n * @notice Queries the details of a pool identified by Comptroller address\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param comptroller The Comptroller implementation address\\n * @return PoolData structure containing the details of the pool\\n */\\n function getPoolByComptroller(\\n address poolRegistryAddress,\\n address comptroller\\n ) external view returns (PoolData memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return getPoolDataFromVenusPool(poolRegistryAddress, poolRegistryInterface.getPoolByComptroller(comptroller));\\n }\\n\\n /**\\n * @notice Returns vToken holding the specified underlying asset in the specified pool\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param comptroller The pool comptroller\\n * @param asset The underlyingAsset of VToken\\n * @return Address of the vToken\\n */\\n function getVTokenForAsset(\\n address poolRegistryAddress,\\n address comptroller,\\n address asset\\n ) external view returns (address) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return poolRegistryInterface.getVTokenForAsset(comptroller, asset);\\n }\\n\\n /**\\n * @notice Returns all pools that support the specified underlying asset\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param asset The underlying asset of vToken\\n * @return A list of Comptroller contracts\\n */\\n function getPoolsSupportedByAsset(\\n address poolRegistryAddress,\\n address asset\\n ) external view returns (address[] memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return poolRegistryInterface.getPoolsSupportedByAsset(asset);\\n }\\n\\n /**\\n * @notice Returns the price data for the underlying assets of the specified vTokens\\n * @param vTokens The list of vToken addresses\\n * @return An array containing the price data for each asset\\n */\\n function vTokenUnderlyingPriceAll(\\n VToken[] calldata vTokens\\n ) external view returns (VTokenUnderlyingPrice[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenUnderlyingPrice[] memory res = new VTokenUnderlyingPrice[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenUnderlyingPrice(vTokens[i]);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Returns the pending rewards for a user for a given pool.\\n * @param account The user account.\\n * @param comptrollerAddress address\\n * @return Pending rewards array\\n */\\n function getPendingRewards(\\n address account,\\n address comptrollerAddress\\n ) external view returns (RewardSummary[] memory) {\\n VToken[] memory markets = ComptrollerInterface(comptrollerAddress).getAllMarkets();\\n RewardsDistributor[] memory rewardsDistributors = ComptrollerViewInterface(comptrollerAddress)\\n .getRewardDistributors();\\n RewardSummary[] memory rewardSummary = new RewardSummary[](rewardsDistributors.length);\\n for (uint256 i; i < rewardsDistributors.length; ++i) {\\n RewardSummary memory reward;\\n reward.distributorAddress = address(rewardsDistributors[i]);\\n reward.rewardTokenAddress = address(rewardsDistributors[i].rewardToken());\\n reward.totalRewards = rewardsDistributors[i].rewardTokenAccrued(account);\\n reward.pendingRewards = _calculateNotDistributedAwards(account, markets, rewardsDistributors[i]);\\n rewardSummary[i] = reward;\\n }\\n return rewardSummary;\\n }\\n\\n /**\\n * @notice Returns a summary of a pool's bad debt broken down by market\\n *\\n * @param comptrollerAddress Address of the comptroller\\n *\\n * @return badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and\\n * a break down of bad debt by market\\n */\\n function getPoolBadDebt(address comptrollerAddress) external view returns (BadDebtSummary memory) {\\n uint256 totalBadDebtUsd;\\n\\n // Get every market in the pool\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\\n VToken[] memory markets = comptroller.getAllMarkets();\\n ResilientOracleInterface priceOracle = comptroller.oracle();\\n\\n BadDebt[] memory badDebts = new BadDebt[](markets.length);\\n\\n BadDebtSummary memory badDebtSummary;\\n badDebtSummary.comptroller = comptrollerAddress;\\n badDebtSummary.badDebts = badDebts;\\n\\n // // Calculate the bad debt is USD per market\\n for (uint256 i; i < markets.length; ++i) {\\n BadDebt memory badDebt;\\n badDebt.vTokenAddress = address(markets[i]);\\n badDebt.badDebtUsd =\\n (VToken(address(markets[i])).badDebt() * priceOracle.getUnderlyingPrice(address(markets[i]))) /\\n EXP_SCALE;\\n badDebtSummary.badDebts[i] = badDebt;\\n totalBadDebtUsd = totalBadDebtUsd + badDebt.badDebtUsd;\\n }\\n\\n badDebtSummary.totalBadDebtUsd = totalBadDebtUsd;\\n\\n return badDebtSummary;\\n }\\n\\n /**\\n * @notice Queries the user's supply/borrow balances in the specified vToken\\n * @param vToken vToken address\\n * @param account The user Account\\n * @return A struct containing the balances data\\n */\\n function vTokenBalances(VToken vToken, address account) public returns (VTokenBalances memory) {\\n uint256 balanceOf = vToken.balanceOf(account);\\n uint256 borrowBalanceCurrent = vToken.borrowBalanceCurrent(account);\\n uint256 balanceOfUnderlying = vToken.balanceOfUnderlying(account);\\n uint256 tokenBalance;\\n uint256 tokenAllowance;\\n\\n IERC20 underlying = IERC20(vToken.underlying());\\n tokenBalance = underlying.balanceOf(account);\\n tokenAllowance = underlying.allowance(account, address(vToken));\\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 Queries additional information for the pool\\n * @param poolRegistryAddress Address of the PoolRegistry\\n * @param venusPool The VenusPool Object from PoolRegistry\\n * @return Enriched PoolData\\n */\\n function getPoolDataFromVenusPool(\\n address poolRegistryAddress,\\n PoolRegistry.VenusPool memory venusPool\\n ) public view returns (PoolData memory) {\\n // Get tokens in the Pool\\n ComptrollerInterface comptrollerInstance = ComptrollerInterface(venusPool.comptroller);\\n\\n VToken[] memory vTokens = comptrollerInstance.getAllMarkets();\\n\\n VTokenMetadata[] memory vTokenMetadataItems = vTokenMetadataAll(vTokens);\\n\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n\\n PoolRegistry.VenusPoolMetaData memory venusPoolMetaData = poolRegistryInterface.getVenusPoolMetadata(\\n venusPool.comptroller\\n );\\n\\n ComptrollerViewInterface comptrollerViewInstance = ComptrollerViewInterface(venusPool.comptroller);\\n\\n PoolData memory poolData = PoolData({\\n name: venusPool.name,\\n creator: venusPool.creator,\\n comptroller: venusPool.comptroller,\\n blockPosted: venusPool.blockPosted,\\n timestampPosted: venusPool.timestampPosted,\\n category: venusPoolMetaData.category,\\n logoURL: venusPoolMetaData.logoURL,\\n description: venusPoolMetaData.description,\\n vTokens: vTokenMetadataItems,\\n priceOracle: address(comptrollerViewInstance.oracle()),\\n closeFactor: comptrollerViewInstance.closeFactorMantissa(),\\n liquidationIncentive: comptrollerViewInstance.liquidationIncentiveMantissa(),\\n minLiquidatableCollateral: comptrollerViewInstance.minLiquidatableCollateral()\\n });\\n\\n return poolData;\\n }\\n\\n /**\\n * @notice Returns the metadata of VToken\\n * @param vToken The address of vToken\\n * @return VTokenMetadata struct\\n */\\n function vTokenMetadata(VToken vToken) public view returns (VTokenMetadata memory) {\\n uint256 exchangeRateCurrent = vToken.exchangeRateStored();\\n address comptrollerAddress = address(vToken.comptroller());\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\\n (bool isListed, uint256 collateralFactorMantissa) = comptroller.markets(address(vToken));\\n\\n address underlyingAssetAddress = vToken.underlying();\\n uint256 underlyingDecimals = IERC20Metadata(underlyingAssetAddress).decimals();\\n\\n uint256 pausedActions;\\n for (uint8 i; i <= uint8(type(Action).max); ++i) {\\n uint256 paused = ComptrollerInterface(comptrollerAddress).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 supplyRatePerBlockOrTimestamp: vToken.supplyRatePerBlock(),\\n borrowRatePerBlockOrTimestamp: vToken.borrowRatePerBlock(),\\n reserveFactorMantissa: vToken.reserveFactorMantissa(),\\n supplyCaps: comptroller.supplyCaps(address(vToken)),\\n borrowCaps: comptroller.borrowCaps(address(vToken)),\\n totalBorrows: vToken.totalBorrows(),\\n totalReserves: vToken.totalReserves(),\\n totalSupply: vToken.totalSupply(),\\n totalCash: vToken.getCash(),\\n isListed: isListed,\\n collateralFactorMantissa: collateralFactorMantissa,\\n underlyingAssetAddress: underlyingAssetAddress,\\n vTokenDecimals: vToken.decimals(),\\n underlyingDecimals: underlyingDecimals,\\n pausedActions: pausedActions\\n });\\n }\\n\\n /**\\n * @notice Returns the metadata of all VTokens\\n * @param vTokens The list of vToken addresses\\n * @return An array of VTokenMetadata structs\\n */\\n function vTokenMetadataAll(VToken[] memory vTokens) public view returns (VTokenMetadata[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenMetadata[] memory res = new VTokenMetadata[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenMetadata(vTokens[i]);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Returns the price data for the underlying asset of the specified vToken\\n * @param vToken vToken address\\n * @return The price data for each asset\\n */\\n function vTokenUnderlyingPrice(VToken vToken) public view returns (VTokenUnderlyingPrice memory) {\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(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 function _calculateNotDistributedAwards(\\n address account,\\n VToken[] memory markets,\\n RewardsDistributor rewardsDistributor\\n ) internal view returns (PendingReward[] memory) {\\n PendingReward[] memory pendingRewards = new PendingReward[](markets.length);\\n\\n for (uint256 i; i < markets.length; ++i) {\\n // Market borrow and supply state we will modify update in-memory, in order to not modify storage\\n RewardTokenState memory borrowState;\\n RewardTokenState memory supplyState;\\n\\n if (isTimeBased) {\\n (\\n borrowState.index,\\n borrowState.blockOrTimestamp,\\n borrowState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenBorrowStateTimeBased(address(markets[i]));\\n (\\n supplyState.index,\\n supplyState.blockOrTimestamp,\\n supplyState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenSupplyStateTimeBased(address(markets[i]));\\n } else {\\n (\\n borrowState.index,\\n borrowState.blockOrTimestamp,\\n borrowState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenBorrowState(address(markets[i]));\\n (\\n supplyState.index,\\n supplyState.blockOrTimestamp,\\n supplyState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenSupplyState(address(markets[i]));\\n }\\n\\n Exp memory marketBorrowIndex = Exp({ mantissa: markets[i].borrowIndex() });\\n\\n // Update market supply and borrow index in-memory\\n updateMarketBorrowIndex(address(markets[i]), rewardsDistributor, borrowState, marketBorrowIndex);\\n updateMarketSupplyIndex(address(markets[i]), rewardsDistributor, supplyState);\\n\\n // Calculate pending rewards\\n uint256 borrowReward = calculateBorrowerReward(\\n address(markets[i]),\\n rewardsDistributor,\\n account,\\n borrowState,\\n marketBorrowIndex\\n );\\n uint256 supplyReward = calculateSupplierReward(\\n address(markets[i]),\\n rewardsDistributor,\\n account,\\n supplyState\\n );\\n\\n PendingReward memory pendingReward;\\n pendingReward.vTokenAddress = address(markets[i]);\\n pendingReward.amount = borrowReward + supplyReward;\\n pendingRewards[i] = pendingReward;\\n }\\n return pendingRewards;\\n }\\n\\n function updateMarketBorrowIndex(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n RewardTokenState memory borrowState,\\n Exp memory marketBorrowIndex\\n ) internal view {\\n uint256 borrowSpeed = rewardsDistributor.rewardTokenBorrowSpeeds(vToken);\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (\\n borrowState.lastRewardingBlockOrTimestamp > 0 &&\\n blockNumberOrTimestamp > borrowState.lastRewardingBlockOrTimestamp\\n ) {\\n blockNumberOrTimestamp = borrowState.lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, borrowState.blockOrTimestamp);\\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\\n // Remove the total earned interest rate since the opening of the market from total borrows\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, borrowSpeed);\\n Double memory ratio = borrowAmount > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\\n } else if (deltaBlocksOrTimestamp > 0) {\\n borrowState.blockOrTimestamp = blockNumberOrTimestamp;\\n }\\n }\\n\\n function updateMarketSupplyIndex(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n RewardTokenState memory supplyState\\n ) internal view {\\n uint256 supplySpeed = rewardsDistributor.rewardTokenSupplySpeeds(vToken);\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (\\n supplyState.lastRewardingBlockOrTimestamp > 0 &&\\n blockNumberOrTimestamp > supplyState.lastRewardingBlockOrTimestamp\\n ) {\\n blockNumberOrTimestamp = supplyState.lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, supplyState.blockOrTimestamp);\\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, supplySpeed);\\n Double memory ratio = supplyTokens > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\\n } else if (deltaBlocksOrTimestamp > 0) {\\n supplyState.blockOrTimestamp = blockNumberOrTimestamp;\\n }\\n }\\n\\n function calculateBorrowerReward(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n address borrower,\\n RewardTokenState memory borrowState,\\n Exp memory marketBorrowIndex\\n ) internal view returns (uint256) {\\n Double memory borrowIndex = Double({ mantissa: borrowState.index });\\n Double memory borrowerIndex = Double({\\n mantissa: rewardsDistributor.rewardTokenBorrowerIndex(vToken, borrower)\\n });\\n if (borrowerIndex.mantissa == 0 && borrowIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set\\n borrowerIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\\n }\\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n return borrowerDelta;\\n }\\n\\n function calculateSupplierReward(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n address supplier,\\n RewardTokenState memory supplyState\\n ) internal view returns (uint256) {\\n Double memory supplyIndex = Double({ mantissa: supplyState.index });\\n Double memory supplierIndex = Double({\\n mantissa: rewardsDistributor.rewardTokenSupplierIndex(vToken, supplier)\\n });\\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\\n // Covers the case where users supplied tokens before the market's supply state index was set\\n supplierIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\\n }\\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n return supplierDelta;\\n }\\n}\\n\",\"keccak256\":\"0xab04eb777ddc89a994e38e10ef0e776d165f1b7d98a4cf7715464366f931007a\",\"license\":\"BSD-3-Clause\"},\"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\",\"keccak256\":\"0x4c25e30635485d162177effa384eee51768b0141a567a0da16ff6ad673274166\",\"license\":\"BSD-3-Clause\"},\"contracts/Pool/PoolRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\nimport { PoolRegistryInterface } from \\\"./PoolRegistryInterface.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"../lib/validators.sol\\\";\\n\\n/**\\n * @title PoolRegistry\\n * @author Venus\\n * @notice The Isolated Pools architecture centers around the `PoolRegistry` contract. The `PoolRegistry` maintains a directory of isolated lending\\n * pools and can perform actions like creating and registering new pools, adding new markets to existing pools, setting and updating the pool's required\\n * metadata, and providing the getter methods to get information on the pools.\\n *\\n * Isolated lending has three main components: PoolRegistry, pools, and markets. The PoolRegistry is responsible for managing pools.\\n * It can create new pools, update pool metadata and manage markets within pools. PoolRegistry contains getter methods to get the details of\\n * any existing pool like `getVTokenForAsset` and `getPoolsSupportedByAsset`. It also contains methods for updating pool metadata (`updatePoolMetadata`)\\n * and setting pool name (`setPoolName`).\\n *\\n * The directory of pools is managed through two mappings: `_poolByComptroller` which is a hashmap with the comptroller address as the key and `VenusPool` as\\n * the value and `_poolsByID` which is an array of comptroller addresses. Individual pools can be accessed by calling `getPoolByComptroller` with the pool's\\n * comptroller address. `_poolsByID` is used to iterate through all of the pools.\\n *\\n * PoolRegistry also contains a map of asset addresses called `_supportedPools` that maps to an array of assets suppored by each pool. This array of pools by\\n * asset is retrieved by calling `getPoolsSupportedByAsset`.\\n *\\n * PoolRegistry registers new isolated pools in the directory with the `createRegistryPool` method. Isolated pools are composed of independent markets with\\n * specific assets and custom risk management configurations according to their markets.\\n */\\ncontract PoolRegistry is Ownable2StepUpgradeable, AccessControlledV8, PoolRegistryInterface {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n struct AddMarketInput {\\n VToken vToken;\\n uint256 collateralFactor;\\n uint256 liquidationThreshold;\\n uint256 initialSupply;\\n address vTokenReceiver;\\n uint256 supplyCap;\\n uint256 borrowCap;\\n }\\n\\n uint256 internal constant MAX_POOL_NAME_LENGTH = 100;\\n\\n /**\\n * @notice Maps pool's comptroller address to metadata.\\n */\\n mapping(address => VenusPoolMetaData) public metadata;\\n\\n /**\\n * @dev Maps pool ID to pool's comptroller address\\n */\\n mapping(uint256 => address) private _poolsByID;\\n\\n /**\\n * @dev Total number of pools created.\\n */\\n uint256 private _numberOfPools;\\n\\n /**\\n * @dev Maps comptroller address to Venus pool Index.\\n */\\n mapping(address => VenusPool) private _poolByComptroller;\\n\\n /**\\n * @dev Maps pool's comptroller address to asset to vToken.\\n */\\n mapping(address => mapping(address => address)) private _vTokens;\\n\\n /**\\n * @dev Maps asset to list of supported pools.\\n */\\n mapping(address => address[]) private _supportedPools;\\n\\n /**\\n * @notice Emitted when a new Venus pool is added to the directory.\\n */\\n event PoolRegistered(address indexed comptroller, VenusPool pool);\\n\\n /**\\n * @notice Emitted when a pool name is set.\\n */\\n event PoolNameSet(address indexed comptroller, string oldName, string newName);\\n\\n /**\\n * @notice Emitted when a pool metadata is updated.\\n */\\n event PoolMetadataUpdated(\\n address indexed comptroller,\\n VenusPoolMetaData oldMetadata,\\n VenusPoolMetaData newMetadata\\n );\\n\\n /**\\n * @notice Emitted when a Market is added to the pool.\\n */\\n event MarketAdded(address indexed comptroller, address indexed vTokenAddress);\\n\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor() {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializes the deployer to owner\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(address accessControlManager_) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n /**\\n * @notice Adds a new Venus pool to the directory\\n * @dev Price oracle must be configured before adding a pool\\n * @param name The name of the pool\\n * @param comptroller Pool's Comptroller contract\\n * @param closeFactor The pool's close factor (scaled by 1e18)\\n * @param liquidationIncentive The pool's liquidation incentive (scaled by 1e18)\\n * @param minLiquidatableCollateral Minimal collateral for regular (non-batch) liquidations flow\\n * @return index The index of the registered Venus pool\\n * @custom:error ZeroAddressNotAllowed is thrown when Comptroller address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\\n */\\n function addPool(\\n string calldata name,\\n Comptroller comptroller,\\n uint256 closeFactor,\\n uint256 liquidationIncentive,\\n uint256 minLiquidatableCollateral\\n ) external virtual returns (uint256 index) {\\n _checkAccessAllowed(\\\"addPool(string,address,uint256,uint256,uint256)\\\");\\n // Input validation\\n ensureNonzeroAddress(address(comptroller));\\n ensureNonzeroAddress(address(comptroller.oracle()));\\n\\n uint256 poolId = _registerPool(name, address(comptroller));\\n\\n // Set Venus pool parameters\\n comptroller.setCloseFactor(closeFactor);\\n comptroller.setLiquidationIncentive(liquidationIncentive);\\n comptroller.setMinLiquidatableCollateral(minLiquidatableCollateral);\\n\\n return poolId;\\n }\\n\\n /**\\n * @notice Add a market to an existing pool and then mint to provide initial supply\\n * @param input The structure describing the parameters for adding a market to a pool\\n * @custom:error ZeroAddressNotAllowed is thrown when vToken address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when vTokenReceiver address is zero\\n */\\n function addMarket(AddMarketInput memory input) external {\\n _checkAccessAllowed(\\\"addMarket(AddMarketInput)\\\");\\n ensureNonzeroAddress(address(input.vToken));\\n ensureNonzeroAddress(input.vTokenReceiver);\\n require(input.initialSupply > 0, \\\"PoolRegistry: initialSupply is zero\\\");\\n\\n VToken vToken = input.vToken;\\n address vTokenAddress = address(vToken);\\n address comptrollerAddress = address(vToken.comptroller());\\n Comptroller comptroller = Comptroller(comptrollerAddress);\\n address underlyingAddress = vToken.underlying();\\n IERC20Upgradeable underlying = IERC20Upgradeable(underlyingAddress);\\n\\n require(_poolByComptroller[comptrollerAddress].creator != address(0), \\\"PoolRegistry: Pool not registered\\\");\\n // solhint-disable-next-line reason-string\\n require(\\n _vTokens[comptrollerAddress][underlyingAddress] == address(0),\\n \\\"PoolRegistry: Market already added for asset comptroller combination\\\"\\n );\\n\\n comptroller.supportMarket(vToken);\\n comptroller.setCollateralFactor(vToken, input.collateralFactor, input.liquidationThreshold);\\n\\n uint256[] memory newSupplyCaps = new uint256[](1);\\n uint256[] memory newBorrowCaps = new uint256[](1);\\n VToken[] memory vTokens = new VToken[](1);\\n\\n newSupplyCaps[0] = input.supplyCap;\\n newBorrowCaps[0] = input.borrowCap;\\n vTokens[0] = vToken;\\n\\n comptroller.setMarketSupplyCaps(vTokens, newSupplyCaps);\\n comptroller.setMarketBorrowCaps(vTokens, newBorrowCaps);\\n\\n _vTokens[comptrollerAddress][underlyingAddress] = vTokenAddress;\\n _supportedPools[underlyingAddress].push(comptrollerAddress);\\n\\n uint256 amountToSupply = _transferIn(underlying, msg.sender, input.initialSupply);\\n underlying.forceApprove(vTokenAddress, 0);\\n underlying.forceApprove(vTokenAddress, amountToSupply);\\n vToken.mintBehalf(input.vTokenReceiver, amountToSupply);\\n\\n emit MarketAdded(comptrollerAddress, vTokenAddress);\\n }\\n\\n /**\\n * @notice Modify existing Venus pool name\\n * @param comptroller Pool's Comptroller\\n * @param name New pool name\\n */\\n function setPoolName(address comptroller, string calldata name) external {\\n _checkAccessAllowed(\\\"setPoolName(address,string)\\\");\\n _ensureValidName(name);\\n VenusPool storage pool = _poolByComptroller[comptroller];\\n string memory oldName = pool.name;\\n pool.name = name;\\n emit PoolNameSet(comptroller, oldName, name);\\n }\\n\\n /**\\n * @notice Update metadata of an existing pool\\n * @param comptroller Pool's Comptroller\\n * @param metadata_ New pool metadata\\n */\\n function updatePoolMetadata(address comptroller, VenusPoolMetaData calldata metadata_) external {\\n _checkAccessAllowed(\\\"updatePoolMetadata(address,VenusPoolMetaData)\\\");\\n VenusPoolMetaData memory oldMetadata = metadata[comptroller];\\n metadata[comptroller] = metadata_;\\n emit PoolMetadataUpdated(comptroller, oldMetadata, metadata_);\\n }\\n\\n /**\\n * @notice Returns arrays of all Venus pools' data\\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\\n * @return A list of all pools within PoolRegistry, with details for each pool\\n */\\n function getAllPools() external view override returns (VenusPool[] memory) {\\n uint256 numberOfPools_ = _numberOfPools; // storage load to save gas\\n VenusPool[] memory _pools = new VenusPool[](numberOfPools_);\\n for (uint256 i = 1; i <= numberOfPools_; ++i) {\\n address comptroller = _poolsByID[i];\\n _pools[i - 1] = (_poolByComptroller[comptroller]);\\n }\\n return _pools;\\n }\\n\\n /**\\n * @param comptroller The comptroller proxy address associated to the pool\\n * @return Returns Venus pool\\n */\\n function getPoolByComptroller(address comptroller) external view override returns (VenusPool memory) {\\n return _poolByComptroller[comptroller];\\n }\\n\\n /**\\n * @param comptroller comptroller of Venus pool\\n * @return Returns Metadata of Venus pool\\n */\\n function getVenusPoolMetadata(address comptroller) external view override returns (VenusPoolMetaData memory) {\\n return metadata[comptroller];\\n }\\n\\n function getVTokenForAsset(address comptroller, address asset) external view override returns (address) {\\n return _vTokens[comptroller][asset];\\n }\\n\\n function getPoolsSupportedByAsset(address asset) external view override returns (address[] memory) {\\n return _supportedPools[asset];\\n }\\n\\n /**\\n * @dev Adds a new Venus pool to the directory (without checking msg.sender).\\n * @param name The name of the pool\\n * @param comptroller The pool's Comptroller proxy contract address\\n * @return The index of the registered Venus pool\\n */\\n function _registerPool(string calldata name, address comptroller) internal returns (uint256) {\\n VenusPool storage storedPool = _poolByComptroller[comptroller];\\n\\n require(storedPool.creator == address(0), \\\"PoolRegistry: Pool already exists in the directory.\\\");\\n _ensureValidName(name);\\n\\n ++_numberOfPools;\\n uint256 numberOfPools_ = _numberOfPools; // cache on stack to save storage read gas\\n\\n VenusPool memory pool = VenusPool(name, msg.sender, comptroller, block.number, block.timestamp);\\n\\n _poolsByID[numberOfPools_] = comptroller;\\n _poolByComptroller[comptroller] = pool;\\n\\n emit PoolRegistered(comptroller, pool);\\n return numberOfPools_;\\n }\\n\\n function _transferIn(IERC20Upgradeable token, address from, uint256 amount) internal returns (uint256) {\\n uint256 balanceBefore = token.balanceOf(address(this));\\n token.safeTransferFrom(from, address(this), amount);\\n uint256 balanceAfter = token.balanceOf(address(this));\\n return balanceAfter - balanceBefore;\\n }\\n\\n function _ensureValidName(string calldata name) internal pure {\\n require(bytes(name).length <= MAX_POOL_NAME_LENGTH, \\\"Pool's name is too large\\\");\\n }\\n}\\n\",\"keccak256\":\"0xafbb871f7b4db3ef439d846baa5f18a136192f9b43ea695c81262a77b06c4b25\",\"license\":\"BSD-3-Clause\"},\"contracts/Pool/PoolRegistryInterface.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 /**\\n * @notice Struct for a Venus interest rate pool metadata.\\n */\\n struct VenusPoolMetaData {\\n string category;\\n string logoURL;\\n string description;\\n }\\n\\n /// @notice Get all pools in PoolRegistry\\n function getAllPools() external view returns (VenusPool[] memory);\\n\\n /// @notice Get a pool by comptroller address\\n function getPoolByComptroller(address comptroller) external view returns (VenusPool memory);\\n\\n /// @notice Get the address of the VToken contract in the Pool where the underlying token is the provided 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 /// @notice Get the metadata of a Pool by comptroller address\\n function getVenusPoolMetadata(address comptroller) external view returns (VenusPoolMetaData memory);\\n}\\n\",\"keccak256\":\"0x7b39cda3b372a686501ce3c2aad288c6af410148110318249d75d4516729c92c\",\"license\":\"BSD-3-Clause\"},\"contracts/Rewards/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\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 { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"../MaxLoopsLimitHelper.sol\\\";\\nimport { RewardsDistributorStorage } from \\\"./RewardsDistributorStorage.sol\\\";\\n\\n/**\\n * @title `RewardsDistributor`\\n * @author Venus\\n * @notice Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol.\\n * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward\\n * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool.\\n * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward\\n * token to be released each slot (block or second) for borrowers and suppliers, which is distributed based on a user\\u2019s percentage of the borrows or supplies\\n * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting\\n * their contributor reward token speed, which similarly allocates a fixed amount of reward token per slot (block or second).\\n *\\n * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed\\n * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized\\n * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\\n */\\ncontract RewardsDistributor is\\n ExponentialNoError,\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n MaxLoopsLimitHelper,\\n RewardsDistributorStorage,\\n TimeManagerV8\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice The initial REWARD TOKEN index for a market\\n uint224 public constant INITIAL_INDEX = 1e36;\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a supplier\\n event DistributedSupplierRewardToken(\\n VToken indexed vToken,\\n address indexed supplier,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenSupplyIndex\\n );\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a borrower\\n event DistributedBorrowerRewardToken(\\n VToken indexed vToken,\\n address indexed borrower,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenBorrowIndex\\n );\\n\\n /// @notice Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when REWARD TOKEN is granted by admin\\n event RewardTokenGranted(address indexed recipient, uint256 amount);\\n\\n /// @notice Emitted when a new REWARD TOKEN speed is set for a contributor\\n event ContributorRewardTokenSpeedUpdated(address indexed contributor, uint256 newSpeed);\\n\\n /// @notice Emitted when a market is initialized\\n event MarketInitialized(address indexed vToken);\\n\\n /// @notice Emitted when a reward token supply index is updated\\n event RewardTokenSupplyIndexUpdated(address indexed vToken);\\n\\n /// @notice Emitted when a reward token borrow index is updated\\n event RewardTokenBorrowIndexUpdated(address indexed vToken, Exp marketBorrowIndex);\\n\\n /// @notice Emitted when a reward for contributor is updated\\n event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued);\\n\\n /// @notice Emitted when a reward token last rewarding block for supply is updated\\n event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding block for borrow is updated\\n event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding timestamp for supply is updated\\n event SupplyLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\\n\\n /// @notice Emitted when a reward token last rewarding timestamp for borrow is updated\\n event BorrowLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\\n\\n modifier onlyComptroller() {\\n require(address(comptroller) == msg.sender, \\\"Only comptroller can call this function\\\");\\n _;\\n }\\n\\n /**\\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice RewardsDistributor initializer\\n * @dev Initializes the deployer to owner\\n * @param comptroller_ Comptroller to attach the reward distributor to\\n * @param rewardToken_ Reward token to distribute\\n * @param loopsLimit_ Maximum number of iterations for the loops in this contract\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(\\n Comptroller comptroller_,\\n IERC20Upgradeable rewardToken_,\\n uint256 loopsLimit_,\\n address accessControlManager_\\n ) external initializer {\\n comptroller = comptroller_;\\n rewardToken = rewardToken_;\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n\\n _setMaxLoopsLimit(loopsLimit_);\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken\\n * @param vToken The address of the vToken to be initialized\\n * @custom:event MarketInitialized emits on success\\n * @custom:access Only Comptroller\\n */\\n function initializeMarket(address vToken) external onlyComptroller {\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n isTimeBased\\n ? _initializeMarketTimestampBased(vToken, blockNumberOrTimestamp)\\n : _initializeMarketBlockBased(vToken, safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\"));\\n\\n emit MarketInitialized(vToken);\\n }\\n\\n /*** Reward Token Distribution ***/\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them\\n * Borrowers will begin to accrue after the first interaction with the protocol.\\n * @dev This function should only be called when the user has a borrow position in the market\\n * (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook)\\n * We avoid an external call to check if they are in the market to save gas because this function is called in many places\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function distributeBorrowerRewardToken(\\n address vToken,\\n address borrower,\\n Exp memory marketBorrowIndex\\n ) external onlyComptroller {\\n _distributeBorrowerRewardToken(vToken, borrower, marketBorrowIndex);\\n }\\n\\n function updateRewardTokenSupplyIndex(address vToken) external onlyComptroller {\\n _updateRewardTokenSupplyIndex(vToken);\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the recipient\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\\n * @param recipient The address of the recipient to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n */\\n function grantRewardToken(address recipient, uint256 amount) external onlyOwner {\\n uint256 amountLeft = _grantRewardToken(recipient, amount);\\n require(amountLeft == 0, \\\"insufficient rewardToken for grant\\\");\\n emit RewardTokenGranted(recipient, amount);\\n }\\n\\n function updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) external onlyComptroller {\\n _updateRewardTokenBorrowIndex(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN borrow and supply speeds for the specified markets\\n * @param vTokens The markets whose REWARD TOKEN speed to update\\n * @param supplySpeeds New supply-side REWARD TOKEN speed for the corresponding market\\n * @param borrowSpeeds New borrow-side REWARD TOKEN speed for the corresponding market\\n */\\n function setRewardTokenSpeeds(\\n VToken[] memory vTokens,\\n uint256[] memory supplySpeeds,\\n uint256[] memory borrowSpeeds\\n ) external {\\n _checkAccessAllowed(\\\"setRewardTokenSpeeds(address[],uint256[],uint256[])\\\");\\n uint256 numTokens = vTokens.length;\\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \\\"invalid setRewardTokenSpeeds\\\");\\n\\n for (uint256 i; i < numTokens; ++i) {\\n _setRewardTokenSpeed(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for the specified markets, used when contract is block based\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market\\n * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market\\n */\\n function setLastRewardingBlocks(\\n VToken[] calldata vTokens,\\n uint32[] calldata supplyLastRewardingBlocks,\\n uint32[] calldata borrowLastRewardingBlocks\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlocks(address[],uint32[],uint32[])\\\");\\n require(!isTimeBased, \\\"Block-based operation only\\\");\\n\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length,\\n \\\"RewardsDistributor::setLastRewardingBlocks invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlock(vTokens[i], supplyLastRewardingBlocks[i], borrowLastRewardingBlocks[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block timestamp for the specified markets, used when contract is time based\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlockTimestamps New supply-side REWARD TOKEN last rewarding block timestamp for the corresponding market\\n * @param borrowLastRewardingBlockTimestamps New borrow-side REWARD TOKEN last rewarding block timestamp for the corresponding market\\n */\\n function setLastRewardingBlockTimestamps(\\n VToken[] calldata vTokens,\\n uint256[] calldata supplyLastRewardingBlockTimestamps,\\n uint256[] calldata borrowLastRewardingBlockTimestamps\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlockTimestamps(address[],uint256[],uint256[])\\\");\\n require(isTimeBased, \\\"Time-based operation only\\\");\\n\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlockTimestamps.length &&\\n numTokens == borrowLastRewardingBlockTimestamps.length,\\n \\\"RewardsDistributor::setLastRewardingBlockTimestamps invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlockTimestamp(\\n vTokens[i],\\n supplyLastRewardingBlockTimestamps[i],\\n borrowLastRewardingBlockTimestamps[i]\\n );\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single contributor\\n * @param contributor The contributor whose REWARD TOKEN speed to update\\n * @param rewardTokenSpeed New REWARD TOKEN speed for contributor\\n */\\n function setContributorRewardTokenSpeed(address contributor, uint256 rewardTokenSpeed) external onlyOwner {\\n // note that REWARD TOKEN speed could be set to 0 to halt liquidity rewards for a contributor\\n updateContributorRewards(contributor);\\n if (rewardTokenSpeed == 0) {\\n // release storage\\n delete lastContributorBlock[contributor];\\n } else {\\n lastContributorBlock[contributor] = getBlockNumberOrTimestamp();\\n }\\n rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed;\\n\\n emit ContributorRewardTokenSpeedUpdated(contributor, rewardTokenSpeed);\\n }\\n\\n function distributeSupplierRewardToken(address vToken, address supplier) external onlyComptroller {\\n _distributeSupplierRewardToken(vToken, supplier);\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in all markets\\n * @param holder The address to claim REWARD TOKEN for\\n */\\n function claimRewardToken(address holder) external {\\n return claimRewardToken(holder, comptroller.getAllMarkets());\\n }\\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) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Calculate additional accrued REWARD TOKEN for a contributor since last accrual\\n * @param contributor The address to calculate contributor rewards for\\n */\\n function updateContributorRewards(address contributor) public {\\n uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, lastContributorBlock[contributor]);\\n if (deltaBlocksOrTimestamp > 0 && rewardTokenSpeed > 0) {\\n uint256 newAccrued = mul_(deltaBlocksOrTimestamp, rewardTokenSpeed);\\n uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued);\\n\\n rewardTokenAccrued[contributor] = contributorAccrued;\\n lastContributorBlock[contributor] = blockNumberOrTimestamp;\\n\\n emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]);\\n }\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in the specified markets\\n * @param holder The address to claim REWARD TOKEN for\\n * @param vTokens The list of markets to claim REWARD TOKEN in\\n */\\n function claimRewardToken(address holder, VToken[] memory vTokens) public {\\n uint256 vTokensCount = vTokens.length;\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n VToken vToken = vTokens[i];\\n require(comptroller.isMarketListed(vToken), \\\"market must be listed\\\");\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n _distributeBorrowerRewardToken(address(vToken), holder, borrowIndex);\\n _updateRewardTokenSupplyIndex(address(vToken));\\n _distributeSupplierRewardToken(address(vToken), holder);\\n }\\n rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for a single market.\\n * @param vToken market's whose reward token last rewarding block to be updated\\n * @param supplyLastRewardingBlock New supply-side REWARD TOKEN last rewarding block for market\\n * @param borrowLastRewardingBlock New borrow-side REWARD TOKEN last rewarding block for market\\n */\\n function _setLastRewardingBlock(\\n VToken vToken,\\n uint32 supplyLastRewardingBlock,\\n uint32 borrowLastRewardingBlock\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockNumber = getBlockNumberOrTimestamp();\\n\\n require(supplyLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n require(borrowLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n\\n uint32 currentSupplyLastRewardingBlock = rewardTokenSupplyState[address(vToken)].lastRewardingBlock;\\n uint32 currentBorrowLastRewardingBlock = rewardTokenBorrowState[address(vToken)].lastRewardingBlock;\\n\\n require(\\n currentSupplyLastRewardingBlock == 0 || currentSupplyLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlock == 0 || currentBorrowLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlock != supplyLastRewardingBlock) {\\n rewardTokenSupplyState[address(vToken)].lastRewardingBlock = supplyLastRewardingBlock;\\n emit SupplyLastRewardingBlockUpdated(address(vToken), supplyLastRewardingBlock);\\n }\\n\\n if (currentBorrowLastRewardingBlock != borrowLastRewardingBlock) {\\n rewardTokenBorrowState[address(vToken)].lastRewardingBlock = borrowLastRewardingBlock;\\n emit BorrowLastRewardingBlockUpdated(address(vToken), borrowLastRewardingBlock);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding timestamp for a single market.\\n * @param vToken market's whose reward token last rewarding timestamp to be updated\\n * @param supplyLastRewardingBlockTimestamp New supply-side REWARD TOKEN last rewarding timestamp for market\\n * @param borrowLastRewardingBlockTimestamp New borrow-side REWARD TOKEN last rewarding timestamp for market\\n */\\n function _setLastRewardingBlockTimestamp(\\n VToken vToken,\\n uint256 supplyLastRewardingBlockTimestamp,\\n uint256 borrowLastRewardingBlockTimestamp\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockTimestamp = getBlockNumberOrTimestamp();\\n\\n require(\\n supplyLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"setting last rewarding timestamp in the past is not allowed\\\"\\n );\\n require(\\n borrowLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"setting last rewarding timestamp in the past is not allowed\\\"\\n );\\n\\n uint256 currentSupplyLastRewardingBlockTimestamp = rewardTokenSupplyStateTimeBased[address(vToken)]\\n .lastRewardingTimestamp;\\n uint256 currentBorrowLastRewardingBlockTimestamp = rewardTokenBorrowStateTimeBased[address(vToken)]\\n .lastRewardingTimestamp;\\n\\n require(\\n currentSupplyLastRewardingBlockTimestamp == 0 || currentSupplyLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlockTimestamp == 0 || currentBorrowLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlockTimestamp != supplyLastRewardingBlockTimestamp) {\\n rewardTokenSupplyStateTimeBased[address(vToken)].lastRewardingTimestamp = supplyLastRewardingBlockTimestamp;\\n emit SupplyLastRewardingBlockTimestampUpdated(address(vToken), supplyLastRewardingBlockTimestamp);\\n }\\n\\n if (currentBorrowLastRewardingBlockTimestamp != borrowLastRewardingBlockTimestamp) {\\n rewardTokenBorrowStateTimeBased[address(vToken)].lastRewardingTimestamp = borrowLastRewardingBlockTimestamp;\\n emit BorrowLastRewardingBlockTimestampUpdated(address(vToken), borrowLastRewardingBlockTimestamp);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single market.\\n * @param vToken market's whose reward token rate to be updated\\n * @param supplySpeed New supply-side REWARD TOKEN speed for market\\n * @param borrowSpeed New borrow-side REWARD TOKEN speed for market\\n */\\n function _setRewardTokenSpeed(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n if (rewardTokenSupplySpeeds[address(vToken)] != supplySpeed) {\\n // Supply speed updated so let's update supply state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n _updateRewardTokenSupplyIndex(address(vToken));\\n\\n // Update speed and emit event\\n rewardTokenSupplySpeeds[address(vToken)] = supplySpeed;\\n emit RewardTokenSupplySpeedUpdated(vToken, supplySpeed);\\n }\\n\\n if (rewardTokenBorrowSpeeds[address(vToken)] != borrowSpeed) {\\n // Borrow speed updated so let's update borrow state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n\\n // Update speed and emit event\\n rewardTokenBorrowSpeeds[address(vToken)] = borrowSpeed;\\n emit RewardTokenBorrowSpeedUpdated(vToken, borrowSpeed);\\n }\\n }\\n\\n /**\\n * @notice Calculate REWARD TOKEN 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 REWARD TOKEN to\\n */\\n function _distributeSupplierRewardToken(address vToken, address supplier) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\\n\\n uint256 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\\n uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier];\\n\\n // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenSupplierIndex[vToken][supplier] = supplyIndex;\\n\\n if (supplierIndex == 0 && supplyIndex >= INITIAL_INDEX) {\\n // Covers the case where users supplied tokens before the market's supply state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when supplier rewards were first\\n // set for the market.\\n supplierIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per vToken accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\\n\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerVToken\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n\\n uint256 supplierAccrued = add_(rewardTokenAccrued[supplier], supplierDelta);\\n rewardTokenAccrued[supplier] = supplierAccrued;\\n\\n emit DistributedSupplierRewardToken(VToken(vToken), supplier, supplierDelta, supplierAccrued, supplyIndex);\\n }\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them.\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function _distributeBorrowerRewardToken(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\\n\\n uint256 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\\n uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower];\\n\\n // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenBorrowerIndex[vToken][borrower] = borrowIndex;\\n\\n if (borrowerIndex == 0 && borrowIndex >= INITIAL_INDEX) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when borrower rewards were first\\n // set for the market.\\n borrowerIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per borrowed unit accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\\n\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerBorrowedUnit\\n if (borrowerAmount != 0) {\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n\\n uint256 borrowerAccrued = add_(rewardTokenAccrued[borrower], borrowerDelta);\\n rewardTokenAccrued[borrower] = borrowerAccrued;\\n\\n emit DistributedBorrowerRewardToken(VToken(vToken), borrower, borrowerDelta, borrowerAccrued, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the user.\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all.\\n * @param user The address of the user to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n * @return The amount of REWARD TOKEN which was NOT transferred to the user\\n */\\n function _grantRewardToken(address user, uint256 amount) internal returns (uint256) {\\n uint256 rewardTokenRemaining = rewardToken.balanceOf(address(this));\\n if (amount > 0 && amount <= rewardTokenRemaining) {\\n rewardToken.safeTransfer(user, amount);\\n return 0;\\n }\\n return amount;\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the supply index\\n * @param vToken The market whose supply index to update\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenSupplyIndex(address vToken) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\\n\\n uint256 supplySpeed = rewardTokenSupplySpeeds[vToken];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (!isTimeBased) {\\n safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\");\\n }\\n\\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\\n ? supplyStateTimeBased.lastRewardingTimestamp\\n : uint256(supplyState.lastRewardingBlock);\\n\\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(\\n blockNumberOrTimestamp,\\n (isTimeBased ? supplyStateTimeBased.timestamp : uint256(supplyState.block))\\n );\\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, supplySpeed);\\n Double memory ratio = supplyTokens > 0\\n ? fraction(accruedSinceUpdate, supplyTokens)\\n : Double({ mantissa: 0 });\\n uint224 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\\n uint224 index = safe224(\\n add_(Double({ mantissa: supplyIndex }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n\\n if (isTimeBased) {\\n supplyStateTimeBased.index = index;\\n supplyStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n supplyState.index = index;\\n supplyState.block = uint32(blockNumberOrTimestamp);\\n }\\n } else if (deltaBlocksOrTimestamp > 0) {\\n isTimeBased ? supplyStateTimeBased.timestamp = blockNumberOrTimestamp : supplyState.block = uint32(\\n blockNumberOrTimestamp\\n );\\n }\\n\\n emit RewardTokenSupplyIndexUpdated(vToken);\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the borrow index\\n * @param vToken The market whose borrow index to update\\n * @param marketBorrowIndex The current global borrow index of vToken\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\\n\\n uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (!isTimeBased) {\\n safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\");\\n }\\n\\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\\n ? borrowStateTimeBased.lastRewardingTimestamp\\n : uint256(borrowState.lastRewardingBlock);\\n\\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(\\n blockNumberOrTimestamp,\\n (isTimeBased ? borrowStateTimeBased.timestamp : uint256(borrowState.block))\\n );\\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, borrowSpeed);\\n Double memory ratio = borrowAmount > 0\\n ? fraction(accruedSinceUpdate, borrowAmount)\\n : Double({ mantissa: 0 });\\n uint224 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\\n uint224 index = safe224(\\n add_(Double({ mantissa: borrowIndex }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n\\n if (isTimeBased) {\\n borrowStateTimeBased.index = index;\\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n borrowState.index = index;\\n borrowState.block = uint32(blockNumberOrTimestamp);\\n }\\n } else if (deltaBlocksOrTimestamp > 0) {\\n if (isTimeBased) {\\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n borrowState.block = uint32(blockNumberOrTimestamp);\\n }\\n }\\n\\n emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken called when contract is block-based\\n * @param vToken The address of the vToken to be initialized\\n * @param blockNumber current block number\\n */\\n function _initializeMarketBlockBased(address vToken, uint32 blockNumber) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n RewardToken storage borrowState = rewardTokenBorrowState[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 = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block numbers\\n */\\n supplyState.block = borrowState.block = blockNumber;\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken called when contract is time-based\\n * @param vToken The address of the vToken to be initialized\\n * @param blockTimestamp current block timestamp\\n */\\n function _initializeMarketTimestampBased(address vToken, uint256 blockTimestamp) internal {\\n TimeBasedRewardToken storage supplyState = rewardTokenSupplyStateTimeBased[vToken];\\n TimeBasedRewardToken storage borrowState = rewardTokenBorrowStateTimeBased[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 = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block timestamp\\n */\\n supplyState.timestamp = borrowState.timestamp = blockTimestamp;\\n }\\n}\\n\",\"keccak256\":\"0x3cc824e59c923cfe25c4f1a875959b7e9410cde8e73cd405de13f301298c697f\",\"license\":\"BSD-3-Clause\"},\"contracts/Rewards/RewardsDistributorStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\n\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\n\\n/**\\n * @title RewardsDistributorStorage\\n * @author Venus\\n * @dev Storage for RewardsDistributor\\n */\\ncontract RewardsDistributorStorage {\\n struct RewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number the index was last updated at\\n uint32 block;\\n // The block number at which to stop rewards\\n uint32 lastRewardingBlock;\\n }\\n\\n struct TimeBasedRewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block timestamp the index was last updated at\\n uint256 timestamp;\\n // The block timestamp at which to stop rewards\\n uint256 lastRewardingTimestamp;\\n }\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => RewardToken) public rewardTokenSupplyState;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex;\\n\\n /// @notice The REWARD TOKEN accrued but not yet transferred to each user\\n mapping(address => uint256) public rewardTokenAccrued;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding borrow market per slot (block or second)\\n mapping(address => uint256) public rewardTokenBorrowSpeeds;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding supply market per slot (block or second)\\n mapping(address => uint256) public rewardTokenSupplySpeeds;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => RewardToken) public rewardTokenBorrowState;\\n\\n /// @notice The portion of REWARD TOKEN that each contributor receives per slot (block or second)\\n mapping(address => uint256) public rewardTokenContributorSpeeds;\\n\\n /// @notice Last slot (block or second) at which a contributor's REWARD TOKEN rewards have been allocated\\n mapping(address => uint256) public lastContributorBlock;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex;\\n\\n Comptroller internal comptroller;\\n\\n IERC20Upgradeable public rewardToken;\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => TimeBasedRewardToken) public rewardTokenSupplyStateTimeBased;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => TimeBasedRewardToken) public rewardTokenBorrowStateTimeBased;\\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[37] private __gap;\\n}\\n\",\"keccak256\":\"0x70e5015a78a2acf95277949c8b4796e10b9ac194130be006d5e5217e158070c0\",\"license\":\"BSD-3-Clause\"},\"contracts/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\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 { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"@venusprotocol/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\\\";\\n\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { ComptrollerInterface, ComptrollerViewInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"./ErrorReporter.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title VToken\\n * @author Venus\\n * @notice Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview,\\n * each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of\\n * the pool. The main actions a user regularly interacts with in a market are:\\n\\n- mint/redeem of vTokens;\\n- transfer of vTokens;\\n- borrow/repay a loan on an underlying asset;\\n- liquidate a borrow or liquidate/heal an account.\\n\\n * A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`.\\n * The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted\\n * `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken`\\n * as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that\\n * a user may borrow up to a portion of their collateral determined by the market\\u2019s collateral factor. However, if their borrowed amount exceeds an amount\\n * calculated using the market\\u2019s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also\\n * pay off interest accrued on the borrow.\\n * \\n * The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller`\\n * and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a\\n * total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`.\\n * Both functions settle all of an account\\u2019s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of\\n * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\\n */\\ncontract VToken is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n VTokenInterface,\\n ExponentialNoError,\\n TokenErrorReporter,\\n TimeManagerV8\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5%\\n\\n // Maximum fraction of interest that can be set aside for reserves\\n uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18;\\n\\n // Maximum borrow rate that can ever be applied per slot(block or second)\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n uint256 internal immutable MAX_BORROW_RATE_MANTISSA;\\n\\n /**\\n * Reentrancy Guard **\\n */\\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 * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @param maxBorrowRateMantissa_ The maximum value of borrowing rate mantissa\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(\\n bool timeBased_,\\n uint256 blocksPerYear_,\\n uint256 maxBorrowRateMantissa_\\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n require(maxBorrowRateMantissa_ <= 1e18, \\\"Max borrow rate must be <= 1e18\\\");\\n\\n MAX_BORROW_RATE_MANTISSA = maxBorrowRateMantissa_;\\n _disableInitializers();\\n }\\n\\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_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n */\\n function initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) external initializer {\\n ensureNonzeroAddress(admin_);\\n\\n // Initialize the market\\n _initialize(\\n underlying_,\\n comptroller_,\\n interestRateModel_,\\n initialExchangeRateMantissa_,\\n name_,\\n symbol_,\\n decimals_,\\n admin_,\\n accessControlManager_,\\n riskManagement,\\n reserveFactorMantissa_\\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 * @return success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, msg.sender, dst, amount);\\n return true;\\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 success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, src, dst, amount);\\n return true;\\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 (uint256.max means infinite)\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Increase approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param addedValue The number of additional tokens spender can transfer\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function increaseAllowance(address spender, uint256 addedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 newAllowance = transferAllowances[src][spender];\\n newAllowance += addedValue;\\n transferAllowances[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n return true;\\n }\\n\\n /**\\n * @notice Decreases approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param subtractedValue The number of tokens to remove from total approval\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 currentAllowance = transferAllowances[src][spender];\\n require(currentAllowance >= subtractedValue, \\\"decreased allowance below zero\\\");\\n unchecked {\\n currentAllowance -= subtractedValue;\\n }\\n\\n transferAllowances[src][spender] = currentAllowance;\\n\\n emit Approval(src, spender, currentAllowance);\\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 amount The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint256) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return totalBorrows The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\\n accrueInterest();\\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 borrowBalance The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n return _borrowBalanceStored(account);\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function mint(uint256 mintAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _mintFresh(msg.sender, msg.sender, mintAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param minter User whom the supply will be attributed to\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when minter address is zero\\n */\\n function mintBehalf(address minter, uint256 mintAmount) external override nonReentrant returns (uint256) {\\n ensureNonzeroAddress(minter);\\n\\n accrueInterest();\\n\\n _mintFresh(msg.sender, minter, mintAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function redeem(uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _redeemFresh(msg.sender, msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function redeemBehalf(address redeemer, uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n _ensureSenderIsDelegateOf(redeemer);\\n\\n accrueInterest();\\n\\n _redeemFresh(redeemer, msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\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 receive from redeeming vTokens\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n */\\n function redeemUnderlying(uint256 redeemAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _redeemFresh(msg.sender, msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function redeemUnderlyingBehalf(\\n address redeemer,\\n uint256 redeemAmount\\n ) external override nonReentrant returns (uint256) {\\n _ensureSenderIsDelegateOf(redeemer);\\n\\n accrueInterest();\\n\\n _redeemFresh(redeemer, msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function borrow(uint256 borrowAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _borrowFresh(msg.sender, msg.sender, borrowAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error DelegateNotApproved is thrown if caller is not approved delegate\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function borrowBehalf(address borrower, uint256 borrowAmount) external override returns (uint256) {\\n _ensureSenderIsDelegateOf(borrower);\\n accrueInterest();\\n\\n _borrowFresh(borrower, msg.sender, borrowAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrow(uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n return NO_ERROR;\\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, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _repayBorrowFresh(msg.sender, borrower, repayAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Not restricted\\n */\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external override returns (uint256) {\\n _liquidateBorrow(msg.sender, borrower, repayAmount, vTokenCollateral, false);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice sets protocol share accumulated from liquidations\\n * @dev must be equal or less than liquidation incentive - 1\\n * @param newProtocolSeizeShareMantissa_ new protocol share mantissa\\n * @custom:event Emits NewProtocolSeizeShare event on success\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error ProtocolSeizeShareTooBig is thrown when the new seize share is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa_) external {\\n _checkAccessAllowed(\\\"setProtocolSeizeShare(uint256)\\\");\\n uint256 liquidationIncentive = ComptrollerViewInterface(address(comptroller)).liquidationIncentiveMantissa();\\n if (newProtocolSeizeShareMantissa_ + MANTISSA_ONE > liquidationIncentive) {\\n revert ProtocolSeizeShareTooBig();\\n }\\n\\n uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\\n protocolSeizeShareMantissa = newProtocolSeizeShareMantissa_;\\n emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa_);\\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 * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n * @custom:event Emits NewReserveFactor event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant {\\n _checkAccessAllowed(\\\"setReserveFactor(uint256)\\\");\\n\\n accrueInterest();\\n _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to the protocol reserve contract\\n * @dev Gracefully return if reserves already reduced in accrueInterest\\n * @param reduceAmount Amount of reduction to reserves\\n * @custom:event Emits ReservesReduced event; may emit AccrueInterest\\n * @custom:error ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash\\n * @custom:error ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\\n * @custom:access Not restricted\\n */\\n function reduceReserves(uint256 reduceAmount) external override nonReentrant {\\n accrueInterest();\\n if (reduceReservesBlockNumber == getBlockNumberOrTimestamp()) return;\\n _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice The sender adds to reserves.\\n * @param addAmount The amount of underlying token to add as reserves\\n * @custom:event Emits ReservesAdded event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function addReserves(uint256 addAmount) external override nonReentrant {\\n accrueInterest();\\n _addReservesFresh(addAmount);\\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 * @custom:event Emits NewMarketInterestRateModel event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external override {\\n _checkAccessAllowed(\\\"setInterestRateModel(address)\\\");\\n\\n accrueInterest();\\n _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially\\n * \\\"forgiving\\\" the borrower. Healing is a situation that should rarely happen. However, some pools\\n * may list risky assets or be configured improperly \\u2013 we want to still handle such cases gracefully.\\n * We assume that Comptroller does the seizing, so this function is only available to Comptroller.\\n * @dev This function does not call any Comptroller hooks (like \\\"healAllowed\\\"), because we assume\\n * the Comptroller does all the necessary checks before calling this function.\\n * @param payer account who repays the debt\\n * @param borrower account to heal\\n * @param repayAmount amount to repay\\n * @custom:event Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\\n * @custom:error HealBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:access Only Comptroller\\n */\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external override nonReentrant {\\n if (repayAmount != 0) {\\n comptroller.preRepayHook(address(this), borrower);\\n }\\n\\n if (msg.sender != address(comptroller)) {\\n revert HealBorrowUnauthorized();\\n }\\n\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 totalBorrowsNew = totalBorrows;\\n\\n uint256 actualRepayAmount;\\n if (repayAmount != 0) {\\n // _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // We violate checks-effects-interactions here to account for tokens that take transfer fees\\n actualRepayAmount = _doTransferIn(payer, repayAmount);\\n totalBorrowsNew = totalBorrowsNew - actualRepayAmount;\\n emit RepayBorrow(\\n payer,\\n borrower,\\n actualRepayAmount,\\n accountBorrowsPrev - actualRepayAmount,\\n totalBorrowsNew\\n );\\n }\\n\\n // The transaction will fail if trying to repay too much\\n uint256 badDebtDelta = accountBorrowsPrev - actualRepayAmount;\\n if (badDebtDelta != 0) {\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld + badDebtDelta;\\n totalBorrowsNew = totalBorrowsNew - badDebtDelta;\\n badDebt = badDebtNew;\\n\\n // We treat healing as \\\"repayment\\\", where vToken is the payer\\n emit RepayBorrow(address(this), borrower, badDebtDelta, 0, totalBorrowsNew);\\n emit BadDebtIncreased(borrower, badDebtDelta, badDebtOld, badDebtNew);\\n }\\n\\n accountBorrows[borrower].principal = 0;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n emit HealBorrow(payer, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice The extended version of liquidations, callable only by Comptroller. May skip\\n * the close factor check. The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Only Comptroller\\n */\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) external override {\\n if (msg.sender != address(comptroller)) {\\n revert ForceLiquidateBorrowUnauthorized();\\n }\\n _liquidateBorrow(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\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 * @custom:event Emits Transfer, ReservesAdded events\\n * @custom:error LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:access Not restricted\\n */\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external override nonReentrant {\\n _seize(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Updates bad debt\\n * @dev Called only when bad debt is recovered from auction\\n * @param recoveredAmount_ The amount of bad debt recovered\\n * @custom:event Emits BadDebtRecovered event\\n * @custom:access Only Shortfall contract\\n */\\n function badDebtRecovered(uint256 recoveredAmount_) external {\\n require(msg.sender == shortfall, \\\"only shortfall contract can update bad debt\\\");\\n require(recoveredAmount_ <= badDebt, \\\"more than bad debt recovered from auction\\\");\\n\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld - recoveredAmount_;\\n badDebt = badDebtNew;\\n\\n emit BadDebtRecovered(badDebtOld, badDebtNew);\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protocolShareReserve_ The address of the protocol share reserve contract\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n * @custom:access Only Governance\\n */\\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\\n _setProtocolShareReserve(protocolShareReserve_);\\n }\\n\\n /**\\n * @notice Sets shortfall contract address\\n * @param shortfall_ The address of the shortfall contract\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:access Only Governance\\n */\\n function setShortfallContract(address shortfall_) external onlyOwner {\\n _setShortfallContract(shortfall_);\\n }\\n\\n /**\\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\\n * @param token The address of the ERC-20 token to sweep\\n * @custom:access Only Governance\\n */\\n function sweepToken(IERC20Upgradeable token) external override {\\n require(msg.sender == owner(), \\\"VToken::sweepToken: only admin can sweep tokens\\\");\\n require(address(token) != underlying, \\\"VToken::sweepToken: can not sweep underlying token\\\");\\n uint256 balance = token.balanceOf(address(this));\\n token.safeTransfer(owner(), balance);\\n\\n emit SweepToken(address(token));\\n }\\n\\n /**\\n * @notice A public function to set new threshold of slot(block or second) difference after which funds will be sent to the protocol share reserve\\n * @param _newReduceReservesBlockOrTimestampDelta slot(block or second) difference value\\n * @custom:access Only Governance\\n */\\n function setReduceReservesBlockDelta(uint256 _newReduceReservesBlockOrTimestampDelta) external {\\n _checkAccessAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n require(_newReduceReservesBlockOrTimestampDelta > 0, \\\"Invalid Input\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, _newReduceReservesBlockOrTimestampDelta);\\n reduceReservesBlockDelta = _newReduceReservesBlockOrTimestampDelta;\\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 amount 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 amount 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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return vTokenBalance User's balance of vTokens\\n * @return borrowBalance Amount owed in terms of underlying\\n * @return exchangeRate Stored exchange rate\\n */\\n function getAccountSnapshot(\\n address account\\n )\\n external\\n view\\n override\\n returns (uint256 error, uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRate)\\n {\\n return (NO_ERROR, accountTokens[account], _borrowBalanceStored(account), _exchangeRateStored());\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return cash The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint256) {\\n return _getCashPrior();\\n }\\n\\n /**\\n * @notice Returns the current per slot(block or second) borrow interest rate for this vToken\\n * @return rate The borrow interest rate per slot(block or second), scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint256) {\\n return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt);\\n }\\n\\n /**\\n * @notice Returns the current per-slot(block or second) supply interest rate for this v\\n * @return rate The supply interest rate per slot(block or second), scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint256) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPrior(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa,\\n badDebt\\n );\\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 borrowBalance The calculated balance\\n */\\n function borrowBalanceStored(address account) external view override returns (uint256) {\\n return _borrowBalanceStored(account);\\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 exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() external view override returns (uint256) {\\n return _exchangeRateStored();\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\\n accrueInterest();\\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 slot(block or second)\\n * up to the current slot(block or second) and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentSlot - reduceReservesBlockNumber >= slotDelta\\n * @return Always NO_ERROR\\n * @custom:event Emits AccrueInterest event on success\\n * @custom:access Not restricted\\n */\\n function accrueInterest() public virtual override returns (uint256) {\\n /* Remember the initial block number or timestamp */\\n uint256 currentSlotNumber = getBlockNumberOrTimestamp();\\n uint256 accrualSlotNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualSlotNumberPrior == currentSlotNumber) {\\n return NO_ERROR;\\n }\\n\\n /* Read the previous values out of storage */\\n uint256 cashPrior = _getCashPrior();\\n uint256 borrowsPrior = totalBorrows;\\n uint256 reservesPrior = totalReserves;\\n uint256 borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt);\\n require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of slots elapsed since the last accrual */\\n uint256 slotDelta = currentSlotNumber - accrualSlotNumberPrior;\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * slotDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), slotDelta);\\n uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\\n uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;\\n uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentSlotNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n if (currentSlotNumber - reduceReservesBlockNumber >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentSlotNumber;\\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 NO_ERROR;\\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 or timestamp\\n * @param payer The address of the account which is sending the assets for supply\\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 */\\n function _mintFresh(address payer, address minter, uint256 mintAmount) internal {\\n /* Fail if mint not allowed */\\n comptroller.preMintHook(address(this), minter, mintAmount);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert MintFreshnessCheck();\\n }\\n\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\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 * `_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 uint256 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 uint256 mintTokens = div_(actualMintAmount, exchangeRate);\\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 * And write them into storage\\n */\\n totalSupply = totalSupply + mintTokens;\\n uint256 balanceAfter = accountTokens[minter] + mintTokens;\\n accountTokens[minter] = balanceAfter;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, actualMintAmount, mintTokens, balanceAfter);\\n emit Transfer(address(0), minter, mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, actualMintAmount, mintTokens);\\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 Comptroller.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current slot(block or second)\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the underlying 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 */\\n function _redeemFresh(address redeemer, address receiver, uint256 redeemTokensIn, uint256 redeemAmountIn) internal {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert RedeemFreshnessCheck();\\n }\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n\\n uint256 redeemTokens;\\n uint256 redeemAmount;\\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 */\\n redeemTokens = redeemTokensIn;\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n */\\n redeemTokens = div_(redeemAmountIn, exchangeRate);\\n\\n uint256 _redeemAmount = mul_(redeemTokens, exchangeRate);\\n if (_redeemAmount != 0 && _redeemAmount != redeemAmountIn) redeemTokens++; // round up\\n }\\n\\n // redeemAmount = exchangeRate * redeemTokens\\n redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokens);\\n\\n // Revert if amount is zero\\n if (redeemAmount == 0) {\\n revert(\\\"redeemAmount is zero\\\");\\n }\\n\\n /* Fail if redeem not allowed */\\n comptroller.preRedeemHook(address(this), redeemer, redeemTokens);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (_getCashPrior() - totalReserves < redeemAmount) {\\n revert RedeemTransferOutNotPossible();\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\\n */\\n totalSupply = totalSupply - redeemTokens;\\n uint256 balanceAfter = accountTokens[redeemer] - redeemTokens;\\n accountTokens[redeemer] = balanceAfter;\\n\\n /*\\n * We invoke _doTransferOut for the receiver and the redeemAmount.\\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 _doTransferOut(receiver, redeemAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), redeemTokens);\\n emit Redeem(redeemer, redeemAmount, redeemTokens, balanceAfter);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, redeemAmount, redeemTokens);\\n }\\n\\n /**\\n * @notice Users or their delegates borrow assets from the protocol\\n * @param borrower User who borrows the assets\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param borrowAmount The amount of the underlying asset to borrow\\n */\\n function _borrowFresh(address borrower, address receiver, uint256 borrowAmount) internal {\\n /* Fail if borrow not allowed */\\n comptroller.preBorrowHook(address(this), borrower, borrowAmount);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert BorrowFreshnessCheck();\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (_getCashPrior() - totalReserves < borrowAmount) {\\n revert BorrowCashNotAvailable();\\n }\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowNew = accountBorrow + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;\\n uint256 totalBorrowsNew = totalBorrows + borrowAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\\n `*/\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /*\\n * We invoke _doTransferOut for the receiver and the borrowAmount.\\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, accountBorrowsNew, totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\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 underlying tokens being returned, or type(uint256).max for the full outstanding amount\\n * @return (uint) the actual repayment amount.\\n */\\n function _repayBorrowFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256) {\\n /* Fail if repayBorrow not allowed */\\n comptroller.preRepayHook(address(this), borrower);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert RepayBorrowFreshnessCheck();\\n }\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n\\n uint256 repayAmountFinal = repayAmount >= accountBorrowsPrev ? accountBorrowsPrev : 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 * 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 uint256 actualRepayAmount = _doTransferIn(payer, repayAmountFinal);\\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 uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\\n uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, actualRepayAmount, borrowIndex);\\n\\n return actualRepayAmount;\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal nonReentrant {\\n accrueInterest();\\n\\n uint256 error = vTokenCollateral.accrueInterest();\\n if (error != NO_ERROR) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n revert LiquidateAccrueCollateralInterestFailed(error);\\n }\\n\\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal {\\n /* Fail if liquidate not allowed */\\n comptroller.preLiquidateHook(\\n address(this),\\n address(vTokenCollateral),\\n borrower,\\n repayAmount,\\n skipLiquidityCheck\\n );\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert LiquidateFreshnessCheck();\\n }\\n\\n /* Verify vTokenCollateral market's slot(block or second) number equals current slot(block or second) number */\\n if (vTokenCollateral.accrualBlockNumber() != getBlockNumberOrTimestamp()) {\\n revert LiquidateCollateralFreshnessCheck();\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateLiquidatorIsBorrower();\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n revert LiquidateCloseAmountIsZero();\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n revert LiquidateCloseAmountIsUintMax();\\n }\\n\\n /* Fail if repayBorrow fails */\\n uint256 actualRepayAmount = _repayBorrowFresh(liquidator, borrower, repayAmount);\\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.liquidateCalculateSeizeTokens(\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n require(amountSeizeError == 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, call _seize internally to avoid re-entrancy, otherwise make an external call\\n if (address(vTokenCollateral) == address(this)) {\\n _seize(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\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\\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 * It's absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerContract The contract seizing the collateral (either borrowed vToken or Comptroller)\\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 */\\n function _seize(address seizerContract, address liquidator, address borrower, uint256 seizeTokens) internal {\\n /* Fail if seize not allowed */\\n comptroller.preSeizeHook(address(this), seizerContract, liquidator, borrower);\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateSeizeLiquidatorIsBorrower();\\n }\\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 uint256 liquidationIncentiveMantissa = ComptrollerViewInterface(address(comptroller))\\n .liquidationIncentiveMantissa();\\n uint256 numerator = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));\\n uint256 protocolSeizeTokens = div_(numerator, Exp({ mantissa: liquidationIncentiveMantissa }));\\n uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n uint256 protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the calculated values into storage */\\n totalSupply = totalSupply - protocolSeizeTokens;\\n accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\\n accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\\n\\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, protocolSeizeAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.LIQUIDATION\\n );\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\\n emit ProtocolSeize(borrower, protocolShareReserve, protocolSeizeAmount);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerContract, liquidator, borrower, seizeTokens);\\n }\\n\\n function _setComptroller(ComptrollerInterface newComptroller) internal {\\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\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n */\\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal {\\n // Verify market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert SetReserveFactorFreshCheck();\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > MAX_RESERVE_FACTOR_MANTISSA) {\\n revert SetReserveFactorBoundsCheck();\\n }\\n\\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\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 actualAddAmount The actual amount added, excluding the potential token fees\\n */\\n function _addReservesFresh(uint256 addAmount) internal returns (uint256) {\\n // totalReserves + actualAddAmount\\n uint256 totalReservesNew;\\n uint256 actualAddAmount;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert AddReservesFactorFreshCheck(actualAddAmount);\\n }\\n\\n actualAddAmount = _doTransferIn(msg.sender, addAmount);\\n totalReservesNew = totalReserves + actualAddAmount;\\n totalReserves = totalReservesNew;\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n return actualAddAmount;\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to the protocol reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n */\\n function _reduceReservesFresh(uint256 reduceAmount) internal {\\n if (reduceAmount == 0) {\\n return;\\n }\\n // totalReserves - reduceAmount\\n uint256 totalReservesNew;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert ReduceReservesFreshCheck();\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (_getCashPrior() < reduceAmount) {\\n revert ReduceReservesCashNotAvailable();\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n revert ReduceReservesCashValidation();\\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 // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, reduceAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit SpreadReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal {\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert SetInterestRateModelFreshCheck();\\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\\n /**\\n * Safe Token **\\n */\\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 returns (uint256) {\\n IERC20Upgradeable token = IERC20Upgradeable(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 to, uint256 amount) internal virtual {\\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\\n token.safeTransfer(to, amount);\\n }\\n\\n /**\\n * @notice Transfer `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 */\\n function _transferTokens(address spender, address src, address dst, uint256 tokens) internal {\\n /* Fail if transfer not allowed */\\n comptroller.preTransferHook(address(this), src, dst, tokens);\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n revert TransferNotAllowed();\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint256 startingAllowance;\\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 uint256 allowanceNew = startingAllowance - tokens;\\n uint256 srcTokensNew = accountTokens[src] - tokens;\\n uint256 dstTokensNew = accountTokens[dst] + tokens;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n\\n accountTokens[src] = srcTokensNew;\\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\\n /**\\n * @notice Initialize the 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_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n */\\n function _initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\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 _setComptroller(comptroller_);\\n\\n // Initialize slot(block or second) number and borrow index (slot(block or second) number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumberOrTimestamp();\\n borrowIndex = MANTISSA_ONE;\\n\\n // Set the interest rate model (depends on slot(block or second) number / borrow index)\\n _setInterestRateModelFresh(interestRateModel_);\\n\\n _setReserveFactorFresh(reserveFactorMantissa_);\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n _setShortfallContract(riskManagement.shortfall);\\n _setProtocolShareReserve(riskManagement.protocolShareReserve);\\n protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA;\\n\\n // Set underlying and sanity check it\\n underlying = underlying_;\\n IERC20Upgradeable(underlying).totalSupply();\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n _transferOwnership(admin_);\\n }\\n\\n function _setShortfallContract(address shortfall_) internal {\\n ensureNonzeroAddress(shortfall_);\\n address oldShortfall = shortfall;\\n shortfall = shortfall_;\\n emit NewShortfallContract(oldShortfall, shortfall_);\\n }\\n\\n function _setProtocolShareReserve(address payable protocolShareReserve_) internal {\\n ensureNonzeroAddress(protocolShareReserve_);\\n address oldProtocolShareReserve = address(protocolShareReserve);\\n protocolShareReserve = protocolShareReserve_;\\n emit NewProtocolShareReserve(oldProtocolShareReserve, address(protocolShareReserve_));\\n }\\n\\n function _ensureSenderIsDelegateOf(address user) internal view {\\n if (!ComptrollerViewInterface(address(comptroller)).approvedDelegates(user, msg.sender)) {\\n revert DelegateNotApproved();\\n }\\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 virtual returns (uint256) {\\n return IERC20Upgradeable(underlying).balanceOf(address(this));\\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 borrowBalance the calculated balance\\n */\\n function _borrowBalanceStored(address account) internal view returns (uint256) {\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot memory 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 0;\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;\\n\\n return principalTimesIndex / borrowSnapshot.interestIndex;\\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 exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function _exchangeRateStored() internal view virtual returns (uint256) {\\n uint256 _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return initialExchangeRateMantissa;\\n }\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply\\n */\\n uint256 totalCash = _getCashPrior();\\n uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;\\n uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply;\\n\\n return exchangeRate;\\n }\\n}\\n\",\"keccak256\":\"0xa220ca317fe69b920b86e43f054c43b5f891f12160fd312c9a21668f969ee056\",\"license\":\"BSD-3-Clause\"},\"contracts/VTokenInterfaces.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\\nimport { ComptrollerInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title VTokenStorage\\n * @author Venus\\n * @notice Storage layout used by the `VToken` contract\\n */\\n// solhint-disable-next-line max-states-count\\ncontract VTokenStorage {\\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 uint256 principal;\\n uint256 interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\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 Protocol share Reserve contract address\\n */\\n address payable public protocolShareReserve;\\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 InterestRateModel public interestRateModel;\\n\\n // Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n uint256 internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint256 public reserveFactorMantissa;\\n\\n /**\\n * @notice Slot(block or second) number that interest was last accrued at\\n */\\n uint256 public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint256 public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint256 public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint256 public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint256 public totalSupply;\\n\\n /**\\n * @notice Total bad debt of the market\\n */\\n uint256 public badDebt;\\n\\n // Official record of token balances for each account\\n mapping(address => uint256) internal accountTokens;\\n\\n // Approved token transfer amounts on behalf of others\\n mapping(address => mapping(address => uint256)) internal transferAllowances;\\n\\n // Mapping of account addresses to outstanding borrow balances\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint256 public protocolSeizeShareMantissa;\\n\\n /**\\n * @notice Storage of Shortfall contract address\\n */\\n address public shortfall;\\n\\n /**\\n * @notice delta slot (block or second) after which reserves will be reduced\\n */\\n uint256 public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last slot (block or second) number at which reserves were reduced\\n */\\n uint256 public reduceReservesBlockNumber;\\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\\n/**\\n * @title VTokenInterface\\n * @author Venus\\n * @notice Interface implemented by the `VToken` contract\\n */\\nabstract contract VTokenInterface is VTokenStorage {\\n struct RiskManagementInit {\\n address shortfall;\\n address payable protocolShareReserve;\\n }\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address indexed minter, uint256 mintAmount, uint256 mintTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address indexed borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(\\n address indexed payer,\\n address indexed borrower,\\n uint256 repayAmount,\\n uint256 accountBorrows,\\n uint256 totalBorrows\\n );\\n\\n /**\\n * @notice Event emitted when bad debt is accumulated on a market\\n * @param borrower borrower to \\\"forgive\\\"\\n * @param badDebtDelta amount of new bad debt recorded\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtIncreased(address indexed borrower, uint256 badDebtDelta, uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when bad debt is recovered via an auction\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtRecovered(uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address indexed liquidator,\\n address indexed borrower,\\n uint256 repayAmount,\\n address indexed vTokenCollateral,\\n uint256 seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface indexed oldComptroller, ComptrollerInterface indexed newComptroller);\\n\\n /**\\n * @notice Event emitted when shortfall contract address is changed\\n */\\n event NewShortfallContract(address indexed oldShortfall, address indexed newShortfall);\\n\\n /**\\n * @notice Event emitted when protocol share reserve contract address is changed\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModel indexed oldInterestRateModel,\\n InterestRateModel indexed newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when protocol seize share is changed\\n */\\n event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address indexed benefactor, uint256 addAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the spread reserves are reduced\\n */\\n event SpreadReservesReduced(address indexed protocolShareReserve, uint256 reduceAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /**\\n * @notice Event emitted when healing the borrow\\n */\\n event HealBorrow(address indexed payer, address indexed borrower, uint256 repayAmount);\\n\\n /**\\n * @notice Event emitted when tokens are swept\\n */\\n event SweepToken(address indexed token);\\n\\n /**\\n * @notice Event emitted when reduce reserves slot (block or second) delta is changed\\n */\\n event NewReduceReservesBlockDelta(\\n uint256 oldReduceReservesBlockOrTimestampDelta,\\n uint256 newReduceReservesBlockOrTimestampDelta\\n );\\n\\n /**\\n * @notice Event emitted when liquidation reserves are reduced\\n */\\n event ProtocolSeize(address indexed from, address indexed to, uint256 amount);\\n\\n /*** User Interface ***/\\n\\n function mint(uint256 mintAmount) external virtual returns (uint256);\\n\\n function mintBehalf(address minter, uint256 mintAllowed) external virtual returns (uint256);\\n\\n function redeem(uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemBehalf(address redeemer, uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);\\n\\n function redeemUnderlyingBehalf(address redeemer, uint256 redeemAmount) external virtual returns (uint256);\\n\\n function borrow(uint256 borrowAmount) external virtual returns (uint256);\\n\\n function borrowBehalf(address borrwwer, uint256 borrowAmount) external virtual returns (uint256);\\n\\n function repayBorrow(uint256 repayAmount) external virtual returns (uint256);\\n\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external virtual returns (uint256);\\n\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external virtual;\\n\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipCloseFactorCheck\\n ) external virtual;\\n\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external virtual;\\n\\n function transfer(address dst, uint256 amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint256 amount) external virtual returns (bool);\\n\\n function accrueInterest() external virtual returns (uint256);\\n\\n function sweepToken(IERC20Upgradeable token) external virtual;\\n\\n /*** Admin Functions ***/\\n\\n function setReserveFactor(uint256 newReserveFactorMantissa) external virtual;\\n\\n function reduceReserves(uint256 reduceAmount) external virtual;\\n\\n function exchangeRateCurrent() external virtual returns (uint256);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint256);\\n\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external virtual;\\n\\n function addReserves(uint256 addAmount) external virtual;\\n\\n function totalBorrowsCurrent() external virtual returns (uint256);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint256);\\n\\n function approve(address spender, uint256 amount) external virtual returns (bool);\\n\\n function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool);\\n\\n function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint256);\\n\\n function balanceOf(address owner) external view virtual returns (uint256);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint256, uint256, uint256, uint256);\\n\\n function borrowRatePerBlock() external view virtual returns (uint256);\\n\\n function supplyRatePerBlock() external view virtual returns (uint256);\\n\\n function borrowBalanceStored(address account) external view virtual returns (uint256);\\n\\n function exchangeRateStored() external view virtual returns (uint256);\\n\\n function getCash() external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is a VToken contract (for inspection)\\n * @return Always true\\n */\\n function isVToken() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x7c4cbb879e3a931cfee4fa7a9eb1978eddff18087a1c4f56decedb84c2479f1e\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\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\",\"keccak256\":\"0x54ab3a6f3bc87569ed12370f3470a1ec84cea9796d4d0ccf3d07dd4280c044aa\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/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 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\",\"keccak256\":\"0x93bdd5cfb100f0f9a1d446857e23c3633df6ab12c266333c978428edd96b1367\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x60e060405234801561001057600080fd5b50604051613ffc380380613ffc83398101604081905261002f916100dc565b81818115801561003d575080155b1561005b576040516302723dfb60e21b815260040160405180910390fd5b81801561006757508015155b156100855760405163ae0fcab360e01b815260040160405180910390fd5b81151560a05281610096578061009c565b6301e133805b608052816100b3576100d460201b611d89176100be565b6100d860201b611d8d175b6001600160401b031660c0525061010f92505050565b4390565b4290565b600080604083850312156100ef57600080fd5b825180151581146100ff57600080fd5b6020939093015192949293505050565b60805160a05160c051613eb76101456000396000611d5d0152600081816102a60152611e5e015260006101d10152613eb76000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c80637c51b64211610097578063c7ad089511610066578063c7ad0895146102a1578063d77ebf96146102d8578063e0a67f11146102f8578063e1d146fb1461031857600080fd5b80637c51b642146102215780637c84e3b314610241578063aa5dbd2314610261578063b31242391461028157600080fd5b806347d86a81116100d357806347d86a811461018e57806355dd9515146101a15780636857249c146101cc5780637a27db571461020157600080fd5b80630d3ae318146101055780631f884fdf1461012e578063345954dc1461014e5780633e3e399c1461016e575b600080fd5b610118610113366004612ece565b610320565b604051610125919061323b565b60405180910390f35b61014161013c366004613299565b610655565b60405161012591906132da565b61016161015c36600461333a565b61071d565b6040516101259190613357565b61018161017c36600461333a565b610850565b60405161012591906133bb565b61011861019c366004613445565b610bc2565b6101b46101af36600461347e565b610c49565b6040516001600160a01b039091168152602001610125565b6101f37f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610125565b61021461020f366004613445565b610cc9565b60405161012591906134c9565b61023461022f3660046135a5565b610fd6565b6040516101259190613630565b61025461024f36600461333a565b61108f565b604051610125919061367e565b61027461026f36600461333a565b6111f9565b604051610125919061369e565b61029461028f366004613445565b611947565b60405161012591906136ad565b6102c87f000000000000000000000000000000000000000000000000000000000000000081565b6040519015158152602001610125565b6102eb6102e6366004613445565b611c2e565b60405161012591906136bb565b61030b61030636600461371f565b611ca1565b60405161012591906137b8565b6101f3611d56565b610328612c95565b6000826040015190506000816001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610371573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261039991908101906137fb565b905060006103a682611ca1565b60408681015190516328ebbe8b60e21b81526001600160a01b039182166004820152919250879160009183169063a3aefa2c90602401600060405180830381865afa1580156103f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261042191908101906138ce565b90506000876040015190506000604051806101a001604052808a6000015181526020018a602001516001600160a01b031681526020018a604001516001600160a01b031681526020018a6060015181526020018a608001518152602001846000015181526020018460200151815260200184604001518152602001836001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104fe9190613982565b6001600160a01b03168152602001836001600160a01b031663e87554466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561054a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061056e919061399f565b8152602001836001600160a01b0316634ada90af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d5919061399f565b8152602001836001600160a01b031663db5c65de6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610618573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063c919061399f565b8152602001959095525092955050505050505b92915050565b6060816000816001600160401b0381111561067257610672612e17565b6040519080825280602002602001820160405280156106b757816020015b60408051808201909152600080825260208201528152602001906001900390816106905790505b50905060005b82811015610714576106ef8686838181106106da576106da6139b8565b905060200201602081019061024f919061333a565b828281518110610701576107016139b8565b60209081029190910101526001016106bd565b50949350505050565b606060008290506000816001600160a01b031663d88ff1f46040518163ffffffff1660e01b8152600401600060405180830381865afa158015610764573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261078c9190810190613a51565b80519091506000816001600160401b038111156107ab576107ab612e17565b6040519080825280602002602001820160405280156107e457816020015b6107d1612c95565b8152602001906001900390816107c95790505b50905060005b82811015610846576000848281518110610806576108066139b8565b60200260200101519050600061081c8983610320565b905080848481518110610831576108316139b8565b602090810291909101015250506001016107ea565b5095945050505050565b604080516060808201835260008083526020830152918101919091526000808390506000816001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156108b2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108da91908101906137fb565b90506000826001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561091c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109409190613982565b9050600082516001600160401b0381111561095d5761095d612e17565b6040519080825280602002602001820160405280156109a257816020015b604080518082019091526000808252602082015281526020019060019003908161097b5790505b5090506109d2604051806060016040528060006001600160a01b0316815260200160008152602001606081525090565b6001600160a01b03881681526040810182905260005b8451811015610bae576040805180820190915260008082526020820152858281518110610a1757610a176139b8565b602002602001015181600001906001600160a01b031690816001600160a01b031681525050670de0b6b3a7640000856001600160a01b031663fc57d4df888581518110610a6657610a666139b8565b60200260200101516040518263ffffffff1660e01b8152600401610a9991906001600160a01b0391909116815260200190565b602060405180830381865afa158015610ab6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ada919061399f565b878481518110610aec57610aec6139b8565b60200260200101516001600160a01b031663bbcac5576040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b55919061399f565b610b5f9190613b17565b610b699190613b2e565b60208201526040830151805182919084908110610b8857610b886139b8565b6020026020010181905250806020015188610ba39190613b50565b9750506001016109e8565b506020810195909552509295945050505050565b610bca612c95565b604051637aee632d60e01b81526001600160a01b0383811660048301528491610c4191839190821690637aee632d90602401600060405180830381865afa158015610c19573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526101139190810190613b63565b949350505050565b60405163266e0a7f60e01b81526001600160a01b0383811660048301528281166024830152600091859182169063266e0a7f90604401602060405180830381865afa158015610c9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc09190613982565b95945050505050565b60606000826001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610d0b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d3391908101906137fb565b90506000836001600160a01b03166361252fd16040518163ffffffff1660e01b8152600401600060405180830381865afa158015610d75573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d9d9190810190613b97565b9050600081516001600160401b03811115610dba57610dba612e17565b604051908082528060200260200182016040528015610e0b57816020015b6040805160808101825260008082526020808301829052928201526060808201528252600019909201910181610dd85790505b50905060005b8251811015610846576040805160808101825260008082526020820181905291810191909152606080820152838281518110610e4f57610e4f6139b8565b60209081029190910101516001600160a01b031681528351849083908110610e7957610e796139b8565b60200260200101516001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ebe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee29190613982565b6001600160a01b031660208201528351849083908110610f0457610f046139b8565b6020908102919091010151604051631627ee8960e01b81526001600160a01b038a8116600483015290911690631627ee8990602401602060405180830381865afa158015610f56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7a919061399f565b816040018181525050610fa78886868581518110610f9a57610f9a6139b8565b6020026020010151611d91565b816060018190525080838381518110610fc257610fc26139b8565b602090810291909101015250600101610e11565b6060826000816001600160401b03811115610ff357610ff3612e17565b60405190808252806020026020018201604052801561102c57816020015b611019612d18565b8152602001906001900390816110115790505b50905060005b828110156108465761106a87878381811061104f5761104f6139b8565b9050602002016020810190611064919061333a565b86611947565b82828151811061107c5761107c6139b8565b6020908102919091010152600101611032565b60408051808201909152600080825260208201526000826001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111079190613982565b90506000816001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611149573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116d9190613982565b6040805180820182526001600160a01b03808816808352925163fc57d4df60e01b815260048101939093529293509160208301919084169063fc57d4df90602401602060405180830381865afa1580156111cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ef919061399f565b9052949350505050565b611201612d57565b6000826001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611241573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611265919061399f565b90506000836001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cb9190613982565b604051638e8f294b60e01b81526001600160a01b03868116600483015291925082916000918291841690638e8f294b906024016040805180830381865afa15801561131a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133e9190613c35565b915091506000876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a69190613982565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061140c9190613c61565b60ff1690506000805b600860ff8216116114d2576000886001600160a01b031663e85a29608d8460ff16600881111561144757611447613c84565b6040518363ffffffff1660e01b8152600401611464929190613c9a565b602060405180830381865afa158015611481573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a59190613cd5565b6114b05760006114b3565b60015b60ff9081169083161b9290921791506114cb81613cf0565b9050611415565b506040518061022001604052808b6001600160a01b031681526020018981526020018b6001600160a01b031663ae9d70b06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611532573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611556919061399f565b81526020018b6001600160a01b031663f8f9da286040518163ffffffff1660e01b8152600401602060405180830381865afa158015611599573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115bd919061399f565b81526020018b6001600160a01b031663173b99046040518163ffffffff1660e01b8152600401602060405180830381865afa158015611600573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611624919061399f565b81526040516302c3bcbb60e01b81526001600160a01b038d811660048301526020909201918916906302c3bcbb90602401602060405180830381865afa158015611672573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611696919061399f565b815260405163252c221960e11b81526001600160a01b038d81166004830152602090920191891690634a58443290602401602060405180830381865afa1580156116e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611708919061399f565b81526020018b6001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561174b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176f919061399f565b81526020018b6001600160a01b0316638f840ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117d6919061399f565b81526020018b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611819573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061183d919061399f565b81526020018b6001600160a01b0316633b1d21a26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611880573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118a4919061399f565b81526020018615158152602001858152602001846001600160a01b031681526020018b6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611904573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119289190613c61565b60ff168152602081019390935260409092015298975050505050505050565b61194f612d18565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908516906370a0823190602401602060405180830381865afa158015611999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119bd919061399f565b6040516305eff7ef60e21b81526001600160a01b0385811660048301529192506000918616906317bfdfbc906024016020604051808303816000875af1158015611a0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a2f919061399f565b604051633af9e66960e01b81526001600160a01b038681166004830152919250600091871690633af9e669906024016020604051808303816000875af1158015611a7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa1919061399f565b90506000806000886001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0a9190613982565b6040516370a0823160e01b81526001600160a01b038a81166004830152919250908216906370a0823190602401602060405180830381865afa158015611b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b78919061399f565b604051636eb1769f60e11b81526001600160a01b038a811660048301528b811660248301529194509082169063dd62ed3e90604401602060405180830381865afa158015611bca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bee919061399f565b6040805160c0810182526001600160a01b038c168152602081019890985287019590955250506060840191909152608083015260a0820152905092915050565b604051631e6db74760e31b81526001600160a01b038281166004830152606091849182169063f36dba3890602401600060405180830381865afa158015611c79573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c419190810190613d0f565b80516060906000816001600160401b03811115611cc057611cc0612e17565b604051908082528060200260200182016040528015611cf957816020015b611ce6612d57565b815260200190600190039081611cde5790505b50905060005b82811015611d4e57611d29858281518110611d1c57611d1c6139b8565b60200260200101516111f9565b828281518110611d3b57611d3b6139b8565b6020908102919091010152600101611cff565b509392505050565b6000611d847f000000000000000000000000000000000000000000000000000000000000000063ffffffff16565b905090565b4390565b4290565b6060600083516001600160401b03811115611dae57611dae612e17565b604051908082528060200260200182016040528015611df357816020015b6040805180820190915260008082526020820152815260200190600190039081611dcc5790505b50905060005b845181101561071457611e2f604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b611e5c604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b7f000000000000000000000000000000000000000000000000000000000000000015611fdf57856001600160a01b0316638f693ec7888581518110611ea357611ea36139b8565b60200260200101516040518263ffffffff1660e01b8152600401611ed691906001600160a01b0391909116815260200190565b606060405180830381865afa158015611ef3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f179190613db4565b604085015260208401526001600160e01b0316825286516001600160a01b03871690638181494590899086908110611f5157611f516139b8565b60200260200101516040518263ffffffff1660e01b8152600401611f8491906001600160a01b0391909116815260200190565b606060405180830381865afa158015611fa1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fc59190613db4565b604084015260208301526001600160e01b0316815261214a565b856001600160a01b0316632c427b57888581518110612000576120006139b8565b60200260200101516040518263ffffffff1660e01b815260040161203391906001600160a01b0391909116815260200190565b606060405180830381865afa158015612050573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120749190613dfd565b63ffffffff90811660408601521660208401526001600160e01b0316825286516001600160a01b038716906392a18235908990869081106120b7576120b76139b8565b60200260200101516040518263ffffffff1660e01b81526004016120ea91906001600160a01b0391909116815260200190565b606060405180830381865afa158015612107573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061212b9190613dfd565b63ffffffff90811660408501521660208301526001600160e01b031681525b60006040518060200160405280898681518110612169576121696139b8565b60200260200101516001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121d2919061399f565b81525090506121fc8885815181106121ec576121ec6139b8565b60200260200101518885846122f1565b612220888581518110612211576122116139b8565b602002602001015188846124f2565b6000612248898681518110612237576122376139b8565b6020026020010151898c87866126e9565b905060006122718a8781518110612261576122616139b8565b60200260200101518a8d87612919565b60408051808201909152600080825260208201529091508a878151811061229a5761229a6139b8565b60209081029190910101516001600160a01b031681526122ba8284613b50565b6020820152875181908990899081106122d5576122d56139b8565b6020026020010181905250505050505050806001019050611df9565b604051637c05a7c560e01b81526001600160a01b03858116600483015260009190851690637c05a7c590602401602060405180830381865afa15801561233b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061235f919061399f565b9050600061236b611d56565b9050600084604001511180156123845750836040015181115b15612390575060408301515b60006123a0828660200151612b3d565b90506000811180156123b25750600083115b156124db576000612424886001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061241e919061399f565b86612b50565b905060006124328386612b6e565b90506000808311612452576040518060200160405280600081525061245c565b61245c8284612b7a565b9050600061248560405180602001604052808b600001516001600160e01b031681525083612bbf565b90506124c08160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612beb565b6001600160e01b0316895250505050602085018290526124e9565b80156124e957602085018290525b50505050505050565b604051631d31307360e21b81526001600160a01b038481166004830152600091908416906374c4c1cc90602401602060405180830381865afa15801561253c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612560919061399f565b9050600061256c611d56565b9050600083604001511180156125855750826040015181115b15612591575060408201515b60006125a1828560200151612b3d565b90506000811180156125b35750600083115b156126d3576000866001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156125f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061261c919061399f565b9050600061262a8386612b6e565b9050600080831161264a5760405180602001604052806000815250612654565b6126548284612b7a565b9050600061267d60405180602001604052808a600001516001600160e01b031681525083612bbf565b90506126b88160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612beb565b6001600160e01b0316885250505050602084018290526126e1565b80156126e157602084018290525b505050505050565b604080516020808201835284516001600160e01b031682528251908101928390526336fe846560e11b9092526001600160a01b0387811660248401528581166044840152600092839181908916636dfd08ca60648301602060405180830381865afa15801561275c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612780919061399f565b905280519091501580156128025750866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f19190613e40565b6001600160e01b0316826000015110155b1561287557866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612845573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128699190613e40565b6001600160e01b031681525b60006128818383612c27565b6040516395dd919360e01b81526001600160a01b0389811660048301529192506000916128fc91908c16906395dd919390602401602060405180830381865afa1580156128d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128f6919061399f565b87612b50565b9050600061290a8284612c53565b9b9a5050505050505050505050565b604080516020808201835283516001600160e01b0316825282519081019283905263552c097160e01b9092526001600160a01b038681166024840152848116604484015260009283918190881663552c097160648301602060405180830381865afa15801561298c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129b0919061399f565b90528051909150158015612a325750856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a219190613e40565b6001600160e01b0316826000015110155b15612aa557856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a999190613e40565b6001600160e01b031681525b6000612ab18383612c27565b6040516370a0823160e01b81526001600160a01b0388811660048301529192506000918a16906370a0823190602401602060405180830381865afa158015612afd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b21919061399f565b90506000612b2f8284612c53565b9a9950505050505050505050565b6000612b498284613e5b565b9392505050565b6000612b49612b6784670de0b6b3a7640000612b6e565b8351612c7d565b6000612b498284613b17565b6040805160208101909152600081526040518060200160405280612bb6612bb0866ec097ce7bc90715b34b9f1000000000612b6e565b85612c7d565b90529392505050565b6040805160208101909152600081526040518060200160405280612bb685600001518560000151612c89565b6000816001600160e01b03841115612c1f5760405162461bcd60e51b8152600401612c169190613e6e565b60405180910390fd5b509192915050565b6040805160208101909152600081526040518060200160405280612bb685600001518560000151612b3d565b60006ec097ce7bc90715b34b9f1000000000612c73848460000151612b6e565b612b499190613b2e565b6000612b498284613b2e565b6000612b498284613b50565b604051806101a001604052806060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160608152602001606081526020016060815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001606081525090565b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180610220016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b6001600160a01b0381168114612e0457600080fd5b50565b8035612e1281612def565b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715612e4f57612e4f612e17565b60405290565b604051606081016001600160401b0381118282101715612e4f57612e4f612e17565b604051601f8201601f191681016001600160401b0381118282101715612e9f57612e9f612e17565b604052919050565b60006001600160401b03821115612ec057612ec0612e17565b50601f01601f191660200190565b60008060408385031215612ee157600080fd5b8235612eec81612def565b91506020838101356001600160401b0380821115612f0957600080fd5b9085019060a08288031215612f1d57600080fd5b612f25612e2d565b823582811115612f3457600080fd5b83019150601f82018813612f4757600080fd5b8135612f5a612f5582612ea7565b612e77565b8181528986838601011115612f6e57600080fd5b818685018783013760008683830101528083525050612f8e848401612e07565b84820152612f9e60408401612e07565b60408201526060830135606082015260808301356080820152809450505050509250929050565b60005b83811015612fe0578181015183820152602001612fc8565b50506000910152565b60008151808452613001816020860160208601612fc5565b601f01601f19169290920160200192915050565b80516001600160a01b031682526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e0830152610100808201518184015250610120808201518184015250610140808201518184015250610160808201516130a08285018215159052565b505061018081810151908301526101a0808201516001600160a01b0316908301526101c080820151908301526101e0808201519083015261020090810151910152565b60008151808452602080850194506020840160005b8381101561311f5761310b878351613015565b6102209690960195908201906001016130f8565b509495945050505050565b60006101a0825181855261314082860182612fe9565b915050602083015161315d60208601826001600160a01b03169052565b50604083015161317860408601826001600160a01b03169052565b50606083015160608501526080830151608085015260a083015184820360a08601526131a48282612fe9565b91505060c083015184820360c08601526131be8282612fe9565b91505060e083015184820360e08601526131d88282612fe9565b915050610100808401516131f6828701826001600160a01b03169052565b5050610120838101519085015261014080840151908501526101608084015190850152610180808401518583038287015261323183826130e3565b9695505050505050565b602081526000612b49602083018461312a565b60008083601f84011261326057600080fd5b5081356001600160401b0381111561327757600080fd5b6020830191508360208260051b850101111561329257600080fd5b9250929050565b600080602083850312156132ac57600080fd5b82356001600160401b038111156132c257600080fd5b6132ce8582860161324e565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b8281101561332d5761331d84835180516001600160a01b03168252602090810151910152565b92840192908501906001016132f7565b5091979650505050505050565b60006020828403121561334c57600080fd5b8135612b4981612def565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156133ae57603f1988860301845261339c85835161312a565b94509285019290850190600101613380565b5092979650505050505050565b602080825282516001600160a01b03168282015282810151604080840191909152808401516060808501528051608085018190526000939291830191849160a08701905b808410156134395761342582865180516001600160a01b03168252602090810151910152565b9385019360019390930192908201906133ff565b50979650505050505050565b6000806040838503121561345857600080fd5b823561346381612def565b9150602083013561347381612def565b809150509250929050565b60008060006060848603121561349357600080fd5b833561349e81612def565b925060208401356134ae81612def565b915060408401356134be81612def565b809150509250925092565b600060208083018184528085518083526040925060408601915060408160051b8701018488016000805b8481101561359657898403603f19018652825180516001600160a01b03908116865289820151168986015287810151888601526060908101516080918601829052805191860182905289019060a086019084905b808210156135815761356d83855180516001600160a01b03168252602090810151910152565b928b0192918a019160019190910190613547565b505096890196945050918701916001016134f3565b50919998505050505050505050565b6000806000604084860312156135ba57600080fd5b83356001600160401b038111156135d057600080fd5b6135dc8682870161324e565b90945092505060208401356134be81612def565b80516001600160a01b031682526020808201519083015260408082015190830152606080820151908301526080808201519083015260a090810151910152565b6020808252825182820181905260009190848201906040850190845b818110156136725761365f8385516135f0565b9284019260c0929092019160010161364c565b50909695505050505050565b81516001600160a01b03168152602080830151908201526040810161064f565b610220810161064f8284613015565b60c0810161064f82846135f0565b6020808252825182820181905260009190848201906040850190845b818110156136725783516001600160a01b0316835292840192918401916001016136d7565b60006001600160401b0382111561371557613715612e17565b5060051b60200190565b6000602080838503121561373257600080fd5b82356001600160401b0381111561374857600080fd5b8301601f8101851361375957600080fd5b8035613767612f55826136fc565b81815260059190911b8201830190838101908783111561378657600080fd5b928401925b828410156137ad57833561379e81612def565b8252928401929084019061378b565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b81811015613672576137e7838551613015565b9284019261022092909201916001016137d4565b6000602080838503121561380e57600080fd5b82516001600160401b0381111561382457600080fd5b8301601f8101851361383557600080fd5b8051613843612f55826136fc565b81815260059190911b8201830190838101908783111561386257600080fd5b928401925b828410156137ad57835161387a81612def565b82529284019290840190613867565b600082601f83011261389a57600080fd5b81516138a8612f5582612ea7565b8181528460208386010111156138bd57600080fd5b610c41826020830160208701612fc5565b6000602082840312156138e057600080fd5b81516001600160401b03808211156138f757600080fd5b908301906060828603121561390b57600080fd5b613913612e55565b82518281111561392257600080fd5b61392e87828601613889565b82525060208301518281111561394357600080fd5b61394f87828601613889565b60208301525060408301518281111561396757600080fd5b61397387828601613889565b60408301525095945050505050565b60006020828403121561399457600080fd5b8151612b4981612def565b6000602082840312156139b157600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600060a082840312156139e057600080fd5b6139e8612e2d565b905081516001600160401b03811115613a0057600080fd5b613a0c84828501613889565b8252506020820151613a1d81612def565b60208201526040820151613a3081612def565b80604083015250606082015160608201526080820151608082015292915050565b60006020808385031215613a6457600080fd5b82516001600160401b0380821115613a7b57600080fd5b818501915085601f830112613a8f57600080fd5b8151613a9d612f55826136fc565b81815260059190911b83018401908481019088831115613abc57600080fd5b8585015b83811015613af457805185811115613ad85760008081fd5b613ae68b89838a01016139ce565b845250918601918601613ac0565b5098975050505050505050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761064f5761064f613b01565b600082613b4b57634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561064f5761064f613b01565b600060208284031215613b7557600080fd5b81516001600160401b03811115613b8b57600080fd5b610c41848285016139ce565b60006020808385031215613baa57600080fd5b82516001600160401b03811115613bc057600080fd5b8301601f81018513613bd157600080fd5b8051613bdf612f55826136fc565b81815260059190911b82018301908381019087831115613bfe57600080fd5b928401925b828410156137ad578351613c1681612def565b82529284019290840190613c03565b80518015158114612e1257600080fd5b60008060408385031215613c4857600080fd5b613c5183613c25565b9150602083015190509250929050565b600060208284031215613c7357600080fd5b815160ff81168114612b4957600080fd5b634e487b7160e01b600052602160045260246000fd5b6001600160a01b03831681526040810160098310613cc857634e487b7160e01b600052602160045260246000fd5b8260208301529392505050565b600060208284031215613ce757600080fd5b612b4982613c25565b600060ff821660ff8103613d0657613d06613b01565b60010192915050565b60006020808385031215613d2257600080fd5b82516001600160401b03811115613d3857600080fd5b8301601f81018513613d4957600080fd5b8051613d57612f55826136fc565b81815260059190911b82018301908381019087831115613d7657600080fd5b928401925b828410156137ad578351613d8e81612def565b82529284019290840190613d7b565b80516001600160e01b0381168114612e1257600080fd5b600080600060608486031215613dc957600080fd5b613dd284613d9d565b925060208401519150604084015190509250925092565b805163ffffffff81168114612e1257600080fd5b600080600060608486031215613e1257600080fd5b613e1b84613d9d565b9250613e2960208501613de9565b9150613e3760408501613de9565b90509250925092565b600060208284031215613e5257600080fd5b612b4982613d9d565b8181038181111561064f5761064f613b01565b602081526000612b496020830184612fe956fea2646970667358221220b9946cc7fdc900bd3735319cd04868b3796a2261574b7617c9cbf91cb2f997ca64736f6c63430008190033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101005760003560e01c80637c51b64211610097578063c7ad089511610066578063c7ad0895146102a1578063d77ebf96146102d8578063e0a67f11146102f8578063e1d146fb1461031857600080fd5b80637c51b642146102215780637c84e3b314610241578063aa5dbd2314610261578063b31242391461028157600080fd5b806347d86a81116100d357806347d86a811461018e57806355dd9515146101a15780636857249c146101cc5780637a27db571461020157600080fd5b80630d3ae318146101055780631f884fdf1461012e578063345954dc1461014e5780633e3e399c1461016e575b600080fd5b610118610113366004612ece565b610320565b604051610125919061323b565b60405180910390f35b61014161013c366004613299565b610655565b60405161012591906132da565b61016161015c36600461333a565b61071d565b6040516101259190613357565b61018161017c36600461333a565b610850565b60405161012591906133bb565b61011861019c366004613445565b610bc2565b6101b46101af36600461347e565b610c49565b6040516001600160a01b039091168152602001610125565b6101f37f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610125565b61021461020f366004613445565b610cc9565b60405161012591906134c9565b61023461022f3660046135a5565b610fd6565b6040516101259190613630565b61025461024f36600461333a565b61108f565b604051610125919061367e565b61027461026f36600461333a565b6111f9565b604051610125919061369e565b61029461028f366004613445565b611947565b60405161012591906136ad565b6102c87f000000000000000000000000000000000000000000000000000000000000000081565b6040519015158152602001610125565b6102eb6102e6366004613445565b611c2e565b60405161012591906136bb565b61030b61030636600461371f565b611ca1565b60405161012591906137b8565b6101f3611d56565b610328612c95565b6000826040015190506000816001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610371573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261039991908101906137fb565b905060006103a682611ca1565b60408681015190516328ebbe8b60e21b81526001600160a01b039182166004820152919250879160009183169063a3aefa2c90602401600060405180830381865afa1580156103f9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261042191908101906138ce565b90506000876040015190506000604051806101a001604052808a6000015181526020018a602001516001600160a01b031681526020018a604001516001600160a01b031681526020018a6060015181526020018a608001518152602001846000015181526020018460200151815260200184604001518152602001836001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104fe9190613982565b6001600160a01b03168152602001836001600160a01b031663e87554466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561054a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061056e919061399f565b8152602001836001600160a01b0316634ada90af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d5919061399f565b8152602001836001600160a01b031663db5c65de6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610618573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061063c919061399f565b8152602001959095525092955050505050505b92915050565b6060816000816001600160401b0381111561067257610672612e17565b6040519080825280602002602001820160405280156106b757816020015b60408051808201909152600080825260208201528152602001906001900390816106905790505b50905060005b82811015610714576106ef8686838181106106da576106da6139b8565b905060200201602081019061024f919061333a565b828281518110610701576107016139b8565b60209081029190910101526001016106bd565b50949350505050565b606060008290506000816001600160a01b031663d88ff1f46040518163ffffffff1660e01b8152600401600060405180830381865afa158015610764573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261078c9190810190613a51565b80519091506000816001600160401b038111156107ab576107ab612e17565b6040519080825280602002602001820160405280156107e457816020015b6107d1612c95565b8152602001906001900390816107c95790505b50905060005b82811015610846576000848281518110610806576108066139b8565b60200260200101519050600061081c8983610320565b905080848481518110610831576108316139b8565b602090810291909101015250506001016107ea565b5095945050505050565b604080516060808201835260008083526020830152918101919091526000808390506000816001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156108b2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108da91908101906137fb565b90506000826001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561091c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109409190613982565b9050600082516001600160401b0381111561095d5761095d612e17565b6040519080825280602002602001820160405280156109a257816020015b604080518082019091526000808252602082015281526020019060019003908161097b5790505b5090506109d2604051806060016040528060006001600160a01b0316815260200160008152602001606081525090565b6001600160a01b03881681526040810182905260005b8451811015610bae576040805180820190915260008082526020820152858281518110610a1757610a176139b8565b602002602001015181600001906001600160a01b031690816001600160a01b031681525050670de0b6b3a7640000856001600160a01b031663fc57d4df888581518110610a6657610a666139b8565b60200260200101516040518263ffffffff1660e01b8152600401610a9991906001600160a01b0391909116815260200190565b602060405180830381865afa158015610ab6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ada919061399f565b878481518110610aec57610aec6139b8565b60200260200101516001600160a01b031663bbcac5576040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b55919061399f565b610b5f9190613b17565b610b699190613b2e565b60208201526040830151805182919084908110610b8857610b886139b8565b6020026020010181905250806020015188610ba39190613b50565b9750506001016109e8565b506020810195909552509295945050505050565b610bca612c95565b604051637aee632d60e01b81526001600160a01b0383811660048301528491610c4191839190821690637aee632d90602401600060405180830381865afa158015610c19573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526101139190810190613b63565b949350505050565b60405163266e0a7f60e01b81526001600160a01b0383811660048301528281166024830152600091859182169063266e0a7f90604401602060405180830381865afa158015610c9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc09190613982565b95945050505050565b60606000826001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015610d0b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d3391908101906137fb565b90506000836001600160a01b03166361252fd16040518163ffffffff1660e01b8152600401600060405180830381865afa158015610d75573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d9d9190810190613b97565b9050600081516001600160401b03811115610dba57610dba612e17565b604051908082528060200260200182016040528015610e0b57816020015b6040805160808101825260008082526020808301829052928201526060808201528252600019909201910181610dd85790505b50905060005b8251811015610846576040805160808101825260008082526020820181905291810191909152606080820152838281518110610e4f57610e4f6139b8565b60209081029190910101516001600160a01b031681528351849083908110610e7957610e796139b8565b60200260200101516001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ebe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee29190613982565b6001600160a01b031660208201528351849083908110610f0457610f046139b8565b6020908102919091010151604051631627ee8960e01b81526001600160a01b038a8116600483015290911690631627ee8990602401602060405180830381865afa158015610f56573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7a919061399f565b816040018181525050610fa78886868581518110610f9a57610f9a6139b8565b6020026020010151611d91565b816060018190525080838381518110610fc257610fc26139b8565b602090810291909101015250600101610e11565b6060826000816001600160401b03811115610ff357610ff3612e17565b60405190808252806020026020018201604052801561102c57816020015b611019612d18565b8152602001906001900390816110115790505b50905060005b828110156108465761106a87878381811061104f5761104f6139b8565b9050602002016020810190611064919061333a565b86611947565b82828151811061107c5761107c6139b8565b6020908102919091010152600101611032565b60408051808201909152600080825260208201526000826001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111079190613982565b90506000816001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611149573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061116d9190613982565b6040805180820182526001600160a01b03808816808352925163fc57d4df60e01b815260048101939093529293509160208301919084169063fc57d4df90602401602060405180830381865afa1580156111cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ef919061399f565b9052949350505050565b611201612d57565b6000826001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611241573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611265919061399f565b90506000836001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112cb9190613982565b604051638e8f294b60e01b81526001600160a01b03868116600483015291925082916000918291841690638e8f294b906024016040805180830381865afa15801561131a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133e9190613c35565b915091506000876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a69190613982565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061140c9190613c61565b60ff1690506000805b600860ff8216116114d2576000886001600160a01b031663e85a29608d8460ff16600881111561144757611447613c84565b6040518363ffffffff1660e01b8152600401611464929190613c9a565b602060405180830381865afa158015611481573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114a59190613cd5565b6114b05760006114b3565b60015b60ff9081169083161b9290921791506114cb81613cf0565b9050611415565b506040518061022001604052808b6001600160a01b031681526020018981526020018b6001600160a01b031663ae9d70b06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611532573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611556919061399f565b81526020018b6001600160a01b031663f8f9da286040518163ffffffff1660e01b8152600401602060405180830381865afa158015611599573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115bd919061399f565b81526020018b6001600160a01b031663173b99046040518163ffffffff1660e01b8152600401602060405180830381865afa158015611600573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611624919061399f565b81526040516302c3bcbb60e01b81526001600160a01b038d811660048301526020909201918916906302c3bcbb90602401602060405180830381865afa158015611672573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611696919061399f565b815260405163252c221960e11b81526001600160a01b038d81166004830152602090920191891690634a58443290602401602060405180830381865afa1580156116e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611708919061399f565b81526020018b6001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561174b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061176f919061399f565b81526020018b6001600160a01b0316638f840ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117d6919061399f565b81526020018b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611819573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061183d919061399f565b81526020018b6001600160a01b0316633b1d21a26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611880573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118a4919061399f565b81526020018615158152602001858152602001846001600160a01b031681526020018b6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611904573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119289190613c61565b60ff168152602081019390935260409092015298975050505050505050565b61194f612d18565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908516906370a0823190602401602060405180830381865afa158015611999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119bd919061399f565b6040516305eff7ef60e21b81526001600160a01b0385811660048301529192506000918616906317bfdfbc906024016020604051808303816000875af1158015611a0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a2f919061399f565b604051633af9e66960e01b81526001600160a01b038681166004830152919250600091871690633af9e669906024016020604051808303816000875af1158015611a7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa1919061399f565b90506000806000886001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0a9190613982565b6040516370a0823160e01b81526001600160a01b038a81166004830152919250908216906370a0823190602401602060405180830381865afa158015611b54573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b78919061399f565b604051636eb1769f60e11b81526001600160a01b038a811660048301528b811660248301529194509082169063dd62ed3e90604401602060405180830381865afa158015611bca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bee919061399f565b6040805160c0810182526001600160a01b038c168152602081019890985287019590955250506060840191909152608083015260a0820152905092915050565b604051631e6db74760e31b81526001600160a01b038281166004830152606091849182169063f36dba3890602401600060405180830381865afa158015611c79573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c419190810190613d0f565b80516060906000816001600160401b03811115611cc057611cc0612e17565b604051908082528060200260200182016040528015611cf957816020015b611ce6612d57565b815260200190600190039081611cde5790505b50905060005b82811015611d4e57611d29858281518110611d1c57611d1c6139b8565b60200260200101516111f9565b828281518110611d3b57611d3b6139b8565b6020908102919091010152600101611cff565b509392505050565b6000611d847f000000000000000000000000000000000000000000000000000000000000000063ffffffff16565b905090565b4390565b4290565b6060600083516001600160401b03811115611dae57611dae612e17565b604051908082528060200260200182016040528015611df357816020015b6040805180820190915260008082526020820152815260200190600190039081611dcc5790505b50905060005b845181101561071457611e2f604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b611e5c604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b7f000000000000000000000000000000000000000000000000000000000000000015611fdf57856001600160a01b0316638f693ec7888581518110611ea357611ea36139b8565b60200260200101516040518263ffffffff1660e01b8152600401611ed691906001600160a01b0391909116815260200190565b606060405180830381865afa158015611ef3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f179190613db4565b604085015260208401526001600160e01b0316825286516001600160a01b03871690638181494590899086908110611f5157611f516139b8565b60200260200101516040518263ffffffff1660e01b8152600401611f8491906001600160a01b0391909116815260200190565b606060405180830381865afa158015611fa1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fc59190613db4565b604084015260208301526001600160e01b0316815261214a565b856001600160a01b0316632c427b57888581518110612000576120006139b8565b60200260200101516040518263ffffffff1660e01b815260040161203391906001600160a01b0391909116815260200190565b606060405180830381865afa158015612050573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120749190613dfd565b63ffffffff90811660408601521660208401526001600160e01b0316825286516001600160a01b038716906392a18235908990869081106120b7576120b76139b8565b60200260200101516040518263ffffffff1660e01b81526004016120ea91906001600160a01b0391909116815260200190565b606060405180830381865afa158015612107573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061212b9190613dfd565b63ffffffff90811660408501521660208301526001600160e01b031681525b60006040518060200160405280898681518110612169576121696139b8565b60200260200101516001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121d2919061399f565b81525090506121fc8885815181106121ec576121ec6139b8565b60200260200101518885846122f1565b612220888581518110612211576122116139b8565b602002602001015188846124f2565b6000612248898681518110612237576122376139b8565b6020026020010151898c87866126e9565b905060006122718a8781518110612261576122616139b8565b60200260200101518a8d87612919565b60408051808201909152600080825260208201529091508a878151811061229a5761229a6139b8565b60209081029190910101516001600160a01b031681526122ba8284613b50565b6020820152875181908990899081106122d5576122d56139b8565b6020026020010181905250505050505050806001019050611df9565b604051637c05a7c560e01b81526001600160a01b03858116600483015260009190851690637c05a7c590602401602060405180830381865afa15801561233b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061235f919061399f565b9050600061236b611d56565b9050600084604001511180156123845750836040015181115b15612390575060408301515b60006123a0828660200151612b3d565b90506000811180156123b25750600083115b156124db576000612424886001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa1580156123fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061241e919061399f565b86612b50565b905060006124328386612b6e565b90506000808311612452576040518060200160405280600081525061245c565b61245c8284612b7a565b9050600061248560405180602001604052808b600001516001600160e01b031681525083612bbf565b90506124c08160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612beb565b6001600160e01b0316895250505050602085018290526124e9565b80156124e957602085018290525b50505050505050565b604051631d31307360e21b81526001600160a01b038481166004830152600091908416906374c4c1cc90602401602060405180830381865afa15801561253c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612560919061399f565b9050600061256c611d56565b9050600083604001511180156125855750826040015181115b15612591575060408201515b60006125a1828560200151612b3d565b90506000811180156125b35750600083115b156126d3576000866001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156125f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061261c919061399f565b9050600061262a8386612b6e565b9050600080831161264a5760405180602001604052806000815250612654565b6126548284612b7a565b9050600061267d60405180602001604052808a600001516001600160e01b031681525083612bbf565b90506126b88160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612beb565b6001600160e01b0316885250505050602084018290526126e1565b80156126e157602084018290525b505050505050565b604080516020808201835284516001600160e01b031682528251908101928390526336fe846560e11b9092526001600160a01b0387811660248401528581166044840152600092839181908916636dfd08ca60648301602060405180830381865afa15801561275c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612780919061399f565b905280519091501580156128025750866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f19190613e40565b6001600160e01b0316826000015110155b1561287557866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612845573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128699190613e40565b6001600160e01b031681525b60006128818383612c27565b6040516395dd919360e01b81526001600160a01b0389811660048301529192506000916128fc91908c16906395dd919390602401602060405180830381865afa1580156128d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128f6919061399f565b87612b50565b9050600061290a8284612c53565b9b9a5050505050505050505050565b604080516020808201835283516001600160e01b0316825282519081019283905263552c097160e01b9092526001600160a01b038681166024840152848116604484015260009283918190881663552c097160648301602060405180830381865afa15801561298c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129b0919061399f565b90528051909150158015612a325750856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a219190613e40565b6001600160e01b0316826000015110155b15612aa557856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a999190613e40565b6001600160e01b031681525b6000612ab18383612c27565b6040516370a0823160e01b81526001600160a01b0388811660048301529192506000918a16906370a0823190602401602060405180830381865afa158015612afd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b21919061399f565b90506000612b2f8284612c53565b9a9950505050505050505050565b6000612b498284613e5b565b9392505050565b6000612b49612b6784670de0b6b3a7640000612b6e565b8351612c7d565b6000612b498284613b17565b6040805160208101909152600081526040518060200160405280612bb6612bb0866ec097ce7bc90715b34b9f1000000000612b6e565b85612c7d565b90529392505050565b6040805160208101909152600081526040518060200160405280612bb685600001518560000151612c89565b6000816001600160e01b03841115612c1f5760405162461bcd60e51b8152600401612c169190613e6e565b60405180910390fd5b509192915050565b6040805160208101909152600081526040518060200160405280612bb685600001518560000151612b3d565b60006ec097ce7bc90715b34b9f1000000000612c73848460000151612b6e565b612b499190613b2e565b6000612b498284613b2e565b6000612b498284613b50565b604051806101a001604052806060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160608152602001606081526020016060815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001606081525090565b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180610220016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b6001600160a01b0381168114612e0457600080fd5b50565b8035612e1281612def565b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715612e4f57612e4f612e17565b60405290565b604051606081016001600160401b0381118282101715612e4f57612e4f612e17565b604051601f8201601f191681016001600160401b0381118282101715612e9f57612e9f612e17565b604052919050565b60006001600160401b03821115612ec057612ec0612e17565b50601f01601f191660200190565b60008060408385031215612ee157600080fd5b8235612eec81612def565b91506020838101356001600160401b0380821115612f0957600080fd5b9085019060a08288031215612f1d57600080fd5b612f25612e2d565b823582811115612f3457600080fd5b83019150601f82018813612f4757600080fd5b8135612f5a612f5582612ea7565b612e77565b8181528986838601011115612f6e57600080fd5b818685018783013760008683830101528083525050612f8e848401612e07565b84820152612f9e60408401612e07565b60408201526060830135606082015260808301356080820152809450505050509250929050565b60005b83811015612fe0578181015183820152602001612fc8565b50506000910152565b60008151808452613001816020860160208601612fc5565b601f01601f19169290920160200192915050565b80516001600160a01b031682526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e0830152610100808201518184015250610120808201518184015250610140808201518184015250610160808201516130a08285018215159052565b505061018081810151908301526101a0808201516001600160a01b0316908301526101c080820151908301526101e0808201519083015261020090810151910152565b60008151808452602080850194506020840160005b8381101561311f5761310b878351613015565b6102209690960195908201906001016130f8565b509495945050505050565b60006101a0825181855261314082860182612fe9565b915050602083015161315d60208601826001600160a01b03169052565b50604083015161317860408601826001600160a01b03169052565b50606083015160608501526080830151608085015260a083015184820360a08601526131a48282612fe9565b91505060c083015184820360c08601526131be8282612fe9565b91505060e083015184820360e08601526131d88282612fe9565b915050610100808401516131f6828701826001600160a01b03169052565b5050610120838101519085015261014080840151908501526101608084015190850152610180808401518583038287015261323183826130e3565b9695505050505050565b602081526000612b49602083018461312a565b60008083601f84011261326057600080fd5b5081356001600160401b0381111561327757600080fd5b6020830191508360208260051b850101111561329257600080fd5b9250929050565b600080602083850312156132ac57600080fd5b82356001600160401b038111156132c257600080fd5b6132ce8582860161324e565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b8281101561332d5761331d84835180516001600160a01b03168252602090810151910152565b92840192908501906001016132f7565b5091979650505050505050565b60006020828403121561334c57600080fd5b8135612b4981612def565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156133ae57603f1988860301845261339c85835161312a565b94509285019290850190600101613380565b5092979650505050505050565b602080825282516001600160a01b03168282015282810151604080840191909152808401516060808501528051608085018190526000939291830191849160a08701905b808410156134395761342582865180516001600160a01b03168252602090810151910152565b9385019360019390930192908201906133ff565b50979650505050505050565b6000806040838503121561345857600080fd5b823561346381612def565b9150602083013561347381612def565b809150509250929050565b60008060006060848603121561349357600080fd5b833561349e81612def565b925060208401356134ae81612def565b915060408401356134be81612def565b809150509250925092565b600060208083018184528085518083526040925060408601915060408160051b8701018488016000805b8481101561359657898403603f19018652825180516001600160a01b03908116865289820151168986015287810151888601526060908101516080918601829052805191860182905289019060a086019084905b808210156135815761356d83855180516001600160a01b03168252602090810151910152565b928b0192918a019160019190910190613547565b505096890196945050918701916001016134f3565b50919998505050505050505050565b6000806000604084860312156135ba57600080fd5b83356001600160401b038111156135d057600080fd5b6135dc8682870161324e565b90945092505060208401356134be81612def565b80516001600160a01b031682526020808201519083015260408082015190830152606080820151908301526080808201519083015260a090810151910152565b6020808252825182820181905260009190848201906040850190845b818110156136725761365f8385516135f0565b9284019260c0929092019160010161364c565b50909695505050505050565b81516001600160a01b03168152602080830151908201526040810161064f565b610220810161064f8284613015565b60c0810161064f82846135f0565b6020808252825182820181905260009190848201906040850190845b818110156136725783516001600160a01b0316835292840192918401916001016136d7565b60006001600160401b0382111561371557613715612e17565b5060051b60200190565b6000602080838503121561373257600080fd5b82356001600160401b0381111561374857600080fd5b8301601f8101851361375957600080fd5b8035613767612f55826136fc565b81815260059190911b8201830190838101908783111561378657600080fd5b928401925b828410156137ad57833561379e81612def565b8252928401929084019061378b565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b81811015613672576137e7838551613015565b9284019261022092909201916001016137d4565b6000602080838503121561380e57600080fd5b82516001600160401b0381111561382457600080fd5b8301601f8101851361383557600080fd5b8051613843612f55826136fc565b81815260059190911b8201830190838101908783111561386257600080fd5b928401925b828410156137ad57835161387a81612def565b82529284019290840190613867565b600082601f83011261389a57600080fd5b81516138a8612f5582612ea7565b8181528460208386010111156138bd57600080fd5b610c41826020830160208701612fc5565b6000602082840312156138e057600080fd5b81516001600160401b03808211156138f757600080fd5b908301906060828603121561390b57600080fd5b613913612e55565b82518281111561392257600080fd5b61392e87828601613889565b82525060208301518281111561394357600080fd5b61394f87828601613889565b60208301525060408301518281111561396757600080fd5b61397387828601613889565b60408301525095945050505050565b60006020828403121561399457600080fd5b8151612b4981612def565b6000602082840312156139b157600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600060a082840312156139e057600080fd5b6139e8612e2d565b905081516001600160401b03811115613a0057600080fd5b613a0c84828501613889565b8252506020820151613a1d81612def565b60208201526040820151613a3081612def565b80604083015250606082015160608201526080820151608082015292915050565b60006020808385031215613a6457600080fd5b82516001600160401b0380821115613a7b57600080fd5b818501915085601f830112613a8f57600080fd5b8151613a9d612f55826136fc565b81815260059190911b83018401908481019088831115613abc57600080fd5b8585015b83811015613af457805185811115613ad85760008081fd5b613ae68b89838a01016139ce565b845250918601918601613ac0565b5098975050505050505050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761064f5761064f613b01565b600082613b4b57634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561064f5761064f613b01565b600060208284031215613b7557600080fd5b81516001600160401b03811115613b8b57600080fd5b610c41848285016139ce565b60006020808385031215613baa57600080fd5b82516001600160401b03811115613bc057600080fd5b8301601f81018513613bd157600080fd5b8051613bdf612f55826136fc565b81815260059190911b82018301908381019087831115613bfe57600080fd5b928401925b828410156137ad578351613c1681612def565b82529284019290840190613c03565b80518015158114612e1257600080fd5b60008060408385031215613c4857600080fd5b613c5183613c25565b9150602083015190509250929050565b600060208284031215613c7357600080fd5b815160ff81168114612b4957600080fd5b634e487b7160e01b600052602160045260246000fd5b6001600160a01b03831681526040810160098310613cc857634e487b7160e01b600052602160045260246000fd5b8260208301529392505050565b600060208284031215613ce757600080fd5b612b4982613c25565b600060ff821660ff8103613d0657613d06613b01565b60010192915050565b60006020808385031215613d2257600080fd5b82516001600160401b03811115613d3857600080fd5b8301601f81018513613d4957600080fd5b8051613d57612f55826136fc565b81815260059190911b82018301908381019087831115613d7657600080fd5b928401925b828410156137ad578351613d8e81612def565b82529284019290840190613d7b565b80516001600160e01b0381168114612e1257600080fd5b600080600060608486031215613dc957600080fd5b613dd284613d9d565b925060208401519150604084015190509250925092565b805163ffffffff81168114612e1257600080fd5b600080600060608486031215613e1257600080fd5b613e1b84613d9d565b9250613e2960208501613de9565b9150613e3760408501613de9565b90509250925092565b600060208284031215613e5257600080fd5b612b4982613d9d565b8181038181111561064f5761064f613b01565b602081526000612b496020830184612fe956fea2646970667358221220b9946cc7fdc900bd3735319cd04868b3796a2261574b7617c9cbf91cb2f997ca64736f6c63430008190033", + "args": [true, 0, "0xe22af1e6b78318e1Fe1053Edbd7209b8Fc62c4Fe"], + "numDeployments": 2, + "solcInputHash": "09f8b2889a382752688c03578bc27f8d", + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"timeBased_\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"blocksPerYear_\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"corePoolComptroller_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidBlocksPerYear\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTimeBasedConfiguration\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"blocksOrSecondsPerYear\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"corePoolComptroller\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"}],\"name\":\"getAllPools\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockNumberOrTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getPendingRewards\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"distributorAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"rewardTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalRewards\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.PendingReward[]\",\"name\":\"pendingRewards\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.RewardSummary[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getPoolBadDebt\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalBadDebtUsd\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"badDebtUsd\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.BadDebt[]\",\"name\":\"badDebts\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.BadDebtSummary\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolByComptroller\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolRegistryInterface.VenusPool\",\"name\":\"venusPool\",\"type\":\"tuple\"}],\"name\":\"getPoolDataFromVenusPool\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getPoolsSupportedByAsset\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getVTokenForAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isTimeBased\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"vTokenBalances\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalanceCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balanceOfUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenAllowance\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenBalances\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"vTokenBalancesAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalanceCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balanceOfUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenAllowance\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenBalances[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"vTokenMetadata\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"vTokenMetadataAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"vTokenUnderlyingPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"underlyingPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenUnderlyingPrice\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"vTokenUnderlyingPriceAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"underlyingPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenUnderlyingPrice[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"params\":{\"blocksPerYear_\":\"The number of blocks per year\",\"corePoolComptroller_\":\"The address of the core pool comptroller\",\"timeBased_\":\"A boolean indicating whether the contract is based on time or block.\"}},\"getAllPools(address)\":{\"details\":\"This function is not designed to be called in a transaction: it is too gas-intensive\",\"params\":{\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"Arrays of all Venus pools' data\"}},\"getBlockNumberOrTimestamp()\":{\"details\":\"Function to simply retrieve block number or block timestamp\",\"returns\":{\"_0\":\"Current block number or block timestamp\"}},\"getPendingRewards(address,address)\":{\"params\":{\"account\":\"The user account.\",\"comptrollerAddress\":\"address\"},\"returns\":{\"_0\":\"Pending rewards array\"}},\"getPoolBadDebt(address)\":{\"params\":{\"comptrollerAddress\":\"Address of the comptroller\"},\"returns\":{\"_0\":\"badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and a break down of bad debt by market\"}},\"getPoolByComptroller(address,address)\":{\"params\":{\"comptroller\":\"The Comptroller implementation address\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"PoolData structure containing the details of the pool\"}},\"getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))\":{\"params\":{\"poolRegistryAddress\":\"Address of the PoolRegistry\",\"venusPool\":\"The VenusPool Object from PoolRegistry\"},\"returns\":{\"_0\":\"Enriched PoolData\"}},\"getPoolsSupportedByAsset(address,address)\":{\"params\":{\"asset\":\"The underlying asset of vToken\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"A list of Comptroller contracts\"}},\"getVTokenForAsset(address,address,address)\":{\"params\":{\"asset\":\"The underlyingAsset of VToken\",\"comptroller\":\"The pool comptroller\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"Address of the vToken\"}},\"vTokenBalances(address,address)\":{\"params\":{\"account\":\"The user Account\",\"vToken\":\"vToken address\"},\"returns\":{\"_0\":\"A struct containing the balances data\"}},\"vTokenBalancesAll(address[],address)\":{\"params\":{\"account\":\"The user Account\",\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"A list of structs containing balances data\"}},\"vTokenMetadata(address)\":{\"params\":{\"vToken\":\"The address of vToken\"},\"returns\":{\"_0\":\"VTokenMetadata struct\"}},\"vTokenMetadataAll(address[])\":{\"params\":{\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"An array of VTokenMetadata structs\"}},\"vTokenUnderlyingPrice(address)\":{\"params\":{\"vToken\":\"vToken address\"},\"returns\":{\"_0\":\"The price data for each asset\"}},\"vTokenUnderlyingPriceAll(address[])\":{\"params\":{\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"An array containing the price data for each asset\"}}},\"title\":\"PoolLens\",\"version\":1},\"userdoc\":{\"errors\":{\"InvalidBlocksPerYear()\":[{\"notice\":\"Thrown when blocks per year is invalid\"}],\"InvalidTimeBasedConfiguration()\":[{\"notice\":\"Thrown when time based but blocks per year is provided\"}]},\"kind\":\"user\",\"methods\":{\"blocksOrSecondsPerYear()\":{\"notice\":\"Stores blocksPerYear if isTimeBased is true else secondsPerYear is stored\"},\"corePoolComptroller()\":{\"notice\":\"Address of the core pool comptroller (all markets are returned for this pool, including paused ones)\"},\"getAllPools(address)\":{\"notice\":\"Queries all pools with addtional details for each of them\"},\"getPendingRewards(address,address)\":{\"notice\":\"Returns the pending rewards for a user for a given pool.\"},\"getPoolBadDebt(address)\":{\"notice\":\"Returns a summary of a pool's bad debt broken down by market\"},\"getPoolByComptroller(address,address)\":{\"notice\":\"Queries the details of a pool identified by Comptroller address\"},\"getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))\":{\"notice\":\"Queries additional information for the pool\"},\"getPoolsSupportedByAsset(address,address)\":{\"notice\":\"Returns all pools that support the specified underlying asset\"},\"getVTokenForAsset(address,address,address)\":{\"notice\":\"Returns vToken holding the specified underlying asset in the specified pool\"},\"isTimeBased()\":{\"notice\":\"Acknowledges if a contract is time based or not\"},\"vTokenBalances(address,address)\":{\"notice\":\"Queries the user's supply/borrow balances in the specified vToken\"},\"vTokenBalancesAll(address[],address)\":{\"notice\":\"Queries the user's supply/borrow balances in vTokens\"},\"vTokenMetadata(address)\":{\"notice\":\"Returns the metadata of VToken\"},\"vTokenMetadataAll(address[])\":{\"notice\":\"Returns the metadata of all VTokens\"},\"vTokenUnderlyingPrice(address)\":{\"notice\":\"Returns the price data for the underlying asset of the specified vToken\"},\"vTokenUnderlyingPriceAll(address[])\":{\"notice\":\"Returns the price data for the underlying assets of the specified vTokens\"}},\"notice\":\"The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be looked up for specific pools and markets: - the vToken balance of a given user; - the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address; - the vToken address in a pool for a given asset; - a list of all pools that support an asset; - the underlying asset price of a vToken; - the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Lens/PoolLens.sol\":\"PoolLens\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"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\",\"keccak256\":\"0x9140dabc466abab21b48b72dbda26736b1183a310d0e677d3719d201df026510\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x359a1ab89b46b9aba7bcad3fb651924baf4893d15153049b9976b0fc9be1358e\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x07e881de3b9f6d2c07909f193f24b96c7fe4ea60013260f3f25aecd8bab3c2f8\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0x75097e35253e7fb282ee4d7f27a80eaacfa759923185bf17302a89cbc059c5ef\",\"license\":\"MIT\"},\"@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\"},\"@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\",\"keccak256\":\"0xfe0fd441c84ac907cabc88db69ef04f6d7532d770c7e6a1dfe6e7d6305debb49\",\"license\":\"BSD-3-Clause\"},\"@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 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/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface IProtocolShareReserve {\\n /// @notice it represents the type of vToken income\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(\\n address comptroller,\\n address asset,\\n IncomeType incomeType\\n ) external;\\n}\\n\",\"keccak256\":\"0x0f341bbef8f12885d79b7acaad7aaf11b84809e8f6b059ef4efc011c8f6c39a5\",\"license\":\"BSD-3-Clause\"},\"@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\",\"keccak256\":\"0x57a2bbb9b8e02b1c0a5c0e305fef1328a22db56c3d4b148c362010a6e767243c\",\"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\"},\"@venusprotocol/venus-protocol/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\",\"keccak256\":\"0xd112f60183416ad796093b4a83a80ddc1b8b655965f02ae55ca82e2a0c68f97d\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/venus-protocol/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\",\"keccak256\":\"0x5285c875114db2ea2be0b81b65722d5761806217022db733323c4e03365a95e7\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IPrime } from \\\"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\\\";\\n\\nimport { ComptrollerInterface, Action } from \\\"./ComptrollerInterface.sol\\\";\\nimport { ComptrollerStorage } from \\\"./ComptrollerStorage.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"./MaxLoopsLimitHelper.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title Comptroller\\n * @author Venus\\n * @notice The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating,\\n * and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts\\n * with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows\\n * or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing\\n * liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow,\\n * as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the\\n * markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market\\u2019s corresponding liquidation threshold,\\n * the borrow is eligible for liquidation.\\n *\\n * The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed\\n * the `minLiquidatableCollateral` for the `Comptroller`:\\n *\\n * - `healAccount()`: This function is called to seize all of a given user\\u2019s collateral, requiring the `msg.sender` repay a certain percentage\\n * of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed\\n * 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt\\n * and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool.\\n * - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation\\n * incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic\\n * verifying that the repay amount does not exceed the close factor.\\n */\\ncontract Comptroller is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n ComptrollerStorage,\\n ComptrollerInterface,\\n ExponentialNoError,\\n MaxLoopsLimitHelper\\n{\\n // PoolRegistry, immutable to save on gas\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n address public immutable poolRegistry;\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(VToken indexed vToken, address indexed account);\\n\\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(VToken vToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa);\\n\\n /// @notice Emitted when liquidation threshold is changed by admin\\n event NewLiquidationThreshold(\\n VToken vToken,\\n uint256 oldLiquidationThresholdMantissa,\\n uint256 newLiquidationThresholdMantissa\\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 an action is paused on a market\\n event ActionPausedMarket(VToken vToken, Action action, bool pauseState);\\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 the collateral threshold (in USD) for non-batch liquidations is changed\\n event NewMinLiquidatableCollateral(uint256 oldMinLiquidatableCollateral, uint256 newMinLiquidatableCollateral);\\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 a rewards distributor is added\\n event NewRewardsDistributor(address indexed rewardsDistributor, address indexed rewardToken);\\n\\n /// @notice Emitted when a market is supported\\n event MarketSupported(VToken vToken);\\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 a market\\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\\n\\n /// @notice Emitted when a market is unlisted\\n event MarketUnlisted(address indexed vToken);\\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 Thrown when collateral factor exceeds the upper bound\\n error InvalidCollateralFactor();\\n\\n /// @notice Thrown when liquidation threshold exceeds the collateral factor\\n error InvalidLiquidationThreshold();\\n\\n /// @notice Thrown when the action is only available to specific sender, but the real sender was different\\n error UnexpectedSender(address expectedSender, address actualSender);\\n\\n /// @notice Thrown when the oracle returns an invalid price for some asset\\n error PriceError(address vToken);\\n\\n /// @notice Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\\n error SnapshotError(address vToken, address user);\\n\\n /// @notice Thrown when the market is not listed\\n error MarketNotListed(address market);\\n\\n /// @notice Thrown when a market has an unexpected comptroller\\n error ComptrollerMismatch();\\n\\n /// @notice Thrown when user is not member of market\\n error MarketNotCollateral(address vToken, address user);\\n\\n /// @notice Thrown when borrow action is not paused\\n error BorrowActionNotPaused();\\n\\n /// @notice Thrown when mint action is not paused\\n error MintActionNotPaused();\\n\\n /// @notice Thrown when redeem action is not paused\\n error RedeemActionNotPaused();\\n\\n /// @notice Thrown when repay action is not paused\\n error RepayActionNotPaused();\\n\\n /// @notice Thrown when seize action is not paused\\n error SeizeActionNotPaused();\\n\\n /// @notice Thrown when exit market action is not paused\\n error ExitMarketActionNotPaused();\\n\\n /// @notice Thrown when transfer action is not paused\\n error TransferActionNotPaused();\\n\\n /// @notice Thrown when enter market action is not paused\\n error EnterMarketActionNotPaused();\\n\\n /// @notice Thrown when liquidate action is not paused\\n error LiquidateActionNotPaused();\\n\\n /// @notice Thrown when borrow cap is not zero\\n error BorrowCapIsNotZero();\\n\\n /// @notice Thrown when supply cap is not zero\\n error SupplyCapIsNotZero();\\n\\n /// @notice Thrown when collateral factor is not zero\\n error CollateralFactorIsNotZero();\\n\\n /**\\n * @notice Thrown during the liquidation if user's total collateral amount is lower than\\n * a predefined threshold. In this case only batch liquidations (either liquidateAccount\\n * or healAccount) are available.\\n */\\n error MinimalCollateralViolated(uint256 expectedGreaterThan, uint256 actual);\\n error CollateralExceedsThreshold(uint256 expectedLessThanOrEqualTo, uint256 actual);\\n error InsufficientCollateral(uint256 collateralToSeize, uint256 availableCollateral);\\n\\n /// @notice Thrown when the account doesn't have enough liquidity to redeem or borrow\\n error InsufficientLiquidity();\\n\\n /// @notice Thrown when trying to liquidate a healthy account\\n error InsufficientShortfall();\\n\\n /// @notice Thrown when trying to repay more than allowed by close factor\\n error TooMuchRepay();\\n\\n /// @notice Thrown if the user is trying to exit a market in which they have an outstanding debt\\n error NonzeroBorrowBalance();\\n\\n /// @notice Thrown when trying to perform an action that is paused\\n error ActionPaused(address market, Action action);\\n\\n /// @notice Thrown when trying to add a market that is already listed\\n error MarketAlreadyListed(address market);\\n\\n /// @notice Thrown if the supply cap is exceeded\\n error SupplyCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if the borrow cap is exceeded\\n error BorrowCapExceeded(address market, uint256 cap);\\n\\n /// @notice Thrown if delegate approval status is already set to the requested value\\n error DelegationStatusUnchanged();\\n\\n /// @param poolRegistry_ Pool registry address\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\\n constructor(address poolRegistry_) {\\n ensureNonzeroAddress(poolRegistry_);\\n\\n poolRegistry = poolRegistry_;\\n _disableInitializers();\\n }\\n\\n /**\\n * @param loopLimit Limit for the loops can iterate to avoid the DOS\\n * @param accessControlManager Access control manager contract address\\n */\\n function initialize(uint256 loopLimit, address accessControlManager) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager);\\n\\n _setMaxLoopsLimit(loopLimit);\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation; enabling them to be used as collateral\\n * @param vTokens The list of addresses of the vToken markets to be enabled\\n * @return errors An array of NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketEntered is emitted for each market on success\\n * @custom:error ActionPaused error is thrown if entering any of the markets is paused\\n * @custom:error MarketNotListed error is thrown if any of the markets is not listed\\n * @custom:access Not restricted\\n */\\n function enterMarkets(address[] memory vTokens) external override returns (uint256[] memory) {\\n uint256 len = vTokens.length;\\n\\n uint256[] memory results = new uint256[](len);\\n for (uint256 i; i < len; ++i) {\\n VToken vToken = VToken(vTokens[i]);\\n\\n _addToMarket(vToken, msg.sender);\\n results[i] = NO_ERROR;\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Unlist a market by setting isListed to false\\n * @dev Checks if all actions are paused, borrow/supply caps is set to 0 and collateral factor is to 0.\\n * @param market The address of the market (token) to unlist\\n * @return uint256 Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketUnlisted is emitted on success\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error BorrowActionNotPaused error is thrown if borrow action is not paused\\n * @custom:error MintActionNotPaused error is thrown if mint action is not paused\\n * @custom:error RedeemActionNotPaused error is thrown if redeem action is not paused\\n * @custom:error RepayActionNotPaused error is thrown if repay action is not paused\\n * @custom:error EnterMarketActionNotPaused error is thrown if enter market action is not paused\\n * @custom:error LiquidateActionNotPaused error is thrown if liquidate action is not paused\\n * @custom:error BorrowCapIsNotZero error is thrown if borrow cap is not zero\\n * @custom:error SupplyCapIsNotZero error is thrown if supply cap is not zero\\n * @custom:error CollateralFactorIsNotZero error is thrown if collateral factor is not zero\\n */\\n function unlistMarket(address market) external returns (uint256) {\\n _checkAccessAllowed(\\\"unlistMarket(address)\\\");\\n\\n Market storage _market = markets[market];\\n\\n if (!_market.isListed) {\\n revert MarketNotListed(market);\\n }\\n\\n if (!actionPaused(market, Action.BORROW)) {\\n revert BorrowActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.MINT)) {\\n revert MintActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.REDEEM)) {\\n revert RedeemActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.REPAY)) {\\n revert RepayActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.SEIZE)) {\\n revert SeizeActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.ENTER_MARKET)) {\\n revert EnterMarketActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.LIQUIDATE)) {\\n revert LiquidateActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.TRANSFER)) {\\n revert TransferActionNotPaused();\\n }\\n\\n if (!actionPaused(market, Action.EXIT_MARKET)) {\\n revert ExitMarketActionNotPaused();\\n }\\n\\n if (borrowCaps[market] != 0) {\\n revert BorrowCapIsNotZero();\\n }\\n\\n if (supplyCaps[market] != 0) {\\n revert SupplyCapIsNotZero();\\n }\\n\\n if (_market.collateralFactorMantissa != 0) {\\n revert CollateralFactorIsNotZero();\\n }\\n\\n _market.isListed = false;\\n emit MarketUnlisted(market);\\n\\n return NO_ERROR;\\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 * @custom:event DelegateUpdated emits on success\\n * @custom:error ZeroAddressNotAllowed is thrown when delegate address is zero\\n * @custom:error DelegationStatusUnchanged is thrown if approval status is already set to the requested value\\n * @custom:access Not restricted\\n */\\n function updateDelegate(address delegate, bool approved) external {\\n ensureNonzeroAddress(delegate);\\n if (approvedDelegates[msg.sender][delegate] == approved) {\\n revert DelegationStatusUnchanged();\\n }\\n\\n approvedDelegates[msg.sender][delegate] = approved;\\n emit DelegateUpdated(msg.sender, delegate, approved);\\n }\\n\\n /**\\n * @notice Removes asset from sender's account liquidity calculation; disabling them as collateral\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event MarketExited is emitted on success\\n * @custom:error ActionPaused error is thrown if exiting the market is paused\\n * @custom:error NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function exitMarket(address vTokenAddress) external override returns (uint256) {\\n _checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\\n VToken vToken = VToken(vTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\\n (uint256 tokensHeld, uint256 amountOwed, ) = _safeGetAccountSnapshot(vToken, msg.sender);\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n revert NonzeroBorrowBalance();\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n _checkRedeemAllowed(vTokenAddress, msg.sender, tokensHeld);\\n\\n Market storage marketToExit = markets[address(vToken)];\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return 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 // load into memory for faster iteration\\n VToken[] memory userAssetList = accountAssets[msg.sender];\\n uint256 len = userAssetList.length;\\n\\n uint256 assetIndex = len;\\n for (uint256 i; i < len; ++i) {\\n if (userAssetList[i] == vToken) {\\n assetIndex = i;\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(assetIndex < len);\\n\\n // copy last item in list to location of item to be removed, reduce length by 1\\n VToken[] storage storedList = accountAssets[msg.sender];\\n storedList[assetIndex] = storedList[storedList.length - 1];\\n storedList.pop();\\n\\n emit MarketExited(vToken, msg.sender);\\n\\n return NO_ERROR;\\n }\\n\\n /*** Policy Hooks ***/\\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 * @custom:error ActionPaused error is thrown if supplying to this market is paused\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\\n * @custom:access Not restricted\\n */\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external override {\\n _checkActionPauseState(vToken, Action.MINT);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n uint256 supplyCap = supplyCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (supplyCap != type(uint256).max) {\\n uint256 vTokenSupply = VToken(vToken).totalSupply();\\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\\n if (nextTotalSupply > supplyCap) {\\n revert SupplyCapExceeded(vToken, supplyCap);\\n }\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, minter);\\n }\\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external override {\\n _checkActionPauseState(vToken, Action.REDEEM);\\n\\n _checkRedeemAllowed(vToken, redeemer, redeemTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, redeemer);\\n }\\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 if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(redeemer, vToken);\\n }\\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 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 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 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 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 * @custom:error ActionPaused error is thrown if borrowing is paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if there is not enough collateral to borrow\\n * @custom:error BorrowCapExceeded is thrown if the borrow cap will be exceeded should this borrow succeed\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted if vToken is enabled as collateral, otherwise only vToken\\n */\\n /// disable-eslint\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external override {\\n _checkActionPauseState(vToken, Action.BORROW);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (!markets[vToken].accountMembership[borrower]) {\\n // only vTokens may call borrowAllowed if borrower not in market\\n _checkSenderIs(vToken);\\n\\n // attempt to add borrower to the market or revert\\n _addToMarket(VToken(msg.sender), borrower);\\n }\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (oracle.getUnderlyingPrice(vToken) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 borrowCap = borrowCaps[vToken];\\n // Skipping the cap check for uncapped coins to save some gas\\n if (borrowCap != type(uint256).max) {\\n uint256 totalBorrows = VToken(vToken).totalBorrows();\\n uint256 badDebt = VToken(vToken).badDebt();\\n uint256 nextTotalBorrows = totalBorrows + borrowAmount + badDebt;\\n if (nextTotalBorrows > borrowCap) {\\n revert BorrowCapExceeded(vToken, borrowCap);\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n borrower,\\n VToken(vToken),\\n 0,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\n }\\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 borrower The account which would borrowed the asset\\n * @custom:error ActionPaused error is thrown if repayments are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:access Not restricted\\n */\\n function preRepayHook(address vToken, address borrower) external override {\\n _checkActionPauseState(vToken, Action.REPAY);\\n\\n oracle.updatePrice(vToken);\\n\\n if (!markets[vToken].isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\\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 borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n * @param skipLiquidityCheck Allows the borrow to be liquidated regardless of the account liquidity\\n * @custom:error ActionPaused error is thrown if liquidations are paused in this market\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor\\n * @custom:error MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations\\n * @custom:error InsufficientShortfall is thrown when trying to liquidate a healthy account\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n */\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external override {\\n // Pause Action.LIQUIDATE on BORROWED TOKEN to prevent liquidating it.\\n // If we want to pause liquidating to vTokenCollateral, we should pause\\n // Action.SEIZE on it\\n _checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\\n\\n // Update the prices of tokens\\n updatePrices(borrower);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(address(vTokenBorrowed));\\n }\\n if (!markets[vTokenCollateral].isListed) {\\n revert MarketNotListed(address(vTokenCollateral));\\n }\\n\\n uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\\n\\n /* Allow accounts to be liquidated if it is a forced liquidation */\\n if (skipLiquidityCheck || isForcedLiquidationEnabled[vTokenBorrowed]) {\\n if (repayAmount > borrowBalance) {\\n revert TooMuchRepay();\\n }\\n return;\\n }\\n\\n /* The borrower must have shortfall and collateral > threshold in order to be liquidatable */\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral <= minLiquidatableCollateral) {\\n /* The liquidator should use either liquidateAccount or healAccount */\\n revert MinimalCollateralViolated(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n /* The liquidator may not repay more than what is allowed by the closeFactor */\\n uint256 maxClose = mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance);\\n if (repayAmount > maxClose) {\\n revert TooMuchRepay();\\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 seizerContract Contract that tries to seize the asset (either borrowed vToken or Comptroller)\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @custom:error ActionPaused error is thrown if seizing this type of collateral is paused\\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\\n * @custom:error ComptrollerMismatch error is when seizer contract or seized asset belong to different pools\\n * @custom:access Not restricted\\n */\\n function preSeizeHook(\\n address vTokenCollateral,\\n address seizerContract,\\n address liquidator,\\n address borrower\\n ) external override {\\n // Pause Action.SEIZE on COLLATERAL to prevent seizing it.\\n // If we want to pause liquidating vTokenBorrowed, we should pause\\n // Action.LIQUIDATE on it\\n _checkActionPauseState(vTokenCollateral, Action.SEIZE);\\n\\n Market storage market = markets[vTokenCollateral];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(vTokenCollateral);\\n }\\n\\n if (seizerContract == address(this)) {\\n // If Comptroller is the seizer, just check if collateral's comptroller\\n // is equal to the current address\\n if (address(VToken(vTokenCollateral).comptroller()) != address(this)) {\\n revert ComptrollerMismatch();\\n }\\n } else {\\n // If the seizer is not the Comptroller, check that the seizer is a\\n // listed market, and that the markets' comptrollers match\\n if (!markets[seizerContract].isListed) {\\n revert MarketNotListed(seizerContract);\\n }\\n if (VToken(vTokenCollateral).comptroller() != VToken(seizerContract).comptroller()) {\\n revert ComptrollerMismatch();\\n }\\n }\\n\\n if (!market.accountMembership[borrower]) {\\n revert MarketNotCollateral(vTokenCollateral, borrower);\\n }\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vTokenCollateral);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, borrower);\\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, liquidator);\\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external override {\\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 _checkRedeemAllowed(vToken, src, transferTokens);\\n\\n // Keep the flywheel moving\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, src);\\n rewardsDistributor.distributeSupplierRewardToken(vToken, dst);\\n }\\n }\\n\\n /*** Pool-level operations ***/\\n\\n /**\\n * @notice Seizes all the remaining collateral, makes msg.sender repay the existing\\n * borrows, and treats the rest of the debt as bad debt (for each market).\\n * The sender has to repay a certain percentage of the debt, computed as\\n * collateral / (borrows * liquidationIncentive).\\n * @param user account to heal\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for healing\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function healAccount(address user) external {\\n VToken[] memory userAssets = getAssetsIn(user);\\n uint256 userAssetsCount = userAssets.length;\\n\\n address liquidator = msg.sender;\\n {\\n ResilientOracleInterface oracle_ = oracle;\\n // We need all user's markets to be fresh for the computations to be correct\\n for (uint256 i; i < userAssetsCount; ++i) {\\n userAssets[i].accrueInterest();\\n oracle_.updatePrice(address(userAssets[i]));\\n }\\n }\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(user, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n // percentage = collateral / (borrows * liquidation incentive)\\n Exp memory collateral = Exp({ mantissa: snapshot.totalCollateral });\\n Exp memory scaledBorrows = mul_(\\n Exp({ mantissa: snapshot.borrows }),\\n Exp({ mantissa: liquidationIncentiveMantissa })\\n );\\n\\n Exp memory percentage = div_(collateral, scaledBorrows);\\n if (lessThanExp(Exp({ mantissa: MANTISSA_ONE }), percentage)) {\\n revert CollateralExceedsThreshold(scaledBorrows.mantissa, collateral.mantissa);\\n }\\n\\n for (uint256 i; i < userAssetsCount; ++i) {\\n VToken market = userAssets[i];\\n\\n (uint256 tokens, uint256 borrowBalance, ) = _safeGetAccountSnapshot(market, user);\\n uint256 repaymentAmount = mul_ScalarTruncate(percentage, borrowBalance);\\n\\n // Seize the entire collateral\\n if (tokens != 0) {\\n market.seize(liquidator, user, tokens);\\n }\\n // Repay a certain percentage of the borrow, forgive the rest\\n if (borrowBalance != 0) {\\n market.healBorrow(liquidator, user, repaymentAmount);\\n }\\n }\\n }\\n\\n /**\\n * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than\\n * a predefined threshold, and the account collateral can be seized to cover all borrows. If\\n * the collateral is higher than the threshold, use regular liquidations. If the collateral is\\n * below the threshold, and the account is insolvent, use healAccount.\\n * @param borrower the borrower address\\n * @param orders an array of liquidation orders\\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation\\n * @custom:error InsufficientCollateral error is thrown when there is not enough collateral to cover the debt\\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\\n * @custom:access Not restricted\\n */\\n function liquidateAccount(address borrower, LiquidationOrder[] calldata orders) external {\\n // We will accrue interest and update the oracle prices later during the liquidation\\n\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\\n\\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\\n // You should use the regular vToken.liquidateBorrow(...) call\\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\\n }\\n\\n uint256 collateralToSeize = mul_ScalarTruncate(\\n Exp({ mantissa: liquidationIncentiveMantissa }),\\n snapshot.borrows\\n );\\n if (collateralToSeize >= snapshot.totalCollateral) {\\n // There is not enough collateral to seize. Use healBorrow to repay some part of the borrow\\n // and record bad debt.\\n revert InsufficientCollateral(collateralToSeize, snapshot.totalCollateral);\\n }\\n\\n if (snapshot.shortfall == 0) {\\n revert InsufficientShortfall();\\n }\\n\\n uint256 ordersCount = orders.length;\\n\\n _ensureMaxLoops(ordersCount / 2);\\n\\n for (uint256 i; i < ordersCount; ++i) {\\n if (!markets[address(orders[i].vTokenBorrowed)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenBorrowed));\\n }\\n if (!markets[address(orders[i].vTokenCollateral)].isListed) {\\n revert MarketNotListed(address(orders[i].vTokenCollateral));\\n }\\n\\n LiquidationOrder calldata order = orders[i];\\n order.vTokenBorrowed.forceLiquidateBorrow(\\n msg.sender,\\n borrower,\\n order.repayAmount,\\n order.vTokenCollateral,\\n true\\n );\\n }\\n\\n VToken[] memory borrowMarkets = getAssetsIn(borrower);\\n uint256 marketsCount = borrowMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower);\\n require(borrowBalance == 0, \\\"Nonzero borrow balance after liquidation\\\");\\n }\\n }\\n\\n /**\\n * @notice Sets the closeFactor to use when liquidating borrows\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @custom:event Emits NewCloseFactor on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCloseFactor(uint256 newCloseFactorMantissa) external {\\n _checkAccessAllowed(\\\"setCloseFactor(uint256)\\\");\\n require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, \\\"Close factor greater than maximum close factor\\\");\\n require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, \\\"Close factor smaller than minimum close factor\\\");\\n\\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets the collateralFactor for a market\\n * @dev This function is restricted by the AccessControlManager\\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 * @custom:event Emits NewCollateralFactor when collateral factor is updated\\n * and NewLiquidationThreshold when liquidation threshold is updated\\n * @custom:error MarketNotListed error is thrown when the market is not listed\\n * @custom:error InvalidCollateralFactor error is thrown when collateral factor is too high\\n * @custom:error InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor\\n * @custom:error PriceError is thrown when the oracle returns an invalid price for the asset\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setCollateralFactor(\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external {\\n _checkAccessAllowed(\\\"setCollateralFactor(address,uint256,uint256)\\\");\\n\\n // Verify market is listed\\n Market storage market = markets[address(vToken)];\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n // Check collateral factor <= 0.9\\n if (newCollateralFactorMantissa > MAX_COLLATERAL_FACTOR_MANTISSA) {\\n revert InvalidCollateralFactor();\\n }\\n\\n // Ensure that liquidation threshold <= 1\\n if (newLiquidationThresholdMantissa > MANTISSA_ONE) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // Ensure that liquidation threshold >= CF\\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\\n revert InvalidLiquidationThreshold();\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\\n revert PriceError(address(vToken));\\n }\\n\\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n }\\n\\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\\n emit NewLiquidationThreshold(vToken, oldLiquidationThresholdMantissa, newLiquidationThresholdMantissa);\\n }\\n }\\n\\n /**\\n * @notice Sets liquidationIncentive\\n * @dev This function is restricted by the AccessControlManager\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @custom:event Emits NewLiquidationIncentive on success\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external {\\n require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, \\\"liquidation incentive should be greater than 1e18\\\");\\n\\n _checkAccessAllowed(\\\"setLiquidationIncentive(uint256)\\\");\\n\\n // Save current value for use in log\\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\\n\\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\\n /**\\n * @notice Add the market to the markets mapping and set it as listed\\n * @dev Only callable by the PoolRegistry\\n * @param vToken The address of the market (token) to list\\n * @custom:error MarketAlreadyListed is thrown if the market is already listed in this pool\\n * @custom:access Only PoolRegistry\\n */\\n function supportMarket(VToken vToken) external {\\n _checkSenderIs(poolRegistry);\\n\\n if (markets[address(vToken)].isListed) {\\n revert MarketAlreadyListed(address(vToken));\\n }\\n\\n require(vToken.isVToken(), \\\"Comptroller: Invalid vToken\\\"); // Sanity check to make sure its really a VToken\\n\\n Market storage newMarket = markets[address(vToken)];\\n newMarket.isListed = true;\\n newMarket.collateralFactorMantissa = 0;\\n newMarket.liquidationThresholdMantissa = 0;\\n\\n _addMarket(address(vToken));\\n\\n uint256 rewardDistributorsCount = rewardsDistributors.length;\\n\\n for (uint256 i; i < rewardDistributorsCount; ++i) {\\n rewardsDistributors[i].initializeMarket(address(vToken));\\n }\\n\\n emit MarketSupported(vToken);\\n }\\n\\n /**\\n * @notice Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A borrow cap of type(uint256).max corresponds to unlimited borrowing.\\n * @dev Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed\\n until the total borrows amount goes below the new borrow cap\\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 type(uint256).max corresponds to unlimited borrowing.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\\n _checkAccessAllowed(\\\"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 _ensureMaxLoops(numMarkets);\\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 * @notice Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\\n * @dev This function is restricted by the AccessControlManager\\n * @dev A supply cap of type(uint256).max corresponds to unlimited supply.\\n * @dev Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed\\n until the total supplies amount goes below the new supply cap\\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 type(uint256).max corresponds to unlimited supply.\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\\n _checkAccessAllowed(\\\"setMarketSupplyCaps(address[],uint256[])\\\");\\n uint256 vTokensCount = vTokens.length;\\n\\n require(vTokensCount != 0, \\\"invalid number of markets\\\");\\n require(vTokensCount == newSupplyCaps.length, \\\"invalid number of markets\\\");\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\\n }\\n }\\n\\n /**\\n * @notice Pause/unpause specified actions\\n * @dev This function is restricted by the AccessControlManager\\n * @param marketsList Markets to pause/unpause the actions on\\n * @param actionsList List of action ids to pause/unpause\\n * @param paused The new paused state (true=paused, false=unpaused)\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setActionsPaused(VToken[] calldata marketsList, Action[] calldata actionsList, bool paused) external {\\n _checkAccessAllowed(\\\"setActionsPaused(address[],uint256[],bool)\\\");\\n\\n uint256 marketsCount = marketsList.length;\\n uint256 actionsCount = actionsList.length;\\n\\n _ensureMaxLoops(marketsCount * actionsCount);\\n\\n for (uint256 marketIdx; marketIdx < marketsCount; ++marketIdx) {\\n for (uint256 actionIdx; actionIdx < actionsCount; ++actionIdx) {\\n _setActionPaused(address(marketsList[marketIdx]), actionsList[actionIdx], paused);\\n }\\n }\\n }\\n\\n /**\\n * @notice Set the given collateral threshold for non-batch liquidations. Regular liquidations\\n * will fail if the collateral amount is less than this threshold. Liquidators should use batch\\n * operations like liquidateAccount or healAccount.\\n * @dev This function is restricted by the AccessControlManager\\n * @param newMinLiquidatableCollateral The new min liquidatable collateral (in USD).\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external {\\n _checkAccessAllowed(\\\"setMinLiquidatableCollateral(uint256)\\\");\\n\\n uint256 oldMinLiquidatableCollateral = minLiquidatableCollateral;\\n minLiquidatableCollateral = newMinLiquidatableCollateral;\\n emit NewMinLiquidatableCollateral(oldMinLiquidatableCollateral, newMinLiquidatableCollateral);\\n }\\n\\n /**\\n * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor\\n * contracts with the same rewardToken, and there could be overlaping among them considering the last reward slot (block or second)\\n * @dev Only callable by the admin\\n * @param _rewardsDistributor Address of the RewardDistributor contract to add\\n * @custom:access Only Governance\\n * @custom:event Emits NewRewardsDistributor with distributor address\\n */\\n function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner {\\n require(!rewardsDistributorExists[address(_rewardsDistributor)], \\\"already exists\\\");\\n\\n uint256 rewardsDistributorsLen = rewardsDistributors.length;\\n _ensureMaxLoops(rewardsDistributorsLen + 1);\\n\\n rewardsDistributors.push(_rewardsDistributor);\\n rewardsDistributorExists[address(_rewardsDistributor)] = true;\\n\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n _rewardsDistributor.initializeMarket(address(allMarkets[i]));\\n }\\n\\n emit NewRewardsDistributor(address(_rewardsDistributor), address(_rewardsDistributor.rewardToken()));\\n }\\n\\n /**\\n * @notice Sets a new price oracle for the Comptroller\\n * @dev Only callable by the admin\\n * @param newOracle Address of the new price oracle to set\\n * @custom:event Emits NewPriceOracle on success\\n * @custom:error ZeroAddressNotAllowed is thrown when the new oracle address is zero\\n */\\n function setPriceOracle(ResilientOracleInterface newOracle) external onlyOwner {\\n ensureNonzeroAddress(address(newOracle));\\n\\n ResilientOracleInterface oldOracle = oracle;\\n oracle = newOracle;\\n emit NewPriceOracle(oldOracle, newOracle);\\n }\\n\\n /**\\n * @notice Set the for loop iteration limit to avoid DOS\\n * @param limit Limit for the max loops can execute at a time\\n */\\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Sets the prime token contract for the comptroller\\n * @param _prime Address of the Prime contract\\n */\\n function setPrimeToken(IPrime _prime) external onlyOwner {\\n ensureNonzeroAddress(address(_prime));\\n\\n emit NewPrimeToken(prime, _prime);\\n prime = _prime;\\n }\\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 * @param vTokenBorrowed Borrowed vToken\\n * @param enable Whether to enable forced liquidations\\n */\\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\\n _checkAccessAllowed(\\\"setForcedLiquidation(address,bool)\\\");\\n ensureNonzeroAddress(vTokenBorrowed);\\n\\n if (!markets[vTokenBorrowed].isListed) {\\n revert MarketNotListed(vTokenBorrowed);\\n }\\n\\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to liquidation threshold requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of liquidation threshold requirements,\\n * @return shortfall Account shortfall below liquidation threshold requirements\\n */\\n function getAccountLiquidity(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getLiquidationThreshold);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity with respect to collateral requirements\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\n * @param account The account get liquidity for\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Account liquidity in excess of collateral requirements,\\n * @return shortfall Account shortfall below collateral requirements\\n */\\n function getBorrowingPower(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getCollateralFactor);\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return liquidity Hypothetical account liquidity in excess of collateral requirements,\\n * @return shortfall 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 error, uint256 liquidity, uint256 shortfall) {\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n account,\\n VToken(vTokenModify),\\n redeemTokens,\\n borrowAmount,\\n _getCollateralFactor\\n );\\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\\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 markets The list of market addresses\\n */\\n function getAllMarkets() external view override returns (VToken[] memory) {\\n return allMarkets;\\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 /*** Assets You Are In ***/\\n\\n /**\\n * @notice Returns whether the given account is entered in a given market\\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 market specified, 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 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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return tokensToSeize Number of vTokenCollateral tokens to be seized in a liquidation\\n * @custom:error PriceError if the oracle returns an invalid price\\n */\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view override returns (uint256 error, uint256 tokensToSeize) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint256 priceBorrowedMantissa = _safeGetUnderlyingPrice(VToken(vTokenBorrowed));\\n uint256 priceCollateralMantissa = _safeGetUnderlyingPrice(VToken(vTokenCollateral));\\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 uint256 exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint256 seizeTokens;\\n Exp memory numerator;\\n Exp memory denominator;\\n Exp memory ratio;\\n\\n numerator = mul_(Exp({ mantissa: liquidationIncentiveMantissa }), Exp({ mantissa: priceBorrowedMantissa }));\\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\\n ratio = div_(numerator, denominator);\\n\\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\\n\\n return (NO_ERROR, seizeTokens);\\n }\\n\\n /**\\n * @notice Returns reward speed given a vToken\\n * @param vToken The vToken to get the reward speeds for\\n * @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors\\n */\\n function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {\\n uint256 rewardsDistributorsLength = rewardsDistributors.length;\\n rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);\\n for (uint256 i; i < rewardsDistributorsLength; ++i) {\\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\\n address rewardToken = address(rewardsDistributor.rewardToken());\\n rewardSpeeds[i] = RewardSpeeds({\\n rewardToken: rewardToken,\\n supplySpeed: rewardsDistributor.rewardTokenSupplySpeeds(vToken),\\n borrowSpeed: rewardsDistributor.rewardTokenBorrowSpeeds(vToken)\\n });\\n }\\n return rewardSpeeds;\\n }\\n\\n /**\\n * @notice Return all reward distributors for this pool\\n * @return Array of RewardDistributor addresses\\n */\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory) {\\n return rewardsDistributors;\\n }\\n\\n /**\\n * @notice A marker method that returns true for a valid Comptroller contract\\n * @return Always true\\n */\\n function isComptroller() external pure override returns (bool) {\\n return true;\\n }\\n\\n /**\\n * @notice Update the prices of all the tokens associated with the provided account\\n * @param account Address of the account to get associated tokens with\\n */\\n function updatePrices(address account) public {\\n VToken[] memory vTokens = getAssetsIn(account);\\n uint256 vTokensCount = vTokens.length;\\n\\n ResilientOracleInterface oracle_ = oracle;\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n oracle_.updatePrice(address(vTokens[i]));\\n }\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param market vToken address\\n * @param action Action to check\\n * @return paused True if the action is paused otherwise false\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][action];\\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 list with the assets the account has entered\\n */\\n function getAssetsIn(address account) public 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 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 */\\n function _addToMarket(VToken vToken, address borrower) internal {\\n _checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = markets[address(vToken)];\\n\\n if (!marketToJoin.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return;\\n }\\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\\n /**\\n * @notice Internal function to validate that a market hasn't already been added\\n * and if it hasn't adds it\\n * @param vToken The market to support\\n */\\n function _addMarket(address vToken) internal {\\n uint256 marketsCount = allMarkets.length;\\n\\n for (uint256 i; i < marketsCount; ++i) {\\n if (allMarkets[i] == VToken(vToken)) {\\n revert MarketAlreadyListed(vToken);\\n }\\n }\\n allMarkets.push(VToken(vToken));\\n marketsCount = allMarkets.length;\\n _ensureMaxLoops(marketsCount);\\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 _setActionPaused(address market, Action action, bool paused) internal {\\n require(markets[market].isListed, \\\"cannot pause a market that is not listed\\\");\\n _actionPaused[market][action] = paused;\\n emit ActionPausedMarket(VToken(market), action, paused);\\n }\\n\\n /**\\n * @dev Internal function to check that vTokens can be safely redeemed for the underlying asset.\\n * @param vToken Address of the vTokens to redeem\\n * @param redeemer Account redeeming the tokens\\n * @param redeemTokens The number of tokens to redeem\\n */\\n function _checkRedeemAllowed(address vToken, address redeemer, uint256 redeemTokens) internal {\\n Market storage market = markets[vToken];\\n\\n if (!market.isListed) {\\n revert MarketNotListed(address(vToken));\\n }\\n\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!market.accountMembership[redeemer]) {\\n return;\\n }\\n\\n // Update the prices of tokens\\n updatePrices(redeemer);\\n\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n _getCollateralFactor\\n );\\n if (snapshot.shortfall > 0) {\\n revert InsufficientLiquidity();\\n }\\n }\\n\\n /**\\n * @notice Get the total collateral, weighted collateral, borrow balance, liquidity, shortfall\\n * @param account The account to get the snapshot for\\n * @param weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n * liquidation threshold. Accepts the address of the vToken and returns the weight as Exp.\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getCurrentLiquiditySnapshot(\\n address account,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n return _getHypotheticalLiquiditySnapshot(account, VToken(address(0)), 0, 0, weight);\\n }\\n\\n /**\\n * @notice Determine what the supply/borrow balances 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 weight The function to compute the weight of the collateral \\u2013\\u00a0either collateral factor or\\n liquidation threshold. Accepts the address of the VToken and returns the weight\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return snapshot Account liquidity snapshot\\n */\\n function _getHypotheticalLiquiditySnapshot(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n function(VToken) internal view returns (Exp memory) weight\\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\\n // For each asset the account is in\\n VToken[] memory assets = getAssetsIn(account);\\n uint256 assetsCount = assets.length;\\n\\n for (uint256 i; i < assetsCount; ++i) {\\n VToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the vToken\\n (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) = _safeGetAccountSnapshot(\\n asset,\\n account\\n );\\n\\n // Get the normalized price of the asset\\n Exp memory oraclePrice = Exp({ mantissa: _safeGetUnderlyingPrice(asset) });\\n\\n // Pre-compute conversion factors from vTokens -> usd\\n Exp memory vTokenPrice = mul_(Exp({ mantissa: exchangeRateMantissa }), oraclePrice);\\n Exp memory weightedVTokenPrice = mul_(weight(asset), vTokenPrice);\\n\\n // weightedCollateral += weightedVTokenPrice * vTokenBalance\\n snapshot.weightedCollateral = mul_ScalarTruncateAddUInt(\\n weightedVTokenPrice,\\n vTokenBalance,\\n snapshot.weightedCollateral\\n );\\n\\n // totalCollateral += vTokenPrice * vTokenBalance\\n snapshot.totalCollateral = mul_ScalarTruncateAddUInt(vTokenPrice, vTokenBalance, snapshot.totalCollateral);\\n\\n // borrows += oraclePrice * borrowBalance\\n snapshot.borrows = mul_ScalarTruncateAddUInt(oraclePrice, borrowBalance, snapshot.borrows);\\n\\n // Calculate effects of interacting with vTokenModify\\n if (asset == vTokenModify) {\\n // redeem effect\\n // effects += tokensToDenom * redeemTokens\\n snapshot.effects = mul_ScalarTruncateAddUInt(weightedVTokenPrice, redeemTokens, snapshot.effects);\\n\\n // borrow effect\\n // effects += oraclePrice * borrowAmount\\n snapshot.effects = mul_ScalarTruncateAddUInt(oraclePrice, borrowAmount, snapshot.effects);\\n }\\n }\\n\\n uint256 borrowPlusEffects = snapshot.borrows + snapshot.effects;\\n // These are safe, as the underflow condition is checked first\\n unchecked {\\n if (snapshot.weightedCollateral > borrowPlusEffects) {\\n snapshot.liquidity = snapshot.weightedCollateral - borrowPlusEffects;\\n snapshot.shortfall = 0;\\n } else {\\n snapshot.liquidity = 0;\\n snapshot.shortfall = borrowPlusEffects - snapshot.weightedCollateral;\\n }\\n }\\n\\n return snapshot;\\n }\\n\\n /**\\n * @dev Retrieves price from oracle for an asset and checks it is nonzero\\n * @param asset Address for asset to query price\\n * @return Underlying price\\n */\\n function _safeGetUnderlyingPrice(VToken asset) internal view returns (uint256) {\\n uint256 oraclePriceMantissa = oracle.getUnderlyingPrice(address(asset));\\n if (oraclePriceMantissa == 0) {\\n revert PriceError(address(asset));\\n }\\n return oraclePriceMantissa;\\n }\\n\\n /**\\n * @dev Return collateral factor for a market\\n * @param asset Address for asset\\n * @return Collateral factor as exponential\\n */\\n function _getCollateralFactor(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].collateralFactorMantissa });\\n }\\n\\n /**\\n * @dev Retrieves liquidation threshold for a market as an exponential\\n * @param asset Address for asset to liquidation threshold\\n * @return Liquidation threshold as exponential\\n */\\n function _getLiquidationThreshold(VToken asset) internal view returns (Exp memory) {\\n return Exp({ mantissa: markets[address(asset)].liquidationThresholdMantissa });\\n }\\n\\n /**\\n * @dev Returns supply and borrow balances of user in vToken, reverts on failure\\n * @param vToken Market to query\\n * @param user Account address\\n * @return vTokenBalance Balance of vTokens, the same as vToken.balanceOf(user)\\n * @return borrowBalance Borrowed amount, including the interest\\n * @return exchangeRateMantissa Stored exchange rate\\n */\\n function _safeGetAccountSnapshot(\\n VToken vToken,\\n address user\\n ) internal view returns (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) {\\n uint256 err;\\n (err, vTokenBalance, borrowBalance, exchangeRateMantissa) = vToken.getAccountSnapshot(user);\\n if (err != 0) {\\n revert SnapshotError(address(vToken), user);\\n }\\n return (vTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /// @notice Reverts if the call is not from expectedSender\\n /// @param expectedSender Expected transaction sender\\n function _checkSenderIs(address expectedSender) internal view {\\n if (msg.sender != expectedSender) {\\n revert UnexpectedSender(expectedSender, msg.sender);\\n }\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n /// @param market Market to check\\n /// @param action Action to check\\n function _checkActionPauseState(address market, Action action) private view {\\n if (actionPaused(market, action)) {\\n revert ActionPaused(market, action);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7c6e1c6264e4681f82a9ac1bcd9155197a930033291ee5561ad97a56006f5e9c\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.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\\n/**\\n * @title ComptrollerInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract.\\n */\\ninterface ComptrollerInterface {\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\\n\\n function exitMarket(address vToken) external returns (uint256);\\n\\n /*** Policy Hooks ***/\\n\\n function preMintHook(address vToken, address minter, uint256 mintAmount) external;\\n\\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external;\\n\\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external;\\n\\n function preRepayHook(address vToken, address borrower) external;\\n\\n function preLiquidateHook(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address borrower,\\n uint256 repayAmount,\\n bool skipLiquidityCheck\\n ) external;\\n\\n function preSeizeHook(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower\\n ) external;\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\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 seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external;\\n\\n function isComptroller() external view returns (bool);\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 repayAmount\\n ) external view returns (uint256, uint256);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n}\\n\\n/**\\n * @title ComptrollerViewInterface\\n * @author Venus\\n * @notice Interface implemented by the `Comptroller` contract, including only some util view functions.\\n */\\ninterface ComptrollerViewInterface {\\n function markets(address) external view returns (bool, uint256);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function closeFactorMantissa() external view returns (uint256);\\n\\n function liquidationIncentiveMantissa() external view returns (uint256);\\n\\n function minLiquidatableCollateral() external view returns (uint256);\\n\\n function getRewardDistributors() external view returns (RewardsDistributor[] memory);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function borrowCaps(address) external view returns (uint256);\\n\\n function supplyCaps(address) external view returns (uint256);\\n\\n function approvedDelegates(address user, address delegate) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xcbf7f9977472650c61345b7cbde23e81f626e1f8863bab4c6ce3dacfc7604919\",\"license\":\"BSD-3-Clause\"},\"contracts/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"./VToken.sol\\\";\\nimport { RewardsDistributor } from \\\"./Rewards/RewardsDistributor.sol\\\";\\nimport { IPrime } from \\\"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\\\";\\nimport { Action } from \\\"./ComptrollerInterface.sol\\\";\\n\\n/**\\n * @title ComptrollerStorage\\n * @author Venus\\n * @notice Storage layout for the `Comptroller` contract.\\n */\\ncontract ComptrollerStorage {\\n struct LiquidationOrder {\\n VToken vTokenCollateral;\\n VToken vTokenBorrowed;\\n uint256 repayAmount;\\n }\\n\\n struct AccountLiquiditySnapshot {\\n uint256 totalCollateral;\\n uint256 weightedCollateral;\\n uint256 borrows;\\n uint256 effects;\\n uint256 liquidity;\\n uint256 shortfall;\\n }\\n\\n struct RewardSpeeds {\\n address rewardToken;\\n uint256 supplySpeed;\\n uint256 borrowSpeed;\\n }\\n\\n struct Market {\\n // Whether or not this market is listed\\n bool isListed;\\n // 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 uint256 collateralFactorMantissa;\\n // 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 uint256 liquidationThresholdMantissa;\\n // Per-market mapping of \\\"accounts in this asset\\\"\\n mapping(address => bool) accountMembership;\\n }\\n\\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 Per-account mapping of \\\"assets you are in\\\"\\n */\\n mapping(address => VToken[]) public accountAssets;\\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 /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\\n mapping(address => uint256) public borrowCaps;\\n\\n /// @notice Minimal collateral required for regular (non-batch) liquidations\\n uint256 public minLiquidatableCollateral;\\n\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\\n mapping(address => uint256) public supplyCaps;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(Action => bool)) internal _actionPaused;\\n\\n // List of Reward Distributors added\\n RewardsDistributor[] internal rewardsDistributors;\\n\\n // Used to check if rewards distributor is added\\n mapping(address => bool) internal rewardsDistributorExists;\\n\\n /// @notice Flag indicating whether forced liquidation enabled for a market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n\\n uint256 internal constant NO_ERROR = 0;\\n\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant MIN_CLOSE_FACTOR_MANTISSA = 0.05e18; // 0.05\\n\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant MAX_CLOSE_FACTOR_MANTISSA = 0.9e18; // 0.9\\n\\n // No collateralFactorMantissa may exceed this value\\n uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.95e18; // 0.95\\n\\n /// Prime token address\\n IPrime public prime;\\n\\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 /**\\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[47] private __gap;\\n}\\n\",\"keccak256\":\"0x4df44cb65ac152bac2be4b4545430e703005a74a55b72e144100b16421bd8bfd\",\"license\":\"BSD-3-Clause\"},\"contracts/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title TokenErrorReporter\\n * @author Venus\\n * @notice Errors that can be thrown by the `VToken` contract.\\n */\\ncontract TokenErrorReporter {\\n uint256 public constant NO_ERROR = 0; // support legacy return codes\\n\\n error TransferNotAllowed();\\n\\n error MintFreshnessCheck();\\n\\n error RedeemFreshnessCheck();\\n error RedeemTransferOutNotPossible();\\n\\n error BorrowFreshnessCheck();\\n error BorrowCashNotAvailable();\\n error DelegateNotApproved();\\n\\n error RepayBorrowFreshnessCheck();\\n\\n error HealBorrowUnauthorized();\\n error ForceLiquidateBorrowUnauthorized();\\n\\n error LiquidateFreshnessCheck();\\n error LiquidateCollateralFreshnessCheck();\\n error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\\n error LiquidateLiquidatorIsBorrower();\\n error LiquidateCloseAmountIsZero();\\n error LiquidateCloseAmountIsUintMax();\\n\\n error LiquidateSeizeLiquidatorIsBorrower();\\n\\n error ProtocolSeizeShareTooBig();\\n\\n error SetReserveFactorFreshCheck();\\n error SetReserveFactorBoundsCheck();\\n\\n error AddReservesFactorFreshCheck(uint256 actualAddAmount);\\n\\n error ReduceReservesFreshCheck();\\n error ReduceReservesCashNotAvailable();\\n error ReduceReservesCashValidation();\\n\\n error SetInterestRateModelFreshCheck();\\n}\\n\",\"keccak256\":\"0x7a7ced1caaac2d9242659ebd50b99f308c725ce958ac9e11f7ada404b1d97a7b\",\"license\":\"BSD-3-Clause\"},\"contracts/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from \\\"./lib/constants.sol\\\";\\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 struct Exp {\\n uint256 mantissa;\\n }\\n\\n struct Double {\\n uint256 mantissa;\\n }\\n\\n uint256 internal constant EXP_SCALE = EXP_SCALE_;\\n uint256 internal constant DOUBLE_SCALE = 1e36;\\n uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;\\n uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint256) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / EXP_SCALE;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\\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 // solhint-disable-next-line func-name-mixedcase\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint256 scalar, uint256 addend) internal pure returns (uint256) {\\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 function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\\n require(n <= type(uint224).max, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\\n require(n <= type(uint32).max, 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_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a + b;\\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_(uint256 a, uint256 b) internal pure returns (uint256) {\\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) / EXP_SCALE });\\n }\\n\\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / EXP_SCALE;\\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) / DOUBLE_SCALE });\\n }\\n\\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return mul_(a, b.mantissa) / DOUBLE_SCALE;\\n }\\n\\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a * b;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\\n return div_(mul_(a, EXP_SCALE), 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, DOUBLE_SCALE), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\\n return div_(mul_(a, DOUBLE_SCALE), b.mantissa);\\n }\\n\\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a / b;\\n }\\n\\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });\\n }\\n}\\n\",\"keccak256\":\"0x8afbe8a24fe3539c124e718681ed3dcebd24c40dd53095786c0155998213b9b0\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModel.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Compound's InterestRateModel Interface\\n * @author Compound\\n */\\nabstract contract InterestRateModel {\\n /**\\n * @notice Calculates the current borrow interest rate per slot (block or second)\\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 amount of reserves the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The borrow rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\\n */\\n function getBorrowRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per slot (block or second)\\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 amount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @param badDebt The amount of badDebt in the market\\n * @return The supply rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa,\\n uint256 badDebt\\n ) external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\\n * @return Always true\\n */\\n function isInterestRateModel() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xc4fda1ab75ebe4b187b707c4f10c58780f343cf343c537f641dc75d3cd28ab51\",\"license\":\"BSD-3-Clause\"},\"contracts/Lens/PoolLens.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { IERC20Metadata } from \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Action, ComptrollerInterface, ComptrollerViewInterface } from \\\"../ComptrollerInterface.sol\\\";\\nimport { PoolRegistryInterface } from \\\"../Pool/PoolRegistryInterface.sol\\\";\\nimport { PoolRegistry } from \\\"../Pool/PoolRegistry.sol\\\";\\nimport { RewardsDistributor } from \\\"../Rewards/RewardsDistributor.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\n\\n/**\\n * @title PoolLens\\n * @author Venus\\n * @notice The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information\\n * for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be\\n * looked up for specific pools and markets:\\n- the vToken balance of a given user;\\n- the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address;\\n- the vToken address in a pool for a given asset;\\n- a list of all pools that support an asset;\\n- the underlying asset price of a vToken;\\n- the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\\n */\\ncontract PoolLens is ExponentialNoError, TimeManagerV8 {\\n /**\\n * @dev Struct for PoolDetails.\\n */\\n struct PoolData {\\n string name;\\n address creator;\\n address comptroller;\\n uint256 blockPosted;\\n uint256 timestampPosted;\\n string category;\\n string logoURL;\\n string description;\\n address priceOracle;\\n uint256 closeFactor;\\n uint256 liquidationIncentive;\\n uint256 minLiquidatableCollateral;\\n VTokenMetadata[] vTokens;\\n }\\n\\n /**\\n * @dev Struct for VToken.\\n */\\n struct VTokenMetadata {\\n address vToken;\\n uint256 exchangeRateCurrent;\\n uint256 supplyRatePerBlockOrTimestamp;\\n uint256 borrowRatePerBlockOrTimestamp;\\n uint256 reserveFactorMantissa;\\n uint256 supplyCaps;\\n uint256 borrowCaps;\\n uint256 totalBorrows;\\n uint256 totalReserves;\\n uint256 totalSupply;\\n uint256 totalCash;\\n bool isListed;\\n uint256 collateralFactorMantissa;\\n address underlyingAssetAddress;\\n uint256 vTokenDecimals;\\n uint256 underlyingDecimals;\\n uint256 pausedActions;\\n }\\n\\n /**\\n * @dev Struct for VTokenBalance.\\n */\\n struct VTokenBalances {\\n address vToken;\\n uint256 balanceOf;\\n uint256 borrowBalanceCurrent;\\n uint256 balanceOfUnderlying;\\n uint256 tokenBalance;\\n uint256 tokenAllowance;\\n }\\n\\n /**\\n * @dev Struct for underlyingPrice of VToken.\\n */\\n struct VTokenUnderlyingPrice {\\n address vToken;\\n uint256 underlyingPrice;\\n }\\n\\n /**\\n * @dev Struct with pending reward info for a market.\\n */\\n struct PendingReward {\\n address vTokenAddress;\\n uint256 amount;\\n }\\n\\n /**\\n * @dev Struct with reward distribution totals for a single reward token and distributor.\\n */\\n struct RewardSummary {\\n address distributorAddress;\\n address rewardTokenAddress;\\n uint256 totalRewards;\\n PendingReward[] pendingRewards;\\n }\\n\\n /**\\n * @dev Struct used in RewardDistributor to save last updated market state.\\n */\\n struct RewardTokenState {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number or timestamp the index was last updated at\\n uint256 blockOrTimestamp;\\n // The block number or timestamp at which to stop rewards\\n uint256 lastRewardingBlockOrTimestamp;\\n }\\n\\n /**\\n * @dev Struct with bad debt of a market denominated\\n */\\n struct BadDebt {\\n address vTokenAddress;\\n uint256 badDebtUsd;\\n }\\n\\n /**\\n * @dev Struct with bad debt total denominated in usd for a pool and an array of BadDebt structs for each market\\n */\\n struct BadDebtSummary {\\n address comptroller;\\n uint256 totalBadDebtUsd;\\n BadDebt[] badDebts;\\n }\\n\\n /// @notice Address of the core pool comptroller (all markets are returned for this pool, including paused ones)\\n address public immutable corePoolComptroller;\\n\\n /**\\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @param corePoolComptroller_ The address of the core pool comptroller\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(\\n bool timeBased_,\\n uint256 blocksPerYear_,\\n address corePoolComptroller_\\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\\n corePoolComptroller = corePoolComptroller_;\\n }\\n\\n /**\\n * @notice Queries the user's supply/borrow balances in vTokens\\n * @param vTokens The list of vToken addresses\\n * @param account The user Account\\n * @return A list of structs containing balances data\\n */\\n function vTokenBalancesAll(VToken[] calldata vTokens, address account) external returns (VTokenBalances[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenBalances[] memory res = new VTokenBalances[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenBalances(vTokens[i], account);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Queries all pools with addtional details for each of them\\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @return Arrays of all Venus pools' data\\n */\\n function getAllPools(address poolRegistryAddress) external view returns (PoolData[] memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n PoolRegistry.VenusPool[] memory venusPools = poolRegistryInterface.getAllPools();\\n uint256 poolLength = venusPools.length;\\n\\n PoolData[] memory poolDataItems = new PoolData[](poolLength);\\n\\n for (uint256 i; i < poolLength; ++i) {\\n PoolRegistry.VenusPool memory venusPool = venusPools[i];\\n PoolData memory poolData = getPoolDataFromVenusPool(poolRegistryAddress, venusPool);\\n poolDataItems[i] = poolData;\\n }\\n\\n return poolDataItems;\\n }\\n\\n /**\\n * @notice Queries the details of a pool identified by Comptroller address\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param comptroller The Comptroller implementation address\\n * @return PoolData structure containing the details of the pool\\n */\\n function getPoolByComptroller(\\n address poolRegistryAddress,\\n address comptroller\\n ) external view returns (PoolData memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return getPoolDataFromVenusPool(poolRegistryAddress, poolRegistryInterface.getPoolByComptroller(comptroller));\\n }\\n\\n /**\\n * @notice Returns vToken holding the specified underlying asset in the specified pool\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param comptroller The pool comptroller\\n * @param asset The underlyingAsset of VToken\\n * @return Address of the vToken\\n */\\n function getVTokenForAsset(\\n address poolRegistryAddress,\\n address comptroller,\\n address asset\\n ) external view returns (address) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return poolRegistryInterface.getVTokenForAsset(comptroller, asset);\\n }\\n\\n /**\\n * @notice Returns all pools that support the specified underlying asset\\n * @param poolRegistryAddress The address of the PoolRegistry contract\\n * @param asset The underlying asset of vToken\\n * @return A list of Comptroller contracts\\n */\\n function getPoolsSupportedByAsset(\\n address poolRegistryAddress,\\n address asset\\n ) external view returns (address[] memory) {\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n return poolRegistryInterface.getPoolsSupportedByAsset(asset);\\n }\\n\\n /**\\n * @notice Returns the price data for the underlying assets of the specified vTokens\\n * @param vTokens The list of vToken addresses\\n * @return An array containing the price data for each asset\\n */\\n function vTokenUnderlyingPriceAll(\\n VToken[] calldata vTokens\\n ) external view returns (VTokenUnderlyingPrice[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenUnderlyingPrice[] memory res = new VTokenUnderlyingPrice[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenUnderlyingPrice(vTokens[i]);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Returns the pending rewards for a user for a given pool.\\n * @param account The user account.\\n * @param comptrollerAddress address\\n * @return Pending rewards array\\n */\\n function getPendingRewards(\\n address account,\\n address comptrollerAddress\\n ) external view returns (RewardSummary[] memory) {\\n VToken[] memory markets = _getMarkets(ComptrollerInterface(comptrollerAddress));\\n RewardsDistributor[] memory rewardsDistributors = ComptrollerViewInterface(comptrollerAddress)\\n .getRewardDistributors();\\n RewardSummary[] memory rewardSummary = new RewardSummary[](rewardsDistributors.length);\\n for (uint256 i; i < rewardsDistributors.length; ++i) {\\n RewardSummary memory reward;\\n reward.distributorAddress = address(rewardsDistributors[i]);\\n reward.rewardTokenAddress = address(rewardsDistributors[i].rewardToken());\\n reward.totalRewards = rewardsDistributors[i].rewardTokenAccrued(account);\\n reward.pendingRewards = _calculateNotDistributedAwards(account, markets, rewardsDistributors[i]);\\n rewardSummary[i] = reward;\\n }\\n return rewardSummary;\\n }\\n\\n /**\\n * @notice Returns a summary of a pool's bad debt broken down by market\\n *\\n * @param comptrollerAddress Address of the comptroller\\n *\\n * @return badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and\\n * a break down of bad debt by market\\n */\\n function getPoolBadDebt(address comptrollerAddress) external view returns (BadDebtSummary memory) {\\n uint256 totalBadDebtUsd;\\n\\n // Get every listed market in the pool\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\\n VToken[] memory markets = _getMarkets(ComptrollerInterface(comptrollerAddress));\\n ResilientOracleInterface priceOracle = comptroller.oracle();\\n\\n BadDebt[] memory badDebts = new BadDebt[](markets.length);\\n\\n BadDebtSummary memory badDebtSummary;\\n badDebtSummary.comptroller = comptrollerAddress;\\n badDebtSummary.badDebts = badDebts;\\n\\n // // Calculate the bad debt is USD per market\\n for (uint256 i; i < markets.length; ++i) {\\n BadDebt memory badDebt;\\n badDebt.vTokenAddress = address(markets[i]);\\n badDebt.badDebtUsd =\\n (VToken(address(markets[i])).badDebt() * priceOracle.getUnderlyingPrice(address(markets[i]))) /\\n EXP_SCALE;\\n badDebtSummary.badDebts[i] = badDebt;\\n totalBadDebtUsd = totalBadDebtUsd + badDebt.badDebtUsd;\\n }\\n\\n badDebtSummary.totalBadDebtUsd = totalBadDebtUsd;\\n\\n return badDebtSummary;\\n }\\n\\n /**\\n * @notice Queries the user's supply/borrow balances in the specified vToken\\n * @param vToken vToken address\\n * @param account The user Account\\n * @return A struct containing the balances data\\n */\\n function vTokenBalances(VToken vToken, address account) public returns (VTokenBalances memory) {\\n uint256 balanceOf = vToken.balanceOf(account);\\n uint256 borrowBalanceCurrent = vToken.borrowBalanceCurrent(account);\\n uint256 balanceOfUnderlying = vToken.balanceOfUnderlying(account);\\n uint256 tokenBalance;\\n uint256 tokenAllowance;\\n\\n IERC20 underlying = IERC20(vToken.underlying());\\n tokenBalance = underlying.balanceOf(account);\\n tokenAllowance = underlying.allowance(account, address(vToken));\\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 Queries additional information for the pool\\n * @param poolRegistryAddress Address of the PoolRegistry\\n * @param venusPool The VenusPool Object from PoolRegistry\\n * @return Enriched PoolData\\n */\\n function getPoolDataFromVenusPool(\\n address poolRegistryAddress,\\n PoolRegistry.VenusPool memory venusPool\\n ) public view returns (PoolData memory) {\\n // Get tokens in the Pool\\n ComptrollerInterface comptrollerInstance = ComptrollerInterface(venusPool.comptroller);\\n\\n VToken[] memory vTokens = _getMarkets(comptrollerInstance);\\n\\n VTokenMetadata[] memory vTokenMetadataItems = vTokenMetadataAll(vTokens);\\n\\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\\n\\n PoolRegistry.VenusPoolMetaData memory venusPoolMetaData = poolRegistryInterface.getVenusPoolMetadata(\\n venusPool.comptroller\\n );\\n\\n ComptrollerViewInterface comptrollerViewInstance = ComptrollerViewInterface(venusPool.comptroller);\\n\\n PoolData memory poolData = PoolData({\\n name: venusPool.name,\\n creator: venusPool.creator,\\n comptroller: venusPool.comptroller,\\n blockPosted: venusPool.blockPosted,\\n timestampPosted: venusPool.timestampPosted,\\n category: venusPoolMetaData.category,\\n logoURL: venusPoolMetaData.logoURL,\\n description: venusPoolMetaData.description,\\n vTokens: vTokenMetadataItems,\\n priceOracle: address(comptrollerViewInstance.oracle()),\\n closeFactor: comptrollerViewInstance.closeFactorMantissa(),\\n liquidationIncentive: comptrollerViewInstance.liquidationIncentiveMantissa(),\\n minLiquidatableCollateral: comptrollerViewInstance.minLiquidatableCollateral()\\n });\\n\\n return poolData;\\n }\\n\\n /**\\n * @notice Returns the metadata of VToken\\n * @param vToken The address of vToken\\n * @return VTokenMetadata struct\\n */\\n function vTokenMetadata(VToken vToken) public view returns (VTokenMetadata memory) {\\n uint256 exchangeRateCurrent = vToken.exchangeRateStored();\\n address comptrollerAddress = address(vToken.comptroller());\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\\n (bool isListed, uint256 collateralFactorMantissa) = comptroller.markets(address(vToken));\\n\\n address underlyingAssetAddress = vToken.underlying();\\n uint256 underlyingDecimals = IERC20Metadata(underlyingAssetAddress).decimals();\\n\\n uint256 pausedActions;\\n for (uint8 i; i <= uint8(type(Action).max); ++i) {\\n uint256 paused = ComptrollerInterface(comptrollerAddress).actionPaused(address(vToken), Action(i)) ? 1 : 0;\\n pausedActions |= paused << i;\\n }\\n\\n uint256 supplyRatePerBlock;\\n\\n if (vToken.totalSupply() > 0) {\\n supplyRatePerBlock = vToken.supplyRatePerBlock();\\n }\\n\\n return\\n VTokenMetadata({\\n vToken: address(vToken),\\n exchangeRateCurrent: exchangeRateCurrent,\\n supplyRatePerBlockOrTimestamp: supplyRatePerBlock,\\n borrowRatePerBlockOrTimestamp: vToken.borrowRatePerBlock(),\\n reserveFactorMantissa: vToken.reserveFactorMantissa(),\\n supplyCaps: comptroller.supplyCaps(address(vToken)),\\n borrowCaps: comptroller.borrowCaps(address(vToken)),\\n totalBorrows: vToken.totalBorrows(),\\n totalReserves: vToken.totalReserves(),\\n totalSupply: vToken.totalSupply(),\\n totalCash: vToken.getCash(),\\n isListed: isListed,\\n collateralFactorMantissa: collateralFactorMantissa,\\n underlyingAssetAddress: underlyingAssetAddress,\\n vTokenDecimals: vToken.decimals(),\\n underlyingDecimals: underlyingDecimals,\\n pausedActions: pausedActions\\n });\\n }\\n\\n /**\\n * @notice Returns the metadata of all VTokens\\n * @param vTokens The list of vToken addresses\\n * @return An array of VTokenMetadata structs\\n */\\n function vTokenMetadataAll(VToken[] memory vTokens) public view returns (VTokenMetadata[] memory) {\\n uint256 vTokenCount = vTokens.length;\\n VTokenMetadata[] memory res = new VTokenMetadata[](vTokenCount);\\n for (uint256 i; i < vTokenCount; ++i) {\\n res[i] = vTokenMetadata(vTokens[i]);\\n }\\n return res;\\n }\\n\\n /**\\n * @notice Returns the price data for the underlying asset of the specified vToken\\n * @param vToken vToken address\\n * @return The price data for each asset\\n */\\n function vTokenUnderlyingPrice(VToken vToken) public view returns (VTokenUnderlyingPrice memory) {\\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(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 Returns markets from a comptroller. For the core pool, all markets are returned.\\n * For other pools, markets with zero internalCash are filtered.\\n * @param comptroller The comptroller to query\\n * @return An array of VToken addresses\\n */\\n function _getMarkets(ComptrollerInterface comptroller) internal view returns (VToken[] memory) {\\n VToken[] memory allMarkets = comptroller.getAllMarkets();\\n\\n if (address(comptroller) == corePoolComptroller) {\\n return allMarkets;\\n }\\n\\n // Single-loop filter: pack active markets to the front of allMarkets\\n uint256 count;\\n uint256 len = allMarkets.length;\\n for (uint256 i; i < len; ++i) {\\n if (allMarkets[i].internalCash() > 0) {\\n allMarkets[count] = allMarkets[i];\\n ++count;\\n }\\n }\\n\\n // Trim the array to the active count\\n assembly {\\n mstore(allMarkets, count)\\n }\\n\\n return allMarkets;\\n }\\n\\n function _calculateNotDistributedAwards(\\n address account,\\n VToken[] memory markets,\\n RewardsDistributor rewardsDistributor\\n ) internal view returns (PendingReward[] memory) {\\n PendingReward[] memory pendingRewards = new PendingReward[](markets.length);\\n\\n for (uint256 i; i < markets.length; ++i) {\\n // Market borrow and supply state we will modify update in-memory, in order to not modify storage\\n RewardTokenState memory borrowState;\\n RewardTokenState memory supplyState;\\n\\n if (isTimeBased) {\\n (\\n borrowState.index,\\n borrowState.blockOrTimestamp,\\n borrowState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenBorrowStateTimeBased(address(markets[i]));\\n (\\n supplyState.index,\\n supplyState.blockOrTimestamp,\\n supplyState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenSupplyStateTimeBased(address(markets[i]));\\n } else {\\n (\\n borrowState.index,\\n borrowState.blockOrTimestamp,\\n borrowState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenBorrowState(address(markets[i]));\\n (\\n supplyState.index,\\n supplyState.blockOrTimestamp,\\n supplyState.lastRewardingBlockOrTimestamp\\n ) = rewardsDistributor.rewardTokenSupplyState(address(markets[i]));\\n }\\n\\n Exp memory marketBorrowIndex = Exp({ mantissa: markets[i].borrowIndex() });\\n\\n // Update market supply and borrow index in-memory\\n updateMarketBorrowIndex(address(markets[i]), rewardsDistributor, borrowState, marketBorrowIndex);\\n updateMarketSupplyIndex(address(markets[i]), rewardsDistributor, supplyState);\\n\\n // Calculate pending rewards\\n uint256 borrowReward = calculateBorrowerReward(\\n address(markets[i]),\\n rewardsDistributor,\\n account,\\n borrowState,\\n marketBorrowIndex\\n );\\n uint256 supplyReward = calculateSupplierReward(\\n address(markets[i]),\\n rewardsDistributor,\\n account,\\n supplyState\\n );\\n\\n PendingReward memory pendingReward;\\n pendingReward.vTokenAddress = address(markets[i]);\\n pendingReward.amount = borrowReward + supplyReward;\\n pendingRewards[i] = pendingReward;\\n }\\n return pendingRewards;\\n }\\n\\n function updateMarketBorrowIndex(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n RewardTokenState memory borrowState,\\n Exp memory marketBorrowIndex\\n ) internal view {\\n uint256 borrowSpeed = rewardsDistributor.rewardTokenBorrowSpeeds(vToken);\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (\\n borrowState.lastRewardingBlockOrTimestamp > 0 &&\\n blockNumberOrTimestamp > borrowState.lastRewardingBlockOrTimestamp\\n ) {\\n blockNumberOrTimestamp = borrowState.lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, borrowState.blockOrTimestamp);\\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\\n // Remove the total earned interest rate since the opening of the market from total borrows\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, borrowSpeed);\\n Double memory ratio = borrowAmount > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\\n } else if (deltaBlocksOrTimestamp > 0) {\\n borrowState.blockOrTimestamp = blockNumberOrTimestamp;\\n }\\n }\\n\\n function updateMarketSupplyIndex(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n RewardTokenState memory supplyState\\n ) internal view {\\n uint256 supplySpeed = rewardsDistributor.rewardTokenSupplySpeeds(vToken);\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (\\n supplyState.lastRewardingBlockOrTimestamp > 0 &&\\n blockNumberOrTimestamp > supplyState.lastRewardingBlockOrTimestamp\\n ) {\\n blockNumberOrTimestamp = supplyState.lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, supplyState.blockOrTimestamp);\\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, supplySpeed);\\n Double memory ratio = supplyTokens > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\\n } else if (deltaBlocksOrTimestamp > 0) {\\n supplyState.blockOrTimestamp = blockNumberOrTimestamp;\\n }\\n }\\n\\n function calculateBorrowerReward(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n address borrower,\\n RewardTokenState memory borrowState,\\n Exp memory marketBorrowIndex\\n ) internal view returns (uint256) {\\n Double memory borrowIndex = Double({ mantissa: borrowState.index });\\n Double memory borrowerIndex = Double({\\n mantissa: rewardsDistributor.rewardTokenBorrowerIndex(vToken, borrower)\\n });\\n if (borrowerIndex.mantissa == 0 && borrowIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set\\n borrowerIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\\n }\\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n return borrowerDelta;\\n }\\n\\n function calculateSupplierReward(\\n address vToken,\\n RewardsDistributor rewardsDistributor,\\n address supplier,\\n RewardTokenState memory supplyState\\n ) internal view returns (uint256) {\\n Double memory supplyIndex = Double({ mantissa: supplyState.index });\\n Double memory supplierIndex = Double({\\n mantissa: rewardsDistributor.rewardTokenSupplierIndex(vToken, supplier)\\n });\\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\\n // Covers the case where users supplied tokens before the market's supply state index was set\\n supplierIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\\n }\\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n return supplierDelta;\\n }\\n}\\n\",\"keccak256\":\"0xfe3f00ebb7f0b5c98ee03cf1cfa1a013a56984cf6879373c70a74b3d9d0db399\",\"license\":\"BSD-3-Clause\"},\"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\",\"keccak256\":\"0x4c25e30635485d162177effa384eee51768b0141a567a0da16ff6ad673274166\",\"license\":\"BSD-3-Clause\"},\"contracts/Pool/PoolRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { Ownable2StepUpgradeable } from \\\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\\\";\\nimport { SafeERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\\\";\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\nimport { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\n\\nimport { PoolRegistryInterface } from \\\"./PoolRegistryInterface.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"../lib/validators.sol\\\";\\n\\n/**\\n * @title PoolRegistry\\n * @author Venus\\n * @notice The Isolated Pools architecture centers around the `PoolRegistry` contract. The `PoolRegistry` maintains a directory of isolated lending\\n * pools and can perform actions like creating and registering new pools, adding new markets to existing pools, setting and updating the pool's required\\n * metadata, and providing the getter methods to get information on the pools.\\n *\\n * Isolated lending has three main components: PoolRegistry, pools, and markets. The PoolRegistry is responsible for managing pools.\\n * It can create new pools, update pool metadata and manage markets within pools. PoolRegistry contains getter methods to get the details of\\n * any existing pool like `getVTokenForAsset` and `getPoolsSupportedByAsset`. It also contains methods for updating pool metadata (`updatePoolMetadata`)\\n * and setting pool name (`setPoolName`).\\n *\\n * The directory of pools is managed through two mappings: `_poolByComptroller` which is a hashmap with the comptroller address as the key and `VenusPool` as\\n * the value and `_poolsByID` which is an array of comptroller addresses. Individual pools can be accessed by calling `getPoolByComptroller` with the pool's\\n * comptroller address. `_poolsByID` is used to iterate through all of the pools.\\n *\\n * PoolRegistry also contains a map of asset addresses called `_supportedPools` that maps to an array of assets suppored by each pool. This array of pools by\\n * asset is retrieved by calling `getPoolsSupportedByAsset`.\\n *\\n * PoolRegistry registers new isolated pools in the directory with the `createRegistryPool` method. Isolated pools are composed of independent markets with\\n * specific assets and custom risk management configurations according to their markets.\\n */\\ncontract PoolRegistry is Ownable2StepUpgradeable, AccessControlledV8, PoolRegistryInterface {\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n struct AddMarketInput {\\n VToken vToken;\\n uint256 collateralFactor;\\n uint256 liquidationThreshold;\\n uint256 initialSupply;\\n address vTokenReceiver;\\n uint256 supplyCap;\\n uint256 borrowCap;\\n }\\n\\n uint256 internal constant MAX_POOL_NAME_LENGTH = 100;\\n\\n /**\\n * @notice Maps pool's comptroller address to metadata.\\n */\\n mapping(address => VenusPoolMetaData) public metadata;\\n\\n /**\\n * @dev Maps pool ID to pool's comptroller address\\n */\\n mapping(uint256 => address) private _poolsByID;\\n\\n /**\\n * @dev Total number of pools created.\\n */\\n uint256 private _numberOfPools;\\n\\n /**\\n * @dev Maps comptroller address to Venus pool Index.\\n */\\n mapping(address => VenusPool) private _poolByComptroller;\\n\\n /**\\n * @dev Maps pool's comptroller address to asset to vToken.\\n */\\n mapping(address => mapping(address => address)) private _vTokens;\\n\\n /**\\n * @dev Maps asset to list of supported pools.\\n */\\n mapping(address => address[]) private _supportedPools;\\n\\n /**\\n * @notice Emitted when a new Venus pool is added to the directory.\\n */\\n event PoolRegistered(address indexed comptroller, VenusPool pool);\\n\\n /**\\n * @notice Emitted when a pool name is set.\\n */\\n event PoolNameSet(address indexed comptroller, string oldName, string newName);\\n\\n /**\\n * @notice Emitted when a pool metadata is updated.\\n */\\n event PoolMetadataUpdated(\\n address indexed comptroller,\\n VenusPoolMetaData oldMetadata,\\n VenusPoolMetaData newMetadata\\n );\\n\\n /**\\n * @notice Emitted when a Market is added to the pool.\\n */\\n event MarketAdded(address indexed comptroller, address indexed vTokenAddress);\\n\\n /// @custom:oz-upgrades-unsafe-allow constructor\\n constructor() {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice Initializes the deployer to owner\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(address accessControlManager_) external initializer {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n }\\n\\n /**\\n * @notice Adds a new Venus pool to the directory\\n * @dev Price oracle must be configured before adding a pool\\n * @param name The name of the pool\\n * @param comptroller Pool's Comptroller contract\\n * @param closeFactor The pool's close factor (scaled by 1e18)\\n * @param liquidationIncentive The pool's liquidation incentive (scaled by 1e18)\\n * @param minLiquidatableCollateral Minimal collateral for regular (non-batch) liquidations flow\\n * @return index The index of the registered Venus pool\\n * @custom:error ZeroAddressNotAllowed is thrown when Comptroller address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\\n */\\n function addPool(\\n string calldata name,\\n Comptroller comptroller,\\n uint256 closeFactor,\\n uint256 liquidationIncentive,\\n uint256 minLiquidatableCollateral\\n ) external virtual returns (uint256 index) {\\n _checkAccessAllowed(\\\"addPool(string,address,uint256,uint256,uint256)\\\");\\n // Input validation\\n ensureNonzeroAddress(address(comptroller));\\n ensureNonzeroAddress(address(comptroller.oracle()));\\n\\n uint256 poolId = _registerPool(name, address(comptroller));\\n\\n // Set Venus pool parameters\\n comptroller.setCloseFactor(closeFactor);\\n comptroller.setLiquidationIncentive(liquidationIncentive);\\n comptroller.setMinLiquidatableCollateral(minLiquidatableCollateral);\\n\\n return poolId;\\n }\\n\\n /**\\n * @notice Add a market to an existing pool and then mint to provide initial supply\\n * @param input The structure describing the parameters for adding a market to a pool\\n * @custom:error ZeroAddressNotAllowed is thrown when vToken address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when vTokenReceiver address is zero\\n */\\n function addMarket(AddMarketInput memory input) external {\\n _checkAccessAllowed(\\\"addMarket(AddMarketInput)\\\");\\n ensureNonzeroAddress(address(input.vToken));\\n ensureNonzeroAddress(input.vTokenReceiver);\\n require(input.initialSupply > 0, \\\"PoolRegistry: initialSupply is zero\\\");\\n\\n VToken vToken = input.vToken;\\n address vTokenAddress = address(vToken);\\n address comptrollerAddress = address(vToken.comptroller());\\n Comptroller comptroller = Comptroller(comptrollerAddress);\\n address underlyingAddress = vToken.underlying();\\n IERC20Upgradeable underlying = IERC20Upgradeable(underlyingAddress);\\n\\n require(_poolByComptroller[comptrollerAddress].creator != address(0), \\\"PoolRegistry: Pool not registered\\\");\\n // solhint-disable-next-line reason-string\\n require(\\n _vTokens[comptrollerAddress][underlyingAddress] == address(0),\\n \\\"PoolRegistry: Market already added for asset comptroller combination\\\"\\n );\\n\\n comptroller.supportMarket(vToken);\\n comptroller.setCollateralFactor(vToken, input.collateralFactor, input.liquidationThreshold);\\n\\n uint256[] memory newSupplyCaps = new uint256[](1);\\n uint256[] memory newBorrowCaps = new uint256[](1);\\n VToken[] memory vTokens = new VToken[](1);\\n\\n newSupplyCaps[0] = input.supplyCap;\\n newBorrowCaps[0] = input.borrowCap;\\n vTokens[0] = vToken;\\n\\n comptroller.setMarketSupplyCaps(vTokens, newSupplyCaps);\\n comptroller.setMarketBorrowCaps(vTokens, newBorrowCaps);\\n\\n _vTokens[comptrollerAddress][underlyingAddress] = vTokenAddress;\\n _supportedPools[underlyingAddress].push(comptrollerAddress);\\n\\n uint256 amountToSupply = _transferIn(underlying, msg.sender, input.initialSupply);\\n underlying.forceApprove(vTokenAddress, 0);\\n underlying.forceApprove(vTokenAddress, amountToSupply);\\n vToken.mintBehalf(input.vTokenReceiver, amountToSupply);\\n\\n emit MarketAdded(comptrollerAddress, vTokenAddress);\\n }\\n\\n /**\\n * @notice Modify existing Venus pool name\\n * @param comptroller Pool's Comptroller\\n * @param name New pool name\\n */\\n function setPoolName(address comptroller, string calldata name) external {\\n _checkAccessAllowed(\\\"setPoolName(address,string)\\\");\\n _ensureValidName(name);\\n VenusPool storage pool = _poolByComptroller[comptroller];\\n string memory oldName = pool.name;\\n pool.name = name;\\n emit PoolNameSet(comptroller, oldName, name);\\n }\\n\\n /**\\n * @notice Update metadata of an existing pool\\n * @param comptroller Pool's Comptroller\\n * @param metadata_ New pool metadata\\n */\\n function updatePoolMetadata(address comptroller, VenusPoolMetaData calldata metadata_) external {\\n _checkAccessAllowed(\\\"updatePoolMetadata(address,VenusPoolMetaData)\\\");\\n VenusPoolMetaData memory oldMetadata = metadata[comptroller];\\n metadata[comptroller] = metadata_;\\n emit PoolMetadataUpdated(comptroller, oldMetadata, metadata_);\\n }\\n\\n /**\\n * @notice Returns arrays of all Venus pools' data\\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\\n * @return A list of all pools within PoolRegistry, with details for each pool\\n */\\n function getAllPools() external view override returns (VenusPool[] memory) {\\n uint256 numberOfPools_ = _numberOfPools; // storage load to save gas\\n VenusPool[] memory _pools = new VenusPool[](numberOfPools_);\\n for (uint256 i = 1; i <= numberOfPools_; ++i) {\\n address comptroller = _poolsByID[i];\\n _pools[i - 1] = (_poolByComptroller[comptroller]);\\n }\\n return _pools;\\n }\\n\\n /**\\n * @param comptroller The comptroller proxy address associated to the pool\\n * @return Returns Venus pool\\n */\\n function getPoolByComptroller(address comptroller) external view override returns (VenusPool memory) {\\n return _poolByComptroller[comptroller];\\n }\\n\\n /**\\n * @param comptroller comptroller of Venus pool\\n * @return Returns Metadata of Venus pool\\n */\\n function getVenusPoolMetadata(address comptroller) external view override returns (VenusPoolMetaData memory) {\\n return metadata[comptroller];\\n }\\n\\n function getVTokenForAsset(address comptroller, address asset) external view override returns (address) {\\n return _vTokens[comptroller][asset];\\n }\\n\\n function getPoolsSupportedByAsset(address asset) external view override returns (address[] memory) {\\n return _supportedPools[asset];\\n }\\n\\n /**\\n * @dev Adds a new Venus pool to the directory (without checking msg.sender).\\n * @param name The name of the pool\\n * @param comptroller The pool's Comptroller proxy contract address\\n * @return The index of the registered Venus pool\\n */\\n function _registerPool(string calldata name, address comptroller) internal returns (uint256) {\\n VenusPool storage storedPool = _poolByComptroller[comptroller];\\n\\n require(storedPool.creator == address(0), \\\"PoolRegistry: Pool already exists in the directory.\\\");\\n _ensureValidName(name);\\n\\n ++_numberOfPools;\\n uint256 numberOfPools_ = _numberOfPools; // cache on stack to save storage read gas\\n\\n VenusPool memory pool = VenusPool(name, msg.sender, comptroller, block.number, block.timestamp);\\n\\n _poolsByID[numberOfPools_] = comptroller;\\n _poolByComptroller[comptroller] = pool;\\n\\n emit PoolRegistered(comptroller, pool);\\n return numberOfPools_;\\n }\\n\\n function _transferIn(IERC20Upgradeable token, address from, uint256 amount) internal returns (uint256) {\\n uint256 balanceBefore = token.balanceOf(address(this));\\n token.safeTransferFrom(from, address(this), amount);\\n uint256 balanceAfter = token.balanceOf(address(this));\\n return balanceAfter - balanceBefore;\\n }\\n\\n function _ensureValidName(string calldata name) internal pure {\\n require(bytes(name).length <= MAX_POOL_NAME_LENGTH, \\\"Pool's name is too large\\\");\\n }\\n}\\n\",\"keccak256\":\"0xafbb871f7b4db3ef439d846baa5f18a136192f9b43ea695c81262a77b06c4b25\",\"license\":\"BSD-3-Clause\"},\"contracts/Pool/PoolRegistryInterface.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 /**\\n * @notice Struct for a Venus interest rate pool metadata.\\n */\\n struct VenusPoolMetaData {\\n string category;\\n string logoURL;\\n string description;\\n }\\n\\n /// @notice Get all pools in PoolRegistry\\n function getAllPools() external view returns (VenusPool[] memory);\\n\\n /// @notice Get a pool by comptroller address\\n function getPoolByComptroller(address comptroller) external view returns (VenusPool memory);\\n\\n /// @notice Get the address of the VToken contract in the Pool where the underlying token is the provided 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 /// @notice Get the metadata of a Pool by comptroller address\\n function getVenusPoolMetadata(address comptroller) external view returns (VenusPoolMetaData memory);\\n}\\n\",\"keccak256\":\"0x7b39cda3b372a686501ce3c2aad288c6af410148110318249d75d4516729c92c\",\"license\":\"BSD-3-Clause\"},\"contracts/Rewards/RewardsDistributor.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\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 { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\n\\nimport { ExponentialNoError } from \\\"../ExponentialNoError.sol\\\";\\nimport { VToken } from \\\"../VToken.sol\\\";\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\nimport { MaxLoopsLimitHelper } from \\\"../MaxLoopsLimitHelper.sol\\\";\\nimport { RewardsDistributorStorage } from \\\"./RewardsDistributorStorage.sol\\\";\\n\\n/**\\n * @title `RewardsDistributor`\\n * @author Venus\\n * @notice Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol.\\n * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward\\n * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool.\\n * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward\\n * token to be released each slot (block or second) for borrowers and suppliers, which is distributed based on a user\\u2019s percentage of the borrows or supplies\\n * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting\\n * their contributor reward token speed, which similarly allocates a fixed amount of reward token per slot (block or second).\\n *\\n * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed\\n * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized\\n * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\\n */\\ncontract RewardsDistributor is\\n ExponentialNoError,\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n MaxLoopsLimitHelper,\\n RewardsDistributorStorage,\\n TimeManagerV8\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n /// @notice The initial REWARD TOKEN index for a market\\n uint224 public constant INITIAL_INDEX = 1e36;\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a supplier\\n event DistributedSupplierRewardToken(\\n VToken indexed vToken,\\n address indexed supplier,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenSupplyIndex\\n );\\n\\n /// @notice Emitted when REWARD TOKEN is distributed to a borrower\\n event DistributedBorrowerRewardToken(\\n VToken indexed vToken,\\n address indexed borrower,\\n uint256 rewardTokenDelta,\\n uint256 rewardTokenTotal,\\n uint256 rewardTokenBorrowIndex\\n );\\n\\n /// @notice Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\\n event RewardTokenBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when REWARD TOKEN is granted by admin\\n event RewardTokenGranted(address indexed recipient, uint256 amount);\\n\\n /// @notice Emitted when a new REWARD TOKEN speed is set for a contributor\\n event ContributorRewardTokenSpeedUpdated(address indexed contributor, uint256 newSpeed);\\n\\n /// @notice Emitted when a market is initialized\\n event MarketInitialized(address indexed vToken);\\n\\n /// @notice Emitted when a reward token supply index is updated\\n event RewardTokenSupplyIndexUpdated(address indexed vToken);\\n\\n /// @notice Emitted when a reward token borrow index is updated\\n event RewardTokenBorrowIndexUpdated(address indexed vToken, Exp marketBorrowIndex);\\n\\n /// @notice Emitted when a reward for contributor is updated\\n event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued);\\n\\n /// @notice Emitted when a reward token last rewarding block for supply is updated\\n event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding block for borrow is updated\\n event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\\n\\n /// @notice Emitted when a reward token last rewarding timestamp for supply is updated\\n event SupplyLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\\n\\n /// @notice Emitted when a reward token last rewarding timestamp for borrow is updated\\n event BorrowLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\\n\\n modifier onlyComptroller() {\\n require(address(comptroller) == msg.sender, \\\"Only comptroller can call this function\\\");\\n _;\\n }\\n\\n /**\\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n _disableInitializers();\\n }\\n\\n /**\\n * @notice RewardsDistributor initializer\\n * @dev Initializes the deployer to owner\\n * @param comptroller_ Comptroller to attach the reward distributor to\\n * @param rewardToken_ Reward token to distribute\\n * @param loopsLimit_ Maximum number of iterations for the loops in this contract\\n * @param accessControlManager_ AccessControlManager contract address\\n */\\n function initialize(\\n Comptroller comptroller_,\\n IERC20Upgradeable rewardToken_,\\n uint256 loopsLimit_,\\n address accessControlManager_\\n ) external initializer {\\n comptroller = comptroller_;\\n rewardToken = rewardToken_;\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\n\\n _setMaxLoopsLimit(loopsLimit_);\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken\\n * @param vToken The address of the vToken to be initialized\\n * @custom:event MarketInitialized emits on success\\n * @custom:access Only Comptroller\\n */\\n function initializeMarket(address vToken) external onlyComptroller {\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n isTimeBased\\n ? _initializeMarketTimestampBased(vToken, blockNumberOrTimestamp)\\n : _initializeMarketBlockBased(vToken, safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\"));\\n\\n emit MarketInitialized(vToken);\\n }\\n\\n /*** Reward Token Distribution ***/\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them\\n * Borrowers will begin to accrue after the first interaction with the protocol.\\n * @dev This function should only be called when the user has a borrow position in the market\\n * (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook)\\n * We avoid an external call to check if they are in the market to save gas because this function is called in many places\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function distributeBorrowerRewardToken(\\n address vToken,\\n address borrower,\\n Exp memory marketBorrowIndex\\n ) external onlyComptroller {\\n _distributeBorrowerRewardToken(vToken, borrower, marketBorrowIndex);\\n }\\n\\n function updateRewardTokenSupplyIndex(address vToken) external onlyComptroller {\\n _updateRewardTokenSupplyIndex(vToken);\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the recipient\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\\n * @param recipient The address of the recipient to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n */\\n function grantRewardToken(address recipient, uint256 amount) external onlyOwner {\\n uint256 amountLeft = _grantRewardToken(recipient, amount);\\n require(amountLeft == 0, \\\"insufficient rewardToken for grant\\\");\\n emit RewardTokenGranted(recipient, amount);\\n }\\n\\n function updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) external onlyComptroller {\\n _updateRewardTokenBorrowIndex(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN borrow and supply speeds for the specified markets\\n * @param vTokens The markets whose REWARD TOKEN speed to update\\n * @param supplySpeeds New supply-side REWARD TOKEN speed for the corresponding market\\n * @param borrowSpeeds New borrow-side REWARD TOKEN speed for the corresponding market\\n */\\n function setRewardTokenSpeeds(\\n VToken[] memory vTokens,\\n uint256[] memory supplySpeeds,\\n uint256[] memory borrowSpeeds\\n ) external {\\n _checkAccessAllowed(\\\"setRewardTokenSpeeds(address[],uint256[],uint256[])\\\");\\n uint256 numTokens = vTokens.length;\\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \\\"invalid setRewardTokenSpeeds\\\");\\n\\n for (uint256 i; i < numTokens; ++i) {\\n _setRewardTokenSpeed(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for the specified markets, used when contract is block based\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market\\n * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market\\n */\\n function setLastRewardingBlocks(\\n VToken[] calldata vTokens,\\n uint32[] calldata supplyLastRewardingBlocks,\\n uint32[] calldata borrowLastRewardingBlocks\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlocks(address[],uint32[],uint32[])\\\");\\n require(!isTimeBased, \\\"Block-based operation only\\\");\\n\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length,\\n \\\"RewardsDistributor::setLastRewardingBlocks invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlock(vTokens[i], supplyLastRewardingBlocks[i], borrowLastRewardingBlocks[i]);\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block timestamp for the specified markets, used when contract is time based\\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\\n * @param supplyLastRewardingBlockTimestamps New supply-side REWARD TOKEN last rewarding block timestamp for the corresponding market\\n * @param borrowLastRewardingBlockTimestamps New borrow-side REWARD TOKEN last rewarding block timestamp for the corresponding market\\n */\\n function setLastRewardingBlockTimestamps(\\n VToken[] calldata vTokens,\\n uint256[] calldata supplyLastRewardingBlockTimestamps,\\n uint256[] calldata borrowLastRewardingBlockTimestamps\\n ) external {\\n _checkAccessAllowed(\\\"setLastRewardingBlockTimestamps(address[],uint256[],uint256[])\\\");\\n require(isTimeBased, \\\"Time-based operation only\\\");\\n\\n uint256 numTokens = vTokens.length;\\n require(\\n numTokens == supplyLastRewardingBlockTimestamps.length &&\\n numTokens == borrowLastRewardingBlockTimestamps.length,\\n \\\"RewardsDistributor::setLastRewardingBlockTimestamps invalid input\\\"\\n );\\n\\n for (uint256 i; i < numTokens; ) {\\n _setLastRewardingBlockTimestamp(\\n vTokens[i],\\n supplyLastRewardingBlockTimestamps[i],\\n borrowLastRewardingBlockTimestamps[i]\\n );\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single contributor\\n * @param contributor The contributor whose REWARD TOKEN speed to update\\n * @param rewardTokenSpeed New REWARD TOKEN speed for contributor\\n */\\n function setContributorRewardTokenSpeed(address contributor, uint256 rewardTokenSpeed) external onlyOwner {\\n // note that REWARD TOKEN speed could be set to 0 to halt liquidity rewards for a contributor\\n updateContributorRewards(contributor);\\n if (rewardTokenSpeed == 0) {\\n // release storage\\n delete lastContributorBlock[contributor];\\n } else {\\n lastContributorBlock[contributor] = getBlockNumberOrTimestamp();\\n }\\n rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed;\\n\\n emit ContributorRewardTokenSpeedUpdated(contributor, rewardTokenSpeed);\\n }\\n\\n function distributeSupplierRewardToken(address vToken, address supplier) external onlyComptroller {\\n _distributeSupplierRewardToken(vToken, supplier);\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in all markets\\n * @param holder The address to claim REWARD TOKEN for\\n */\\n function claimRewardToken(address holder) external {\\n return claimRewardToken(holder, comptroller.getAllMarkets());\\n }\\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) external onlyOwner {\\n _setMaxLoopsLimit(limit);\\n }\\n\\n /**\\n * @notice Calculate additional accrued REWARD TOKEN for a contributor since last accrual\\n * @param contributor The address to calculate contributor rewards for\\n */\\n function updateContributorRewards(address contributor) public {\\n uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, lastContributorBlock[contributor]);\\n if (deltaBlocksOrTimestamp > 0 && rewardTokenSpeed > 0) {\\n uint256 newAccrued = mul_(deltaBlocksOrTimestamp, rewardTokenSpeed);\\n uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued);\\n\\n rewardTokenAccrued[contributor] = contributorAccrued;\\n lastContributorBlock[contributor] = blockNumberOrTimestamp;\\n\\n emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]);\\n }\\n }\\n\\n /**\\n * @notice Claim all the rewardToken accrued by holder in the specified markets\\n * @param holder The address to claim REWARD TOKEN for\\n * @param vTokens The list of markets to claim REWARD TOKEN in\\n */\\n function claimRewardToken(address holder, VToken[] memory vTokens) public {\\n uint256 vTokensCount = vTokens.length;\\n\\n _ensureMaxLoops(vTokensCount);\\n\\n for (uint256 i; i < vTokensCount; ++i) {\\n VToken vToken = vTokens[i];\\n require(comptroller.isMarketListed(vToken), \\\"market must be listed\\\");\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n _distributeBorrowerRewardToken(address(vToken), holder, borrowIndex);\\n _updateRewardTokenSupplyIndex(address(vToken));\\n _distributeSupplierRewardToken(address(vToken), holder);\\n }\\n rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]);\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding block for a single market.\\n * @param vToken market's whose reward token last rewarding block to be updated\\n * @param supplyLastRewardingBlock New supply-side REWARD TOKEN last rewarding block for market\\n * @param borrowLastRewardingBlock New borrow-side REWARD TOKEN last rewarding block for market\\n */\\n function _setLastRewardingBlock(\\n VToken vToken,\\n uint32 supplyLastRewardingBlock,\\n uint32 borrowLastRewardingBlock\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockNumber = getBlockNumberOrTimestamp();\\n\\n require(supplyLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n require(borrowLastRewardingBlock > blockNumber, \\\"setting last rewarding block in the past is not allowed\\\");\\n\\n uint32 currentSupplyLastRewardingBlock = rewardTokenSupplyState[address(vToken)].lastRewardingBlock;\\n uint32 currentBorrowLastRewardingBlock = rewardTokenBorrowState[address(vToken)].lastRewardingBlock;\\n\\n require(\\n currentSupplyLastRewardingBlock == 0 || currentSupplyLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlock == 0 || currentBorrowLastRewardingBlock > blockNumber,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlock != supplyLastRewardingBlock) {\\n rewardTokenSupplyState[address(vToken)].lastRewardingBlock = supplyLastRewardingBlock;\\n emit SupplyLastRewardingBlockUpdated(address(vToken), supplyLastRewardingBlock);\\n }\\n\\n if (currentBorrowLastRewardingBlock != borrowLastRewardingBlock) {\\n rewardTokenBorrowState[address(vToken)].lastRewardingBlock = borrowLastRewardingBlock;\\n emit BorrowLastRewardingBlockUpdated(address(vToken), borrowLastRewardingBlock);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN last rewarding timestamp for a single market.\\n * @param vToken market's whose reward token last rewarding timestamp to be updated\\n * @param supplyLastRewardingBlockTimestamp New supply-side REWARD TOKEN last rewarding timestamp for market\\n * @param borrowLastRewardingBlockTimestamp New borrow-side REWARD TOKEN last rewarding timestamp for market\\n */\\n function _setLastRewardingBlockTimestamp(\\n VToken vToken,\\n uint256 supplyLastRewardingBlockTimestamp,\\n uint256 borrowLastRewardingBlockTimestamp\\n ) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n uint256 blockTimestamp = getBlockNumberOrTimestamp();\\n\\n require(\\n supplyLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"setting last rewarding timestamp in the past is not allowed\\\"\\n );\\n require(\\n borrowLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"setting last rewarding timestamp in the past is not allowed\\\"\\n );\\n\\n uint256 currentSupplyLastRewardingBlockTimestamp = rewardTokenSupplyStateTimeBased[address(vToken)]\\n .lastRewardingTimestamp;\\n uint256 currentBorrowLastRewardingBlockTimestamp = rewardTokenBorrowStateTimeBased[address(vToken)]\\n .lastRewardingTimestamp;\\n\\n require(\\n currentSupplyLastRewardingBlockTimestamp == 0 || currentSupplyLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n require(\\n currentBorrowLastRewardingBlockTimestamp == 0 || currentBorrowLastRewardingBlockTimestamp > blockTimestamp,\\n \\\"this RewardsDistributor is already locked\\\"\\n );\\n\\n if (currentSupplyLastRewardingBlockTimestamp != supplyLastRewardingBlockTimestamp) {\\n rewardTokenSupplyStateTimeBased[address(vToken)].lastRewardingTimestamp = supplyLastRewardingBlockTimestamp;\\n emit SupplyLastRewardingBlockTimestampUpdated(address(vToken), supplyLastRewardingBlockTimestamp);\\n }\\n\\n if (currentBorrowLastRewardingBlockTimestamp != borrowLastRewardingBlockTimestamp) {\\n rewardTokenBorrowStateTimeBased[address(vToken)].lastRewardingTimestamp = borrowLastRewardingBlockTimestamp;\\n emit BorrowLastRewardingBlockTimestampUpdated(address(vToken), borrowLastRewardingBlockTimestamp);\\n }\\n }\\n\\n /**\\n * @notice Set REWARD TOKEN speed for a single market.\\n * @param vToken market's whose reward token rate to be updated\\n * @param supplySpeed New supply-side REWARD TOKEN speed for market\\n * @param borrowSpeed New borrow-side REWARD TOKEN speed for market\\n */\\n function _setRewardTokenSpeed(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\\n require(comptroller.isMarketListed(vToken), \\\"rewardToken market is not listed\\\");\\n\\n if (rewardTokenSupplySpeeds[address(vToken)] != supplySpeed) {\\n // Supply speed updated so let's update supply state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n _updateRewardTokenSupplyIndex(address(vToken));\\n\\n // Update speed and emit event\\n rewardTokenSupplySpeeds[address(vToken)] = supplySpeed;\\n emit RewardTokenSupplySpeedUpdated(vToken, supplySpeed);\\n }\\n\\n if (rewardTokenBorrowSpeeds[address(vToken)] != borrowSpeed) {\\n // Borrow speed updated so let's update borrow state to ensure that\\n // 1. REWARD TOKEN accrued properly for the old speed, and\\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\\n\\n // Update speed and emit event\\n rewardTokenBorrowSpeeds[address(vToken)] = borrowSpeed;\\n emit RewardTokenBorrowSpeedUpdated(vToken, borrowSpeed);\\n }\\n }\\n\\n /**\\n * @notice Calculate REWARD TOKEN 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 REWARD TOKEN to\\n */\\n function _distributeSupplierRewardToken(address vToken, address supplier) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\\n\\n uint256 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\\n uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier];\\n\\n // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenSupplierIndex[vToken][supplier] = supplyIndex;\\n\\n if (supplierIndex == 0 && supplyIndex >= INITIAL_INDEX) {\\n // Covers the case where users supplied tokens before the market's supply state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when supplier rewards were first\\n // set for the market.\\n supplierIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per vToken accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\\n\\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerVToken\\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\\n\\n uint256 supplierAccrued = add_(rewardTokenAccrued[supplier], supplierDelta);\\n rewardTokenAccrued[supplier] = supplierAccrued;\\n\\n emit DistributedSupplierRewardToken(VToken(vToken), supplier, supplierDelta, supplierAccrued, supplyIndex);\\n }\\n\\n /**\\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them.\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\\n * @param marketBorrowIndex The current global borrow index of vToken\\n */\\n function _distributeBorrowerRewardToken(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\\n\\n uint256 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\\n uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower];\\n\\n // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN\\n rewardTokenBorrowerIndex[vToken][borrower] = borrowIndex;\\n\\n if (borrowerIndex == 0 && borrowIndex >= INITIAL_INDEX) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\\n // Rewards the user with REWARD TOKEN accrued from the start of when borrower rewards were first\\n // set for the market.\\n borrowerIndex = INITIAL_INDEX;\\n }\\n\\n // Calculate change in the cumulative sum of the REWARD TOKEN per borrowed unit accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\\n\\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\\n\\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerBorrowedUnit\\n if (borrowerAmount != 0) {\\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\\n\\n uint256 borrowerAccrued = add_(rewardTokenAccrued[borrower], borrowerDelta);\\n rewardTokenAccrued[borrower] = borrowerAccrued;\\n\\n emit DistributedBorrowerRewardToken(VToken(vToken), borrower, borrowerDelta, borrowerAccrued, borrowIndex);\\n }\\n }\\n\\n /**\\n * @notice Transfer REWARD TOKEN to the user.\\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all.\\n * @param user The address of the user to transfer REWARD TOKEN to\\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\\n * @return The amount of REWARD TOKEN which was NOT transferred to the user\\n */\\n function _grantRewardToken(address user, uint256 amount) internal returns (uint256) {\\n uint256 rewardTokenRemaining = rewardToken.balanceOf(address(this));\\n if (amount > 0 && amount <= rewardTokenRemaining) {\\n rewardToken.safeTransfer(user, amount);\\n return 0;\\n }\\n return amount;\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the supply index\\n * @param vToken The market whose supply index to update\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenSupplyIndex(address vToken) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\\n\\n uint256 supplySpeed = rewardTokenSupplySpeeds[vToken];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (!isTimeBased) {\\n safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\");\\n }\\n\\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\\n ? supplyStateTimeBased.lastRewardingTimestamp\\n : uint256(supplyState.lastRewardingBlock);\\n\\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(\\n blockNumberOrTimestamp,\\n (isTimeBased ? supplyStateTimeBased.timestamp : uint256(supplyState.block))\\n );\\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, supplySpeed);\\n Double memory ratio = supplyTokens > 0\\n ? fraction(accruedSinceUpdate, supplyTokens)\\n : Double({ mantissa: 0 });\\n uint224 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\\n uint224 index = safe224(\\n add_(Double({ mantissa: supplyIndex }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n\\n if (isTimeBased) {\\n supplyStateTimeBased.index = index;\\n supplyStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n supplyState.index = index;\\n supplyState.block = uint32(blockNumberOrTimestamp);\\n }\\n } else if (deltaBlocksOrTimestamp > 0) {\\n isTimeBased ? supplyStateTimeBased.timestamp = blockNumberOrTimestamp : supplyState.block = uint32(\\n blockNumberOrTimestamp\\n );\\n }\\n\\n emit RewardTokenSupplyIndexUpdated(vToken);\\n }\\n\\n /**\\n * @notice Accrue REWARD TOKEN to the market by updating the borrow index\\n * @param vToken The market whose borrow index to update\\n * @param marketBorrowIndex The current global borrow index of vToken\\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\\n */\\n function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\\n\\n uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken];\\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\\n\\n if (!isTimeBased) {\\n safe32(blockNumberOrTimestamp, \\\"block number exceeds 32 bits\\\");\\n }\\n\\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\\n ? borrowStateTimeBased.lastRewardingTimestamp\\n : uint256(borrowState.lastRewardingBlock);\\n\\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\\n }\\n\\n uint256 deltaBlocksOrTimestamp = sub_(\\n blockNumberOrTimestamp,\\n (isTimeBased ? borrowStateTimeBased.timestamp : uint256(borrowState.block))\\n );\\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, borrowSpeed);\\n Double memory ratio = borrowAmount > 0\\n ? fraction(accruedSinceUpdate, borrowAmount)\\n : Double({ mantissa: 0 });\\n uint224 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\\n uint224 index = safe224(\\n add_(Double({ mantissa: borrowIndex }), ratio).mantissa,\\n \\\"new index exceeds 224 bits\\\"\\n );\\n\\n if (isTimeBased) {\\n borrowStateTimeBased.index = index;\\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n borrowState.index = index;\\n borrowState.block = uint32(blockNumberOrTimestamp);\\n }\\n } else if (deltaBlocksOrTimestamp > 0) {\\n if (isTimeBased) {\\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\\n } else {\\n borrowState.block = uint32(blockNumberOrTimestamp);\\n }\\n }\\n\\n emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex);\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken called when contract is block-based\\n * @param vToken The address of the vToken to be initialized\\n * @param blockNumber current block number\\n */\\n function _initializeMarketBlockBased(address vToken, uint32 blockNumber) internal {\\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\\n RewardToken storage borrowState = rewardTokenBorrowState[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 = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block numbers\\n */\\n supplyState.block = borrowState.block = blockNumber;\\n }\\n\\n /**\\n * @notice Initializes the market state for a specific vToken called when contract is time-based\\n * @param vToken The address of the vToken to be initialized\\n * @param blockTimestamp current block timestamp\\n */\\n function _initializeMarketTimestampBased(address vToken, uint256 blockTimestamp) internal {\\n TimeBasedRewardToken storage supplyState = rewardTokenSupplyStateTimeBased[vToken];\\n TimeBasedRewardToken storage borrowState = rewardTokenBorrowStateTimeBased[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 = INITIAL_INDEX;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = INITIAL_INDEX;\\n }\\n\\n /*\\n * Update market state block timestamp\\n */\\n supplyState.timestamp = borrowState.timestamp = blockTimestamp;\\n }\\n}\\n\",\"keccak256\":\"0x3cc824e59c923cfe25c4f1a875959b7e9410cde8e73cd405de13f301298c697f\",\"license\":\"BSD-3-Clause\"},\"contracts/Rewards/RewardsDistributorStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { IERC20Upgradeable } from \\\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\\\";\\n\\nimport { Comptroller } from \\\"../Comptroller.sol\\\";\\n\\n/**\\n * @title RewardsDistributorStorage\\n * @author Venus\\n * @dev Storage for RewardsDistributor\\n */\\ncontract RewardsDistributorStorage {\\n struct RewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block number the index was last updated at\\n uint32 block;\\n // The block number at which to stop rewards\\n uint32 lastRewardingBlock;\\n }\\n\\n struct TimeBasedRewardToken {\\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\\n uint224 index;\\n // The block timestamp the index was last updated at\\n uint256 timestamp;\\n // The block timestamp at which to stop rewards\\n uint256 lastRewardingTimestamp;\\n }\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => RewardToken) public rewardTokenSupplyState;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex;\\n\\n /// @notice The REWARD TOKEN accrued but not yet transferred to each user\\n mapping(address => uint256) public rewardTokenAccrued;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding borrow market per slot (block or second)\\n mapping(address => uint256) public rewardTokenBorrowSpeeds;\\n\\n /// @notice The rate at which rewardToken is distributed to the corresponding supply market per slot (block or second)\\n mapping(address => uint256) public rewardTokenSupplySpeeds;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => RewardToken) public rewardTokenBorrowState;\\n\\n /// @notice The portion of REWARD TOKEN that each contributor receives per slot (block or second)\\n mapping(address => uint256) public rewardTokenContributorSpeeds;\\n\\n /// @notice Last slot (block or second) at which a contributor's REWARD TOKEN rewards have been allocated\\n mapping(address => uint256) public lastContributorBlock;\\n\\n /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\\n mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex;\\n\\n Comptroller internal comptroller;\\n\\n IERC20Upgradeable public rewardToken;\\n\\n /// @notice The REWARD TOKEN market supply state for each market\\n mapping(address => TimeBasedRewardToken) public rewardTokenSupplyStateTimeBased;\\n\\n /// @notice The REWARD TOKEN market borrow state for each market\\n mapping(address => TimeBasedRewardToken) public rewardTokenBorrowStateTimeBased;\\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[37] private __gap;\\n}\\n\",\"keccak256\":\"0x70e5015a78a2acf95277949c8b4796e10b9ac194130be006d5e5217e158070c0\",\"license\":\"BSD-3-Clause\"},\"contracts/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\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 { AccessControlledV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"@venusprotocol/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\\\";\\n\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { ComptrollerInterface, ComptrollerViewInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"./ErrorReporter.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\nimport { TimeManagerV8 } from \\\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\\\";\\nimport { ensureNonzeroAddress } from \\\"./lib/validators.sol\\\";\\n\\n/**\\n * @title VToken\\n * @author Venus\\n * @notice Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview,\\n * each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of\\n * the pool. The main actions a user regularly interacts with in a market are:\\n\\n- mint/redeem of vTokens;\\n- transfer of vTokens;\\n- borrow/repay a loan on an underlying asset;\\n- liquidate a borrow or liquidate/heal an account.\\n\\n * A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`.\\n * The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted\\n * `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken`\\n * as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that\\n * a user may borrow up to a portion of their collateral determined by the market\\u2019s collateral factor. However, if their borrowed amount exceeds an amount\\n * calculated using the market\\u2019s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also\\n * pay off interest accrued on the borrow.\\n * \\n * The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller`\\n * and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a\\n * total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`.\\n * Both functions settle all of an account\\u2019s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of\\n * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\\n */\\ncontract VToken is\\n Ownable2StepUpgradeable,\\n AccessControlledV8,\\n VTokenInterface,\\n ExponentialNoError,\\n TokenErrorReporter,\\n TimeManagerV8\\n{\\n using SafeERC20Upgradeable for IERC20Upgradeable;\\n\\n uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5%\\n\\n // Maximum fraction of interest that can be set aside for reserves\\n uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18;\\n\\n // Maximum borrow rate that can ever be applied per slot(block or second)\\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\\n uint256 internal immutable MAX_BORROW_RATE_MANTISSA;\\n\\n /**\\n * Reentrancy Guard **\\n */\\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 * @param timeBased_ A boolean indicating whether the contract is based on time or block.\\n * @param blocksPerYear_ The number of blocks per year\\n * @param maxBorrowRateMantissa_ The maximum value of borrowing rate mantissa\\n * @custom:oz-upgrades-unsafe-allow constructor\\n */\\n constructor(\\n bool timeBased_,\\n uint256 blocksPerYear_,\\n uint256 maxBorrowRateMantissa_\\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\\n // Note that the contract is upgradeable. Use initialize() or reinitializers\\n // to set the state variables.\\n require(maxBorrowRateMantissa_ <= 1e18, \\\"Max borrow rate must be <= 1e18\\\");\\n\\n MAX_BORROW_RATE_MANTISSA = maxBorrowRateMantissa_;\\n _disableInitializers();\\n }\\n\\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_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n */\\n function initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) external initializer {\\n ensureNonzeroAddress(admin_);\\n\\n // Initialize the market\\n _initialize(\\n underlying_,\\n comptroller_,\\n interestRateModel_,\\n initialExchangeRateMantissa_,\\n name_,\\n symbol_,\\n decimals_,\\n admin_,\\n accessControlManager_,\\n riskManagement,\\n reserveFactorMantissa_\\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 * @return success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, msg.sender, dst, amount);\\n return true;\\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 success True if the transfer succeeded, reverts otherwise\\n * @custom:event Emits Transfer event on success\\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\\n * @custom:access Not restricted\\n */\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n _transferTokens(msg.sender, src, dst, amount);\\n return true;\\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 (uint256.max means infinite)\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n transferAllowances[src][spender] = amount;\\n emit Approval(src, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Increase approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param addedValue The number of additional tokens spender can transfer\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function increaseAllowance(address spender, uint256 addedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 newAllowance = transferAllowances[src][spender];\\n newAllowance += addedValue;\\n transferAllowances[src][spender] = newAllowance;\\n\\n emit Approval(src, spender, newAllowance);\\n return true;\\n }\\n\\n /**\\n * @notice Decreases approval for `spender`\\n * @param spender The address of the account which may transfer tokens\\n * @param subtractedValue The number of tokens to remove from total approval\\n * @return success Whether or not the approval succeeded\\n * @custom:event Emits Approval event\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) external override returns (bool) {\\n ensureNonzeroAddress(spender);\\n\\n address src = msg.sender;\\n uint256 currentAllowance = transferAllowances[src][spender];\\n require(currentAllowance >= subtractedValue, \\\"decreased allowance below zero\\\");\\n unchecked {\\n currentAllowance -= subtractedValue;\\n }\\n\\n transferAllowances[src][spender] = currentAllowance;\\n\\n emit Approval(src, spender, currentAllowance);\\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 amount The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint256) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return totalBorrows The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\\n accrueInterest();\\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 borrowBalance The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n return _borrowBalanceStored(account);\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function mint(uint256 mintAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _mintFresh(msg.sender, msg.sender, mintAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param minter User whom the supply will be attributed to\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n * @custom:error ZeroAddressNotAllowed is thrown when minter address is zero\\n */\\n function mintBehalf(address minter, uint256 mintAmount) external override nonReentrant returns (uint256) {\\n ensureNonzeroAddress(minter);\\n\\n accrueInterest();\\n\\n _mintFresh(msg.sender, minter, mintAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function redeem(uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _redeemFresh(msg.sender, msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function redeemBehalf(address redeemer, uint256 redeemTokens) external override nonReentrant returns (uint256) {\\n _ensureSenderIsDelegateOf(redeemer);\\n\\n accrueInterest();\\n\\n _redeemFresh(redeemer, msg.sender, redeemTokens, 0);\\n return NO_ERROR;\\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 receive from redeeming vTokens\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n */\\n function redeemUnderlying(uint256 redeemAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _redeemFresh(msg.sender, msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function redeemUnderlyingBehalf(\\n address redeemer,\\n uint256 redeemAmount\\n ) external override nonReentrant returns (uint256) {\\n _ensureSenderIsDelegateOf(redeemer);\\n\\n accrueInterest();\\n\\n _redeemFresh(redeemer, msg.sender, 0, redeemAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:access Not restricted\\n */\\n function borrow(uint256 borrowAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _borrowFresh(msg.sender, msg.sender, borrowAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:error DelegateNotApproved is thrown if caller is not approved delegate\\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\\n * @custom:event Emits Borrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function borrowBehalf(address borrower, uint256 borrowAmount) external override returns (uint256) {\\n _ensureSenderIsDelegateOf(borrower);\\n accrueInterest();\\n\\n _borrowFresh(borrower, msg.sender, borrowAmount);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrow(uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n return NO_ERROR;\\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, or type(uint256).max for the full outstanding amount\\n * @return error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override nonReentrant returns (uint256) {\\n accrueInterest();\\n\\n _repayBorrowFresh(msg.sender, borrower, repayAmount);\\n return NO_ERROR;\\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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Not restricted\\n */\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external override returns (uint256) {\\n _liquidateBorrow(msg.sender, borrower, repayAmount, vTokenCollateral, false);\\n return NO_ERROR;\\n }\\n\\n /**\\n * @notice sets protocol share accumulated from liquidations\\n * @dev must be equal or less than liquidation incentive - 1\\n * @param newProtocolSeizeShareMantissa_ new protocol share mantissa\\n * @custom:event Emits NewProtocolSeizeShare event on success\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error ProtocolSeizeShareTooBig is thrown when the new seize share is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa_) external {\\n _checkAccessAllowed(\\\"setProtocolSeizeShare(uint256)\\\");\\n uint256 liquidationIncentive = ComptrollerViewInterface(address(comptroller)).liquidationIncentiveMantissa();\\n if (newProtocolSeizeShareMantissa_ + MANTISSA_ONE > liquidationIncentive) {\\n revert ProtocolSeizeShareTooBig();\\n }\\n\\n uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\\n protocolSeizeShareMantissa = newProtocolSeizeShareMantissa_;\\n emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa_);\\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 * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n * @custom:event Emits NewReserveFactor event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:error SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant {\\n _checkAccessAllowed(\\\"setReserveFactor(uint256)\\\");\\n\\n accrueInterest();\\n _setReserveFactorFresh(newReserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to the protocol reserve contract\\n * @dev Gracefully return if reserves already reduced in accrueInterest\\n * @param reduceAmount Amount of reduction to reserves\\n * @custom:event Emits ReservesReduced event; may emit AccrueInterest\\n * @custom:error ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash\\n * @custom:error ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\\n * @custom:access Not restricted\\n */\\n function reduceReserves(uint256 reduceAmount) external override nonReentrant {\\n accrueInterest();\\n if (reduceReservesBlockNumber == getBlockNumberOrTimestamp()) return;\\n _reduceReservesFresh(reduceAmount);\\n }\\n\\n /**\\n * @notice The sender adds to reserves.\\n * @param addAmount The amount of underlying token to add as reserves\\n * @custom:event Emits ReservesAdded event; may emit AccrueInterest\\n * @custom:access Not restricted\\n */\\n function addReserves(uint256 addAmount) external override nonReentrant {\\n accrueInterest();\\n _addReservesFresh(addAmount);\\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 * @custom:event Emits NewMarketInterestRateModel event; may emit AccrueInterest\\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\\n * @custom:access Controlled by AccessControlManager\\n */\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external override {\\n _checkAccessAllowed(\\\"setInterestRateModel(address)\\\");\\n\\n accrueInterest();\\n _setInterestRateModelFresh(newInterestRateModel);\\n }\\n\\n /**\\n * @notice Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially\\n * \\\"forgiving\\\" the borrower. Healing is a situation that should rarely happen. However, some pools\\n * may list risky assets or be configured improperly \\u2013 we want to still handle such cases gracefully.\\n * We assume that Comptroller does the seizing, so this function is only available to Comptroller.\\n * @dev This function does not call any Comptroller hooks (like \\\"healAllowed\\\"), because we assume\\n * the Comptroller does all the necessary checks before calling this function.\\n * @param payer account who repays the debt\\n * @param borrower account to heal\\n * @param repayAmount amount to repay\\n * @custom:event Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\\n * @custom:error HealBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:access Only Comptroller\\n */\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external override nonReentrant {\\n if (repayAmount != 0) {\\n comptroller.preRepayHook(address(this), borrower);\\n }\\n\\n if (msg.sender != address(comptroller)) {\\n revert HealBorrowUnauthorized();\\n }\\n\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 totalBorrowsNew = totalBorrows;\\n\\n uint256 actualRepayAmount;\\n if (repayAmount != 0) {\\n // _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // We violate checks-effects-interactions here to account for tokens that take transfer fees\\n actualRepayAmount = _doTransferIn(payer, repayAmount);\\n totalBorrowsNew = totalBorrowsNew - actualRepayAmount;\\n emit RepayBorrow(\\n payer,\\n borrower,\\n actualRepayAmount,\\n accountBorrowsPrev - actualRepayAmount,\\n totalBorrowsNew\\n );\\n }\\n\\n // The transaction will fail if trying to repay too much\\n uint256 badDebtDelta = accountBorrowsPrev - actualRepayAmount;\\n if (badDebtDelta != 0) {\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld + badDebtDelta;\\n totalBorrowsNew = totalBorrowsNew - badDebtDelta;\\n badDebt = badDebtNew;\\n\\n // We treat healing as \\\"repayment\\\", where vToken is the payer\\n emit RepayBorrow(address(this), borrower, badDebtDelta, 0, totalBorrowsNew);\\n emit BadDebtIncreased(borrower, badDebtDelta, badDebtOld, badDebtNew);\\n }\\n\\n accountBorrows[borrower].principal = 0;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n emit HealBorrow(payer, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice The extended version of liquidations, callable only by Comptroller. May skip\\n * the close factor check. The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\\n * @custom:error ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller\\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\\n * @custom:access Only Comptroller\\n */\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) external override {\\n if (msg.sender != address(comptroller)) {\\n revert ForceLiquidateBorrowUnauthorized();\\n }\\n _liquidateBorrow(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\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 * @custom:event Emits Transfer, ReservesAdded events\\n * @custom:error LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\\n * @custom:access Not restricted\\n */\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external override nonReentrant {\\n _seize(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Updates bad debt\\n * @dev Called only when bad debt is recovered from auction. Updates internal cash balance.\\n * @param recoveredAmount_ The amount of bad debt recovered\\n * @custom:event Emits BadDebtRecovered event\\n * @custom:access Only Shortfall contract\\n */\\n function badDebtRecovered(uint256 recoveredAmount_) external {\\n require(msg.sender == shortfall, \\\"only shortfall contract can update bad debt\\\");\\n require(recoveredAmount_ <= badDebt, \\\"more than bad debt recovered from auction\\\");\\n\\n uint256 badDebtOld = badDebt;\\n uint256 badDebtNew = badDebtOld - recoveredAmount_;\\n badDebt = badDebtNew;\\n internalCash += recoveredAmount_;\\n\\n emit BadDebtRecovered(badDebtOld, badDebtNew);\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protocolShareReserve_ The address of the protocol share reserve contract\\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\\n * @custom:access Only Governance\\n */\\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\\n _setProtocolShareReserve(protocolShareReserve_);\\n }\\n\\n /**\\n * @notice Sets shortfall contract address\\n * @param shortfall_ The address of the shortfall contract\\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\\n * @custom:access Only Governance\\n */\\n function setShortfallContract(address shortfall_) external onlyOwner {\\n _setShortfallContract(shortfall_);\\n }\\n\\n /**\\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\\n * @param token The address of the ERC-20 token to sweep\\n * @custom:access Only Governance\\n */\\n function sweepToken(IERC20Upgradeable token) external override {\\n require(msg.sender == owner(), \\\"VToken::sweepToken: only admin can sweep tokens\\\");\\n require(address(token) != underlying, \\\"VToken::sweepToken: can not sweep underlying token\\\");\\n uint256 balance = token.balanceOf(address(this));\\n token.safeTransfer(owner(), balance);\\n\\n emit SweepToken(address(token));\\n }\\n\\n /**\\n * @notice Sync internalCash with the actual underlying token balance\\n * @dev Used for one-time migration after upgrade to initialize internalCash\\n * @custom:event Emits CashSynced\\n * @custom:access Controlled by AccessControlManager\\n */\\n function syncCash() external override nonReentrant {\\n _checkAccessAllowed(\\\"syncCash()\\\");\\n uint256 oldInternalCash = internalCash;\\n uint256 actualCash = IERC20Upgradeable(underlying).balanceOf(address(this));\\n internalCash = actualCash;\\n emit CashSynced(oldInternalCash, actualCash);\\n }\\n\\n /**\\n * @notice A public function to set new threshold of slot(block or second) difference after which funds will be sent to the protocol share reserve\\n * @param _newReduceReservesBlockOrTimestampDelta slot(block or second) difference value\\n * @custom:access Only Governance\\n */\\n function setReduceReservesBlockDelta(uint256 _newReduceReservesBlockOrTimestampDelta) external {\\n _checkAccessAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n require(_newReduceReservesBlockOrTimestampDelta > 0, \\\"Invalid Input\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, _newReduceReservesBlockOrTimestampDelta);\\n reduceReservesBlockDelta = _newReduceReservesBlockOrTimestampDelta;\\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 amount 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 amount 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 error Always NO_ERROR for compatibility with Venus core tooling\\n * @return vTokenBalance User's balance of vTokens\\n * @return borrowBalance Amount owed in terms of underlying\\n * @return exchangeRate Stored exchange rate\\n */\\n function getAccountSnapshot(\\n address account\\n )\\n external\\n view\\n override\\n returns (uint256 error, uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRate)\\n {\\n return (NO_ERROR, accountTokens[account], _borrowBalanceStored(account), _exchangeRateStored());\\n }\\n\\n /**\\n * @notice Get the internally tracked cash balance of this vToken in the underlying asset\\n * @return cash The quantity of underlying asset tracked internally by this contract\\n */\\n function getCash() external view override returns (uint256) {\\n return _getCashPrior();\\n }\\n\\n /**\\n * @notice Returns the current per slot(block or second) borrow interest rate for this vToken\\n * @return rate The borrow interest rate per slot(block or second), scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint256) {\\n return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt);\\n }\\n\\n /**\\n * @notice Returns the current per-slot(block or second) supply interest rate for this v\\n * @return rate The supply interest rate per slot(block or second), scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint256) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPrior(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa,\\n badDebt\\n );\\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 borrowBalance The calculated balance\\n */\\n function borrowBalanceStored(address account) external view override returns (uint256) {\\n return _borrowBalanceStored(account);\\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 exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() external view override returns (uint256) {\\n return _exchangeRateStored();\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\\n accrueInterest();\\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 slot(block or second)\\n * up to the current slot(block or second) and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentSlot - reduceReservesBlockNumber >= slotDelta\\n * @return Always NO_ERROR\\n * @custom:event Emits AccrueInterest event on success\\n * @custom:access Not restricted\\n */\\n function accrueInterest() public virtual override returns (uint256) {\\n /* Remember the initial block number or timestamp */\\n uint256 currentSlotNumber = getBlockNumberOrTimestamp();\\n uint256 accrualSlotNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualSlotNumberPrior == currentSlotNumber) {\\n return NO_ERROR;\\n }\\n\\n /* Read the previous values out of storage */\\n uint256 cashPrior = _getCashPrior();\\n uint256 borrowsPrior = totalBorrows;\\n uint256 reservesPrior = totalReserves;\\n uint256 borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt);\\n require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of slots elapsed since the last accrual */\\n uint256 slotDelta = currentSlotNumber - accrualSlotNumberPrior;\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * slotDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), slotDelta);\\n uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\\n uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;\\n uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentSlotNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n if (currentSlotNumber - reduceReservesBlockNumber >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentSlotNumber;\\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 NO_ERROR;\\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 or timestamp\\n * @param payer The address of the account which is sending the assets for supply\\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 */\\n function _mintFresh(address payer, address minter, uint256 mintAmount) internal {\\n /* Fail if mint not allowed */\\n comptroller.preMintHook(address(this), minter, mintAmount);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert MintFreshnessCheck();\\n }\\n\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\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 * `_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 uint256 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 uint256 mintTokens = div_(actualMintAmount, exchangeRate);\\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 * And write them into storage\\n */\\n totalSupply = totalSupply + mintTokens;\\n uint256 balanceAfter = accountTokens[minter] + mintTokens;\\n accountTokens[minter] = balanceAfter;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, actualMintAmount, mintTokens, balanceAfter);\\n emit Transfer(address(0), minter, mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, actualMintAmount, mintTokens);\\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 Comptroller.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current slot(block or second)\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the underlying 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 */\\n function _redeemFresh(address redeemer, address receiver, uint256 redeemTokensIn, uint256 redeemAmountIn) internal {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert RedeemFreshnessCheck();\\n }\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n\\n uint256 redeemTokens;\\n uint256 redeemAmount;\\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 */\\n redeemTokens = redeemTokensIn;\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n */\\n redeemTokens = div_(redeemAmountIn, exchangeRate);\\n\\n uint256 _redeemAmount = mul_(redeemTokens, exchangeRate);\\n if (_redeemAmount != 0 && _redeemAmount != redeemAmountIn) redeemTokens++; // round up\\n }\\n\\n // redeemAmount = exchangeRate * redeemTokens\\n redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokens);\\n\\n // Revert if amount is zero\\n if (redeemAmount == 0) {\\n revert(\\\"redeemAmount is zero\\\");\\n }\\n\\n /* Fail if redeem not allowed */\\n comptroller.preRedeemHook(address(this), redeemer, redeemTokens);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (_getCashPrior() - totalReserves < redeemAmount) {\\n revert RedeemTransferOutNotPossible();\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\\n */\\n totalSupply = totalSupply - redeemTokens;\\n uint256 balanceAfter = accountTokens[redeemer] - redeemTokens;\\n accountTokens[redeemer] = balanceAfter;\\n\\n /*\\n * We invoke _doTransferOut for the receiver and the redeemAmount.\\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 _doTransferOut(receiver, redeemAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), redeemTokens);\\n emit Redeem(redeemer, redeemAmount, redeemTokens, balanceAfter);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, redeemAmount, redeemTokens);\\n }\\n\\n /**\\n * @notice Users or their delegates borrow assets from the protocol\\n * @param borrower User who borrows the assets\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param borrowAmount The amount of the underlying asset to borrow\\n */\\n function _borrowFresh(address borrower, address receiver, uint256 borrowAmount) internal {\\n /* Fail if borrow not allowed */\\n comptroller.preBorrowHook(address(this), borrower, borrowAmount);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert BorrowFreshnessCheck();\\n }\\n\\n /* Fail gracefully if protocol has insufficient underlying cash */\\n if (_getCashPrior() - totalReserves < borrowAmount) {\\n revert BorrowCashNotAvailable();\\n }\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowNew = accountBorrow + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;\\n uint256 totalBorrowsNew = totalBorrows + borrowAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We write the previously calculated values into storage.\\n * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\\n `*/\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /*\\n * We invoke _doTransferOut for the receiver and the borrowAmount.\\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, accountBorrowsNew, totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\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 underlying tokens being returned, or type(uint256).max for the full outstanding amount\\n * @return (uint) the actual repayment amount.\\n */\\n function _repayBorrowFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256) {\\n /* Fail if repayBorrow not allowed */\\n comptroller.preRepayHook(address(this), borrower);\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert RepayBorrowFreshnessCheck();\\n }\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\\n\\n uint256 repayAmountFinal = repayAmount >= accountBorrowsPrev ? accountBorrowsPrev : 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 * 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 uint256 actualRepayAmount = _doTransferIn(payer, repayAmountFinal);\\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 uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\\n uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, actualRepayAmount, borrowIndex);\\n\\n return actualRepayAmount;\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal nonReentrant {\\n accrueInterest();\\n\\n uint256 error = vTokenCollateral.accrueInterest();\\n if (error != NO_ERROR) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n revert LiquidateAccrueCollateralInterestFailed(error);\\n }\\n\\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param liquidator The address repaying the borrow and seizing collateral\\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\\n * regardless of the account liquidity\\n */\\n function _liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipLiquidityCheck\\n ) internal {\\n /* Fail if liquidate not allowed */\\n comptroller.preLiquidateHook(\\n address(this),\\n address(vTokenCollateral),\\n borrower,\\n repayAmount,\\n skipLiquidityCheck\\n );\\n\\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert LiquidateFreshnessCheck();\\n }\\n\\n /* Verify vTokenCollateral market's slot(block or second) number equals current slot(block or second) number */\\n if (vTokenCollateral.accrualBlockNumber() != getBlockNumberOrTimestamp()) {\\n revert LiquidateCollateralFreshnessCheck();\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateLiquidatorIsBorrower();\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n revert LiquidateCloseAmountIsZero();\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n revert LiquidateCloseAmountIsUintMax();\\n }\\n\\n /* Fail if repayBorrow fails */\\n uint256 actualRepayAmount = _repayBorrowFresh(liquidator, borrower, repayAmount);\\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.liquidateCalculateSeizeTokens(\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n require(amountSeizeError == 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, call _seize internally to avoid re-entrancy, otherwise make an external call\\n if (address(vTokenCollateral) == address(this)) {\\n _seize(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\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\\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 * It's absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerContract The contract seizing the collateral (either borrowed vToken or Comptroller)\\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 */\\n function _seize(address seizerContract, address liquidator, address borrower, uint256 seizeTokens) internal {\\n /* Fail if seize not allowed */\\n comptroller.preSeizeHook(address(this), seizerContract, liquidator, borrower);\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n revert LiquidateSeizeLiquidatorIsBorrower();\\n }\\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 uint256 liquidationIncentiveMantissa = ComptrollerViewInterface(address(comptroller))\\n .liquidationIncentiveMantissa();\\n uint256 numerator = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));\\n uint256 protocolSeizeTokens = div_(numerator, Exp({ mantissa: liquidationIncentiveMantissa }));\\n uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\\n uint256 protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the calculated values into storage */\\n totalSupply = totalSupply - protocolSeizeTokens;\\n accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\\n accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\\n\\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, protocolSeizeAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.LIQUIDATION\\n );\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\\n emit ProtocolSeize(borrower, protocolShareReserve, protocolSeizeAmount);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerContract, liquidator, borrower, seizeTokens);\\n }\\n\\n function _setComptroller(ComptrollerInterface newComptroller) internal {\\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\\n /**\\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\\n * @dev Admin function to set a new reserve factor\\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\\n */\\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal {\\n // Verify market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert SetReserveFactorFreshCheck();\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > MAX_RESERVE_FACTOR_MANTISSA) {\\n revert SetReserveFactorBoundsCheck();\\n }\\n\\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\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 actualAddAmount The actual amount added, excluding the potential token fees\\n */\\n function _addReservesFresh(uint256 addAmount) internal returns (uint256) {\\n // totalReserves + actualAddAmount\\n uint256 totalReservesNew;\\n uint256 actualAddAmount;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert AddReservesFactorFreshCheck(actualAddAmount);\\n }\\n\\n actualAddAmount = _doTransferIn(msg.sender, addAmount);\\n totalReservesNew = totalReserves + actualAddAmount;\\n totalReserves = totalReservesNew;\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n return actualAddAmount;\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to the protocol reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n */\\n function _reduceReservesFresh(uint256 reduceAmount) internal {\\n if (reduceAmount == 0) {\\n return;\\n }\\n // totalReserves - reduceAmount\\n uint256 totalReservesNew;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert ReduceReservesFreshCheck();\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (_getCashPrior() < reduceAmount) {\\n revert ReduceReservesCashNotAvailable();\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n revert ReduceReservesCashValidation();\\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 // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\\n _doTransferOut(protocolShareReserve, reduceAmount);\\n\\n // Update the pool asset's state in the protocol share reserve for the above transfer.\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit SpreadReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\\n }\\n\\n /**\\n * @notice updates the interest rate model (*requires fresh interest accrual)\\n * @dev Admin function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n */\\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal {\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModel oldInterestRateModel;\\n\\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\\n revert SetInterestRateModelFreshCheck();\\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\\n /**\\n * Safe Token **\\n */\\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 returns (uint256) {\\n IERC20Upgradeable token = IERC20Upgradeable(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 * @param to Receiver of the underlying tokens\\n * @param amount Amount of underlying to transfer\\n */\\n function _doTransferOut(address to, uint256 amount) internal virtual {\\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\\n internalCash -= amount;\\n token.safeTransfer(to, amount);\\n }\\n\\n /**\\n * @notice Transfer `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 */\\n function _transferTokens(address spender, address src, address dst, uint256 tokens) internal {\\n /* Fail if transfer not allowed */\\n comptroller.preTransferHook(address(this), src, dst, tokens);\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n revert TransferNotAllowed();\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint256 startingAllowance;\\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 uint256 allowanceNew = startingAllowance - tokens;\\n uint256 srcTokensNew = accountTokens[src] - tokens;\\n uint256 dstTokensNew = accountTokens[dst] + tokens;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n\\n accountTokens[src] = srcTokensNew;\\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\\n /**\\n * @notice Initialize the 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_ ERC-20 name of this token\\n * @param symbol_ ERC-20 symbol of this token\\n * @param decimals_ ERC-20 decimal precision of this token\\n * @param admin_ Address of the administrator of this token\\n * @param accessControlManager_ AccessControlManager contract address\\n * @param riskManagement Addresses of risk & income related contracts\\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\\n */\\n function _initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModel interestRateModel_,\\n uint256 initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_,\\n address admin_,\\n address accessControlManager_,\\n RiskManagementInit memory riskManagement,\\n uint256 reserveFactorMantissa_\\n ) internal onlyInitializing {\\n __Ownable2Step_init();\\n __AccessControlled_init_unchained(accessControlManager_);\\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 _setComptroller(comptroller_);\\n\\n // Initialize slot(block or second) number and borrow index (slot(block or second) number mocks depend on comptroller being set)\\n accrualBlockNumber = getBlockNumberOrTimestamp();\\n borrowIndex = MANTISSA_ONE;\\n\\n // Set the interest rate model (depends on slot(block or second) number / borrow index)\\n _setInterestRateModelFresh(interestRateModel_);\\n\\n _setReserveFactorFresh(reserveFactorMantissa_);\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n _setShortfallContract(riskManagement.shortfall);\\n _setProtocolShareReserve(riskManagement.protocolShareReserve);\\n protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA;\\n\\n // Set underlying and sanity check it\\n underlying = underlying_;\\n IERC20Upgradeable(underlying).totalSupply();\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n _transferOwnership(admin_);\\n }\\n\\n function _setShortfallContract(address shortfall_) internal {\\n ensureNonzeroAddress(shortfall_);\\n address oldShortfall = shortfall;\\n shortfall = shortfall_;\\n emit NewShortfallContract(oldShortfall, shortfall_);\\n }\\n\\n function _setProtocolShareReserve(address payable protocolShareReserve_) internal {\\n ensureNonzeroAddress(protocolShareReserve_);\\n address oldProtocolShareReserve = address(protocolShareReserve);\\n protocolShareReserve = protocolShareReserve_;\\n emit NewProtocolShareReserve(oldProtocolShareReserve, address(protocolShareReserve_));\\n }\\n\\n function _ensureSenderIsDelegateOf(address user) internal view {\\n if (!ComptrollerViewInterface(address(comptroller)).approvedDelegates(user, msg.sender)) {\\n revert DelegateNotApproved();\\n }\\n }\\n\\n /**\\n * @notice Gets the internally tracked cash balance of this market\\n * @dev Returns the internalCash state variable, which is updated on transfers in/out\\n * @return The quantity of underlying tokens tracked internally by this contract\\n */\\n function _getCashPrior() internal view virtual returns (uint256) {\\n return internalCash;\\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 borrowBalance the calculated balance\\n */\\n function _borrowBalanceStored(address account) internal view returns (uint256) {\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot memory 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 0;\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;\\n\\n return principalTimesIndex / borrowSnapshot.interestIndex;\\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 exchangeRate Calculated exchange rate scaled by 1e18\\n */\\n function _exchangeRateStored() internal view virtual returns (uint256) {\\n uint256 _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return initialExchangeRateMantissa;\\n }\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply\\n */\\n uint256 totalCash = _getCashPrior();\\n uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;\\n uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply;\\n\\n return exchangeRate;\\n }\\n}\\n\",\"keccak256\":\"0x7267f5337062ad01a5011f7725a86cc2ad0351cca0aaceadc167341f168cdef2\",\"license\":\"BSD-3-Clause\"},\"contracts/VTokenInterfaces.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\\nimport { ComptrollerInterface } from \\\"./ComptrollerInterface.sol\\\";\\nimport { InterestRateModel } from \\\"./InterestRateModel.sol\\\";\\n\\n/**\\n * @title VTokenStorage\\n * @author Venus\\n * @notice Storage layout used by the `VToken` contract\\n */\\n// solhint-disable-next-line max-states-count\\ncontract VTokenStorage {\\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 uint256 principal;\\n uint256 interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\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 Protocol share Reserve contract address\\n */\\n address payable public protocolShareReserve;\\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 InterestRateModel public interestRateModel;\\n\\n // Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n uint256 internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint256 public reserveFactorMantissa;\\n\\n /**\\n * @notice Slot(block or second) number that interest was last accrued at\\n */\\n uint256 public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint256 public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint256 public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint256 public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint256 public totalSupply;\\n\\n /**\\n * @notice Total bad debt of the market\\n */\\n uint256 public badDebt;\\n\\n // Official record of token balances for each account\\n mapping(address => uint256) internal accountTokens;\\n\\n // Approved token transfer amounts on behalf of others\\n mapping(address => mapping(address => uint256)) internal transferAllowances;\\n\\n // Mapping of account addresses to outstanding borrow balances\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Share of seized collateral that is added to reserves\\n */\\n uint256 public protocolSeizeShareMantissa;\\n\\n /**\\n * @notice Storage of Shortfall contract address\\n */\\n address public shortfall;\\n\\n /**\\n * @notice delta slot (block or second) after which reserves will be reduced\\n */\\n uint256 public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last slot (block or second) number at which reserves were reduced\\n */\\n uint256 public reduceReservesBlockNumber;\\n\\n /**\\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\\n * @dev Updated via _doTransferIn(), _doTransferOut(), syncCash(), and badDebtRecovered(). Must be initialized via syncCash() 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[47] private __gap;\\n}\\n\\n/**\\n * @title VTokenInterface\\n * @author Venus\\n * @notice Interface implemented by the `VToken` contract\\n */\\nabstract contract VTokenInterface is VTokenStorage {\\n struct RiskManagementInit {\\n address shortfall;\\n address payable protocolShareReserve;\\n }\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address indexed minter, uint256 mintAmount, uint256 mintTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens, uint256 accountBalance);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address indexed borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(\\n address indexed payer,\\n address indexed borrower,\\n uint256 repayAmount,\\n uint256 accountBorrows,\\n uint256 totalBorrows\\n );\\n\\n /**\\n * @notice Event emitted when bad debt is accumulated on a market\\n * @param borrower borrower to \\\"forgive\\\"\\n * @param badDebtDelta amount of new bad debt recorded\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtIncreased(address indexed borrower, uint256 badDebtDelta, uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when bad debt is recovered via an auction\\n * @param badDebtOld previous bad debt value\\n * @param badDebtNew new bad debt value\\n */\\n event BadDebtRecovered(uint256 badDebtOld, uint256 badDebtNew);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address indexed liquidator,\\n address indexed borrower,\\n uint256 repayAmount,\\n address indexed vTokenCollateral,\\n uint256 seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface indexed oldComptroller, ComptrollerInterface indexed newComptroller);\\n\\n /**\\n * @notice Event emitted when shortfall contract address is changed\\n */\\n event NewShortfallContract(address indexed oldShortfall, address indexed newShortfall);\\n\\n /**\\n * @notice Event emitted when protocol share reserve contract address is changed\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModel indexed oldInterestRateModel,\\n InterestRateModel indexed newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when protocol seize share is changed\\n */\\n event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address indexed benefactor, uint256 addAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the spread reserves are reduced\\n */\\n event SpreadReservesReduced(address indexed protocolShareReserve, uint256 reduceAmount, uint256 newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint256 amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 amount);\\n\\n /**\\n * @notice Event emitted when healing the borrow\\n */\\n event HealBorrow(address indexed payer, address indexed borrower, uint256 repayAmount);\\n\\n /**\\n * @notice Event emitted when tokens are swept\\n */\\n event SweepToken(address indexed token);\\n\\n /**\\n * @notice Event emitted when reduce reserves slot (block or second) delta is changed\\n */\\n event NewReduceReservesBlockDelta(\\n uint256 oldReduceReservesBlockOrTimestampDelta,\\n uint256 newReduceReservesBlockOrTimestampDelta\\n );\\n\\n /**\\n * @notice Event emitted when liquidation reserves are reduced\\n */\\n event ProtocolSeize(address indexed from, address indexed to, uint256 amount);\\n\\n /**\\n * @notice Event emitted when internalCash is synced with actual token balance\\n */\\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\\n\\n /*** User Interface ***/\\n\\n function mint(uint256 mintAmount) external virtual returns (uint256);\\n\\n function mintBehalf(address minter, uint256 mintAllowed) external virtual returns (uint256);\\n\\n function redeem(uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemBehalf(address redeemer, uint256 redeemTokens) external virtual returns (uint256);\\n\\n function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);\\n\\n function redeemUnderlyingBehalf(address redeemer, uint256 redeemAmount) external virtual returns (uint256);\\n\\n function borrow(uint256 borrowAmount) external virtual returns (uint256);\\n\\n function borrowBehalf(address borrwwer, uint256 borrowAmount) external virtual returns (uint256);\\n\\n function repayBorrow(uint256 repayAmount) external virtual returns (uint256);\\n\\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external virtual returns (uint256);\\n\\n function healBorrow(address payer, address borrower, uint256 repayAmount) external virtual;\\n\\n function forceLiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral,\\n bool skipCloseFactorCheck\\n ) external virtual;\\n\\n function seize(address liquidator, address borrower, uint256 seizeTokens) external virtual;\\n\\n function transfer(address dst, uint256 amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint256 amount) external virtual returns (bool);\\n\\n function accrueInterest() external virtual returns (uint256);\\n\\n function sweepToken(IERC20Upgradeable token) external virtual;\\n\\n /*** Admin Functions ***/\\n\\n function setReserveFactor(uint256 newReserveFactorMantissa) external virtual;\\n\\n function reduceReserves(uint256 reduceAmount) external virtual;\\n\\n function exchangeRateCurrent() external virtual returns (uint256);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint256);\\n\\n function setInterestRateModel(InterestRateModel newInterestRateModel) external virtual;\\n\\n function addReserves(uint256 addAmount) external virtual;\\n\\n function syncCash() external virtual;\\n\\n function totalBorrowsCurrent() external virtual returns (uint256);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint256);\\n\\n function approve(address spender, uint256 amount) external virtual returns (bool);\\n\\n function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool);\\n\\n function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint256);\\n\\n function balanceOf(address owner) external view virtual returns (uint256);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint256, uint256, uint256, uint256);\\n\\n function borrowRatePerBlock() external view virtual returns (uint256);\\n\\n function supplyRatePerBlock() external view virtual returns (uint256);\\n\\n function borrowBalanceStored(address account) external view virtual returns (uint256);\\n\\n function exchangeRateStored() external view virtual returns (uint256);\\n\\n function getCash() external view virtual returns (uint256);\\n\\n /**\\n * @notice Indicator that this is a VToken contract (for inspection)\\n * @return Always true\\n */\\n function isVToken() external pure virtual returns (bool) {\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x155684e9cb12cdd8be63d2314c9452b68ee44ff98a00e0d65cd1fd7d0bdd4391\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\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\",\"keccak256\":\"0x54ab3a6f3bc87569ed12370f3470a1ec84cea9796d4d0ccf3d07dd4280c044aa\",\"license\":\"BSD-3-Clause\"},\"contracts/lib/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 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\",\"keccak256\":\"0x93bdd5cfb100f0f9a1d446857e23c3633df6ab12c266333c978428edd96b1367\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x61010060405234801561001157600080fd5b50604051614176380380614176833981016040819052610030916100e9565b82828115801561003e575080155b1561005c576040516302723dfb60e21b815260040160405180910390fd5b81801561006857508015155b156100865760405163ae0fcab360e01b815260040160405180910390fd5b81151560a05281610097578061009d565b6301e133805b608052816100b4576100e160201b611d0c176100bf565b6100e560201b611d10175b6001600160401b031660c05250506001600160a01b031660e0525061013d9050565b4390565b4290565b6000806000606084860312156100fe57600080fd5b8351801515811461010e57600080fd5b6020850151604086015191945092506001600160a01b038116811461013257600080fd5b809150509250925092565b60805160a05160c05160e051613ff2610184600039600081816102e80152611d8201526000611ce00152600081816102b10152611f80015260006101dc0152613ff26000f3fe608060405234801561001057600080fd5b506004361061010b5760003560e01c80637c51b642116100a2578063c7ad089511610071578063c7ad0895146102ac578063d26998e9146102e3578063d77ebf961461030a578063e0a67f111461032a578063e1d146fb1461034a57600080fd5b80637c51b6421461022c5780637c84e3b31461024c578063aa5dbd231461026c578063b31242391461028c57600080fd5b806347d86a81116100de57806347d86a811461019957806355dd9515146101ac5780636857249c146101d75780637a27db571461020c57600080fd5b80630d3ae318146101105780631f884fdf14610139578063345954dc146101595780633e3e399c14610179575b600080fd5b61012361011e366004612ff0565b610352565b604051610130919061335d565b60405180910390f35b61014c6101473660046133bb565b610626565b60405161013091906133fc565b61016c61016736600461345c565b6106ee565b6040516101309190613479565b61018c61018736600461345c565b610821565b60405161013091906134dd565b6101236101a7366004613567565b610b30565b6101bf6101ba3660046135a0565b610bb7565b6040516001600160a01b039091168152602001610130565b6101fe7f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610130565b61021f61021a366004613567565b610c37565b60405161013091906135eb565b61023f61023a3660046136c7565b610ee7565b6040516101309190613752565b61025f61025a36600461345c565b610fa0565b60405161013091906137a0565b61027f61027a36600461345c565b61110a565b60405161013091906137c0565b61029f61029a366004613567565b6118ca565b60405161013091906137cf565b6102d37f000000000000000000000000000000000000000000000000000000000000000081565b6040519015158152602001610130565b6101bf7f000000000000000000000000000000000000000000000000000000000000000081565b61031d610318366004613567565b611bb1565b60405161013091906137dd565b61033d610338366004613841565b611c24565b60405161013091906138da565b6101fe611cd9565b61035a612db7565b6040820151600061036a82611d14565b9050600061037782611c24565b60408681015190516328ebbe8b60e21b81526001600160a01b039182166004820152919250879160009183169063a3aefa2c90602401600060405180830381865afa1580156103ca573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526103f29190810190613962565b90506000876040015190506000604051806101a001604052808a6000015181526020018a602001516001600160a01b031681526020018a604001516001600160a01b031681526020018a6060015181526020018a608001518152602001846000015181526020018460200151815260200184604001518152602001836001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104cf9190613a16565b6001600160a01b03168152602001836001600160a01b031663e87554466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561051b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053f9190613a33565b8152602001836001600160a01b0316634ada90af6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610582573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105a69190613a33565b8152602001836001600160a01b031663db5c65de6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060d9190613a33565b8152602001959095525092955050505050505b92915050565b6060816000816001600160401b0381111561064357610643612f39565b60405190808252806020026020018201604052801561068857816020015b60408051808201909152600080825260208201528152602001906001900390816106615790505b50905060005b828110156106e5576106c08686838181106106ab576106ab613a4c565b905060200201602081019061025a919061345c565b8282815181106106d2576106d2613a4c565b602090810291909101015260010161068e565b50949350505050565b606060008290506000816001600160a01b031663d88ff1f46040518163ffffffff1660e01b8152600401600060405180830381865afa158015610735573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261075d9190810190613ae5565b80519091506000816001600160401b0381111561077c5761077c612f39565b6040519080825280602002602001820160405280156107b557816020015b6107a2612db7565b81526020019060019003908161079a5790505b50905060005b828110156108175760008482815181106107d7576107d7613a4c565b6020026020010151905060006107ed8983610352565b90508084848151811061080257610802613a4c565b602090810291909101015250506001016107bb565b5095945050505050565b60408051606080820183526000808352602083018190529282015290828161084882611d14565b90506000826001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561088a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ae9190613a16565b9050600082516001600160401b038111156108cb576108cb612f39565b60405190808252806020026020018201604052801561091057816020015b60408051808201909152600080825260208201528152602001906001900390816108e95790505b509050610940604051806060016040528060006001600160a01b0316815260200160008152602001606081525090565b6001600160a01b03881681526040810182905260005b8451811015610b1c57604080518082019091526000808252602082015285828151811061098557610985613a4c565b602002602001015181600001906001600160a01b031690816001600160a01b031681525050670de0b6b3a7640000856001600160a01b031663fc57d4df8885815181106109d4576109d4613a4c565b60200260200101516040518263ffffffff1660e01b8152600401610a0791906001600160a01b0391909116815260200190565b602060405180830381865afa158015610a24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a489190613a33565b878481518110610a5a57610a5a613a4c565b60200260200101516001600160a01b031663bbcac5576040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac39190613a33565b610acd9190613bab565b610ad79190613bc2565b60208201526040830151805182919084908110610af657610af6613a4c565b6020026020010181905250806020015188610b119190613be4565b975050600101610956565b506020810195909552509295945050505050565b610b38612db7565b604051637aee632d60e01b81526001600160a01b0383811660048301528491610baf91839190821690637aee632d90602401600060405180830381865afa158015610b87573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261011e9190810190613bf7565b949350505050565b60405163266e0a7f60e01b81526001600160a01b0383811660048301528281166024830152600091859182169063266e0a7f90604401602060405180830381865afa158015610c0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2e9190613a16565b95945050505050565b60606000610c4483611d14565b90506000836001600160a01b03166361252fd16040518163ffffffff1660e01b8152600401600060405180830381865afa158015610c86573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cae9190810190613c2b565b9050600081516001600160401b03811115610ccb57610ccb612f39565b604051908082528060200260200182016040528015610d1c57816020015b6040805160808101825260008082526020808301829052928201526060808201528252600019909201910181610ce95790505b50905060005b8251811015610817576040805160808101825260008082526020820181905291810191909152606080820152838281518110610d6057610d60613a4c565b60209081029190910101516001600160a01b031681528351849083908110610d8a57610d8a613a4c565b60200260200101516001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dcf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df39190613a16565b6001600160a01b031660208201528351849083908110610e1557610e15613a4c565b6020908102919091010151604051631627ee8960e01b81526001600160a01b038a8116600483015290911690631627ee8990602401602060405180830381865afa158015610e67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8b9190613a33565b816040018181525050610eb88886868581518110610eab57610eab613a4c565b6020026020010151611eb3565b816060018190525080838381518110610ed357610ed3613a4c565b602090810291909101015250600101610d22565b6060826000816001600160401b03811115610f0457610f04612f39565b604051908082528060200260200182016040528015610f3d57816020015b610f2a612e3a565b815260200190600190039081610f225790505b50905060005b8281101561081757610f7b878783818110610f6057610f60613a4c565b9050602002016020810190610f75919061345c565b866118ca565b828281518110610f8d57610f8d613a4c565b6020908102919091010152600101610f43565b60408051808201909152600080825260208201526000826001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ff4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110189190613a16565b90506000816001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561105a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061107e9190613a16565b6040805180820182526001600160a01b03808816808352925163fc57d4df60e01b815260048101939093529293509160208301919084169063fc57d4df90602401602060405180830381865afa1580156110dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111009190613a33565b9052949350505050565b611112612e79565b6000826001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611152573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111769190613a33565b90506000836001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111dc9190613a16565b604051638e8f294b60e01b81526001600160a01b03868116600483015291925082916000918291841690638e8f294b906024016040805180830381865afa15801561122b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061124f9190613cc9565b915091506000876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611293573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b79190613a16565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061131d9190613cf5565b60ff1690506000805b600860ff8216116113e3576000886001600160a01b031663e85a29608d8460ff16600881111561135857611358613d18565b6040518363ffffffff1660e01b8152600401611375929190613d2e565b602060405180830381865afa158015611392573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b69190613d69565b6113c15760006113c4565b60015b60ff9081169083161b9290921791506113dc81613d84565b9050611326565b506000808b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611425573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114499190613a33565b11156114b4578a6001600160a01b031663ae9d70b06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561148d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114b19190613a33565b90505b6040518061022001604052808c6001600160a01b031681526020018a81526020018281526020018c6001600160a01b031663f8f9da286040518163ffffffff1660e01b8152600401602060405180830381865afa158015611519573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153d9190613a33565b81526020018c6001600160a01b031663173b99046040518163ffffffff1660e01b8152600401602060405180830381865afa158015611580573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a49190613a33565b81526040516302c3bcbb60e01b81526001600160a01b038e811660048301526020909201918a16906302c3bcbb90602401602060405180830381865afa1580156115f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116169190613a33565b815260405163252c221960e11b81526001600160a01b038e811660048301526020909201918a1690634a58443290602401602060405180830381865afa158015611664573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116889190613a33565b81526020018c6001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ef9190613a33565b81526020018c6001600160a01b0316638f840ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611732573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117569190613a33565b81526020018c6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611799573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117bd9190613a33565b81526020018c6001600160a01b0316633b1d21a26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611800573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118249190613a33565b81526020018715158152602001868152602001856001600160a01b031681526020018c6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611884573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118a89190613cf5565b60ff168152602001848152602001838152509950505050505050505050919050565b6118d2612e3a565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908516906370a0823190602401602060405180830381865afa15801561191c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119409190613a33565b6040516305eff7ef60e21b81526001600160a01b0385811660048301529192506000918616906317bfdfbc906024016020604051808303816000875af115801561198e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b29190613a33565b604051633af9e66960e01b81526001600160a01b038681166004830152919250600091871690633af9e669906024016020604051808303816000875af1158015611a00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a249190613a33565b90506000806000886001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a8d9190613a16565b6040516370a0823160e01b81526001600160a01b038a81166004830152919250908216906370a0823190602401602060405180830381865afa158015611ad7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611afb9190613a33565b604051636eb1769f60e11b81526001600160a01b038a811660048301528b811660248301529194509082169063dd62ed3e90604401602060405180830381865afa158015611b4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b719190613a33565b6040805160c0810182526001600160a01b038c168152602081019890985287019590955250506060840191909152608083015260a0820152905092915050565b604051631e6db74760e31b81526001600160a01b038281166004830152606091849182169063f36dba3890602401600060405180830381865afa158015611bfc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610baf9190810190613da3565b80516060906000816001600160401b03811115611c4357611c43612f39565b604051908082528060200260200182016040528015611c7c57816020015b611c69612e79565b815260200190600190039081611c615790505b50905060005b82811015611cd157611cac858281518110611c9f57611c9f613a4c565b602002602001015161110a565b828281518110611cbe57611cbe613a4c565b6020908102919091010152600101611c82565b509392505050565b6000611d077f000000000000000000000000000000000000000000000000000000000000000063ffffffff16565b905090565b4390565b4290565b60606000826001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015611d56573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d7e9190810190613e31565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031603611dbf5792915050565b8051600090815b81811015611ea9576000848281518110611de257611de2613a4c565b60200260200101516001600160a01b03166322abdbf56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e4b9190613a33565b1115611ea157838181518110611e6357611e63613a4c565b6020026020010151848481518110611e7d57611e7d613a4c565b6001600160a01b0390921660209283029190910190910152611e9e83613ebf565b92505b600101611dc6565b5050815292915050565b6060600083516001600160401b03811115611ed057611ed0612f39565b604051908082528060200260200182016040528015611f1557816020015b6040805180820190915260008082526020820152815260200190600190039081611eee5790505b50905060005b84518110156106e557611f51604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b611f7e604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b7f00000000000000000000000000000000000000000000000000000000000000001561210157856001600160a01b0316638f693ec7888581518110611fc557611fc5613a4c565b60200260200101516040518263ffffffff1660e01b8152600401611ff891906001600160a01b0391909116815260200190565b606060405180830381865afa158015612015573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120399190613eef565b604085015260208401526001600160e01b0316825286516001600160a01b0387169063818149459089908690811061207357612073613a4c565b60200260200101516040518263ffffffff1660e01b81526004016120a691906001600160a01b0391909116815260200190565b606060405180830381865afa1580156120c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e79190613eef565b604084015260208301526001600160e01b0316815261226c565b856001600160a01b0316632c427b5788858151811061212257612122613a4c565b60200260200101516040518263ffffffff1660e01b815260040161215591906001600160a01b0391909116815260200190565b606060405180830381865afa158015612172573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121969190613f38565b63ffffffff90811660408601521660208401526001600160e01b0316825286516001600160a01b038716906392a18235908990869081106121d9576121d9613a4c565b60200260200101516040518263ffffffff1660e01b815260040161220c91906001600160a01b0391909116815260200190565b606060405180830381865afa158015612229573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061224d9190613f38565b63ffffffff90811660408501521660208301526001600160e01b031681525b6000604051806020016040528089868151811061228b5761228b613a4c565b60200260200101516001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122f49190613a33565b815250905061231e88858151811061230e5761230e613a4c565b6020026020010151888584612413565b61234288858151811061233357612333613a4c565b60200260200101518884612614565b600061236a89868151811061235957612359613a4c565b6020026020010151898c878661280b565b905060006123938a878151811061238357612383613a4c565b60200260200101518a8d87612a3b565b60408051808201909152600080825260208201529091508a87815181106123bc576123bc613a4c565b60209081029190910101516001600160a01b031681526123dc8284613be4565b6020820152875181908990899081106123f7576123f7613a4c565b6020026020010181905250505050505050806001019050611f1b565b604051637c05a7c560e01b81526001600160a01b03858116600483015260009190851690637c05a7c590602401602060405180830381865afa15801561245d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124819190613a33565b9050600061248d611cd9565b9050600084604001511180156124a65750836040015181115b156124b2575060408301515b60006124c2828660200151612c5f565b90506000811180156124d45750600083115b156125fd576000612546886001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561251c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125409190613a33565b86612c72565b905060006125548386612c90565b90506000808311612574576040518060200160405280600081525061257e565b61257e8284612c9c565b905060006125a760405180602001604052808b600001516001600160e01b031681525083612ce1565b90506125e28160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612d0d565b6001600160e01b03168952505050506020850182905261260b565b801561260b57602085018290525b50505050505050565b604051631d31307360e21b81526001600160a01b038481166004830152600091908416906374c4c1cc90602401602060405180830381865afa15801561265e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126829190613a33565b9050600061268e611cd9565b9050600083604001511180156126a75750826040015181115b156126b3575060408201515b60006126c3828560200151612c5f565b90506000811180156126d55750600083115b156127f5576000866001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561271a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061273e9190613a33565b9050600061274c8386612c90565b9050600080831161276c5760405180602001604052806000815250612776565b6127768284612c9c565b9050600061279f60405180602001604052808a600001516001600160e01b031681525083612ce1565b90506127da8160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612d0d565b6001600160e01b031688525050505060208401829052612803565b801561280357602084018290525b505050505050565b604080516020808201835284516001600160e01b031682528251908101928390526336fe846560e11b9092526001600160a01b0387811660248401528581166044840152600092839181908916636dfd08ca60648301602060405180830381865afa15801561287e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a29190613a33565b905280519091501580156129245750866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129139190613f7b565b6001600160e01b0316826000015110155b1561299757866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061298b9190613f7b565b6001600160e01b031681525b60006129a38383612d49565b6040516395dd919360e01b81526001600160a01b038981166004830152919250600091612a1e91908c16906395dd919390602401602060405180830381865afa1580156129f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a189190613a33565b87612c72565b90506000612a2c8284612d75565b9b9a5050505050505050505050565b604080516020808201835283516001600160e01b0316825282519081019283905263552c097160e01b9092526001600160a01b038681166024840152848116604484015260009283918190881663552c097160648301602060405180830381865afa158015612aae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ad29190613a33565b90528051909150158015612b545750856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b439190613f7b565b6001600160e01b0316826000015110155b15612bc757856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bbb9190613f7b565b6001600160e01b031681525b6000612bd38383612d49565b6040516370a0823160e01b81526001600160a01b0388811660048301529192506000918a16906370a0823190602401602060405180830381865afa158015612c1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c439190613a33565b90506000612c518284612d75565b9a9950505050505050505050565b6000612c6b8284613f96565b9392505050565b6000612c6b612c8984670de0b6b3a7640000612c90565b8351612d9f565b6000612c6b8284613bab565b6040805160208101909152600081526040518060200160405280612cd8612cd2866ec097ce7bc90715b34b9f1000000000612c90565b85612d9f565b90529392505050565b6040805160208101909152600081526040518060200160405280612cd885600001518560000151612dab565b6000816001600160e01b03841115612d415760405162461bcd60e51b8152600401612d389190613fa9565b60405180910390fd5b509192915050565b6040805160208101909152600081526040518060200160405280612cd885600001518560000151612c5f565b60006ec097ce7bc90715b34b9f1000000000612d95848460000151612c90565b612c6b9190613bc2565b6000612c6b8284613bc2565b6000612c6b8284613be4565b604051806101a001604052806060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160608152602001606081526020016060815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001606081525090565b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180610220016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b6001600160a01b0381168114612f2657600080fd5b50565b8035612f3481612f11565b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715612f7157612f71612f39565b60405290565b604051606081016001600160401b0381118282101715612f7157612f71612f39565b604051601f8201601f191681016001600160401b0381118282101715612fc157612fc1612f39565b604052919050565b60006001600160401b03821115612fe257612fe2612f39565b50601f01601f191660200190565b6000806040838503121561300357600080fd5b823561300e81612f11565b91506020838101356001600160401b038082111561302b57600080fd5b9085019060a0828803121561303f57600080fd5b613047612f4f565b82358281111561305657600080fd5b83019150601f8201881361306957600080fd5b813561307c61307782612fc9565b612f99565b818152898683860101111561309057600080fd5b8186850187830137600086838301015280835250506130b0848401612f29565b848201526130c060408401612f29565b60408201526060830135606082015260808301356080820152809450505050509250929050565b60005b838110156131025781810151838201526020016130ea565b50506000910152565b600081518084526131238160208601602086016130e7565b601f01601f19169290920160200192915050565b80516001600160a01b031682526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e0830152610100808201518184015250610120808201518184015250610140808201518184015250610160808201516131c28285018215159052565b505061018081810151908301526101a0808201516001600160a01b0316908301526101c080820151908301526101e0808201519083015261020090810151910152565b60008151808452602080850194506020840160005b838110156132415761322d878351613137565b61022096909601959082019060010161321a565b509495945050505050565b60006101a082518185526132628286018261310b565b915050602083015161327f60208601826001600160a01b03169052565b50604083015161329a60408601826001600160a01b03169052565b50606083015160608501526080830151608085015260a083015184820360a08601526132c6828261310b565b91505060c083015184820360c08601526132e0828261310b565b91505060e083015184820360e08601526132fa828261310b565b91505061010080840151613318828701826001600160a01b03169052565b505061012083810151908501526101408084015190850152610160808401519085015261018080840151858303828701526133538382613205565b9695505050505050565b602081526000612c6b602083018461324c565b60008083601f84011261338257600080fd5b5081356001600160401b0381111561339957600080fd5b6020830191508360208260051b85010111156133b457600080fd5b9250929050565b600080602083850312156133ce57600080fd5b82356001600160401b038111156133e457600080fd5b6133f085828601613370565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b8281101561344f5761343f84835180516001600160a01b03168252602090810151910152565b9284019290850190600101613419565b5091979650505050505050565b60006020828403121561346e57600080fd5b8135612c6b81612f11565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156134d057603f198886030184526134be85835161324c565b945092850192908501906001016134a2565b5092979650505050505050565b602080825282516001600160a01b03168282015282810151604080840191909152808401516060808501528051608085018190526000939291830191849160a08701905b8084101561355b5761354782865180516001600160a01b03168252602090810151910152565b938501936001939093019290820190613521565b50979650505050505050565b6000806040838503121561357a57600080fd5b823561358581612f11565b9150602083013561359581612f11565b809150509250929050565b6000806000606084860312156135b557600080fd5b83356135c081612f11565b925060208401356135d081612f11565b915060408401356135e081612f11565b809150509250925092565b600060208083018184528085518083526040925060408601915060408160051b8701018488016000805b848110156136b857898403603f19018652825180516001600160a01b03908116865289820151168986015287810151888601526060908101516080918601829052805191860182905289019060a086019084905b808210156136a35761368f83855180516001600160a01b03168252602090810151910152565b928b0192918a019160019190910190613669565b50509689019694505091870191600101613615565b50919998505050505050505050565b6000806000604084860312156136dc57600080fd5b83356001600160401b038111156136f257600080fd5b6136fe86828701613370565b90945092505060208401356135e081612f11565b80516001600160a01b031682526020808201519083015260408082015190830152606080820151908301526080808201519083015260a090810151910152565b6020808252825182820181905260009190848201906040850190845b8181101561379457613781838551613712565b9284019260c0929092019160010161376e565b50909695505050505050565b81516001600160a01b031681526020808301519082015260408101610620565b61022081016106208284613137565b60c081016106208284613712565b6020808252825182820181905260009190848201906040850190845b818110156137945783516001600160a01b0316835292840192918401916001016137f9565b60006001600160401b0382111561383757613837612f39565b5060051b60200190565b6000602080838503121561385457600080fd5b82356001600160401b0381111561386a57600080fd5b8301601f8101851361387b57600080fd5b80356138896130778261381e565b81815260059190911b820183019083810190878311156138a857600080fd5b928401925b828410156138cf5783356138c081612f11565b825292840192908401906138ad565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561379457613909838551613137565b9284019261022092909201916001016138f6565b600082601f83011261392e57600080fd5b815161393c61307782612fc9565b81815284602083860101111561395157600080fd5b610baf8260208301602087016130e7565b60006020828403121561397457600080fd5b81516001600160401b038082111561398b57600080fd5b908301906060828603121561399f57600080fd5b6139a7612f77565b8251828111156139b657600080fd5b6139c28782860161391d565b8252506020830151828111156139d757600080fd5b6139e38782860161391d565b6020830152506040830151828111156139fb57600080fd5b613a078782860161391d565b60408301525095945050505050565b600060208284031215613a2857600080fd5b8151612c6b81612f11565b600060208284031215613a4557600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600060a08284031215613a7457600080fd5b613a7c612f4f565b905081516001600160401b03811115613a9457600080fd5b613aa08482850161391d565b8252506020820151613ab181612f11565b60208201526040820151613ac481612f11565b80604083015250606082015160608201526080820151608082015292915050565b60006020808385031215613af857600080fd5b82516001600160401b0380821115613b0f57600080fd5b818501915085601f830112613b2357600080fd5b8151613b316130778261381e565b81815260059190911b83018401908481019088831115613b5057600080fd5b8585015b83811015613b8857805185811115613b6c5760008081fd5b613b7a8b89838a0101613a62565b845250918601918601613b54565b5098975050505050505050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761062057610620613b95565b600082613bdf57634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561062057610620613b95565b600060208284031215613c0957600080fd5b81516001600160401b03811115613c1f57600080fd5b610baf84828501613a62565b60006020808385031215613c3e57600080fd5b82516001600160401b03811115613c5457600080fd5b8301601f81018513613c6557600080fd5b8051613c736130778261381e565b81815260059190911b82018301908381019087831115613c9257600080fd5b928401925b828410156138cf578351613caa81612f11565b82529284019290840190613c97565b80518015158114612f3457600080fd5b60008060408385031215613cdc57600080fd5b613ce583613cb9565b9150602083015190509250929050565b600060208284031215613d0757600080fd5b815160ff81168114612c6b57600080fd5b634e487b7160e01b600052602160045260246000fd5b6001600160a01b03831681526040810160098310613d5c57634e487b7160e01b600052602160045260246000fd5b8260208301529392505050565b600060208284031215613d7b57600080fd5b612c6b82613cb9565b600060ff821660ff8103613d9a57613d9a613b95565b60010192915050565b60006020808385031215613db657600080fd5b82516001600160401b03811115613dcc57600080fd5b8301601f81018513613ddd57600080fd5b8051613deb6130778261381e565b81815260059190911b82018301908381019087831115613e0a57600080fd5b928401925b828410156138cf578351613e2281612f11565b82529284019290840190613e0f565b60006020808385031215613e4457600080fd5b82516001600160401b03811115613e5a57600080fd5b8301601f81018513613e6b57600080fd5b8051613e796130778261381e565b81815260059190911b82018301908381019087831115613e9857600080fd5b928401925b828410156138cf578351613eb081612f11565b82529284019290840190613e9d565b600060018201613ed157613ed1613b95565b5060010190565b80516001600160e01b0381168114612f3457600080fd5b600080600060608486031215613f0457600080fd5b613f0d84613ed8565b925060208401519150604084015190509250925092565b805163ffffffff81168114612f3457600080fd5b600080600060608486031215613f4d57600080fd5b613f5684613ed8565b9250613f6460208501613f24565b9150613f7260408501613f24565b90509250925092565b600060208284031215613f8d57600080fd5b612c6b82613ed8565b8181038181111561062057610620613b95565b602081526000612c6b602083018461310b56fea264697066735822122096dca9ef030f65331631c7305d4d9405c1d0b56d48eb3787508d19369d85297764736f6c63430008190033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061010b5760003560e01c80637c51b642116100a2578063c7ad089511610071578063c7ad0895146102ac578063d26998e9146102e3578063d77ebf961461030a578063e0a67f111461032a578063e1d146fb1461034a57600080fd5b80637c51b6421461022c5780637c84e3b31461024c578063aa5dbd231461026c578063b31242391461028c57600080fd5b806347d86a81116100de57806347d86a811461019957806355dd9515146101ac5780636857249c146101d75780637a27db571461020c57600080fd5b80630d3ae318146101105780631f884fdf14610139578063345954dc146101595780633e3e399c14610179575b600080fd5b61012361011e366004612ff0565b610352565b604051610130919061335d565b60405180910390f35b61014c6101473660046133bb565b610626565b60405161013091906133fc565b61016c61016736600461345c565b6106ee565b6040516101309190613479565b61018c61018736600461345c565b610821565b60405161013091906134dd565b6101236101a7366004613567565b610b30565b6101bf6101ba3660046135a0565b610bb7565b6040516001600160a01b039091168152602001610130565b6101fe7f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610130565b61021f61021a366004613567565b610c37565b60405161013091906135eb565b61023f61023a3660046136c7565b610ee7565b6040516101309190613752565b61025f61025a36600461345c565b610fa0565b60405161013091906137a0565b61027f61027a36600461345c565b61110a565b60405161013091906137c0565b61029f61029a366004613567565b6118ca565b60405161013091906137cf565b6102d37f000000000000000000000000000000000000000000000000000000000000000081565b6040519015158152602001610130565b6101bf7f000000000000000000000000000000000000000000000000000000000000000081565b61031d610318366004613567565b611bb1565b60405161013091906137dd565b61033d610338366004613841565b611c24565b60405161013091906138da565b6101fe611cd9565b61035a612db7565b6040820151600061036a82611d14565b9050600061037782611c24565b60408681015190516328ebbe8b60e21b81526001600160a01b039182166004820152919250879160009183169063a3aefa2c90602401600060405180830381865afa1580156103ca573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526103f29190810190613962565b90506000876040015190506000604051806101a001604052808a6000015181526020018a602001516001600160a01b031681526020018a604001516001600160a01b031681526020018a6060015181526020018a608001518152602001846000015181526020018460200151815260200184604001518152602001836001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104cf9190613a16565b6001600160a01b03168152602001836001600160a01b031663e87554466040518163ffffffff1660e01b8152600401602060405180830381865afa15801561051b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053f9190613a33565b8152602001836001600160a01b0316634ada90af6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610582573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105a69190613a33565b8152602001836001600160a01b031663db5c65de6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105e9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060d9190613a33565b8152602001959095525092955050505050505b92915050565b6060816000816001600160401b0381111561064357610643612f39565b60405190808252806020026020018201604052801561068857816020015b60408051808201909152600080825260208201528152602001906001900390816106615790505b50905060005b828110156106e5576106c08686838181106106ab576106ab613a4c565b905060200201602081019061025a919061345c565b8282815181106106d2576106d2613a4c565b602090810291909101015260010161068e565b50949350505050565b606060008290506000816001600160a01b031663d88ff1f46040518163ffffffff1660e01b8152600401600060405180830381865afa158015610735573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261075d9190810190613ae5565b80519091506000816001600160401b0381111561077c5761077c612f39565b6040519080825280602002602001820160405280156107b557816020015b6107a2612db7565b81526020019060019003908161079a5790505b50905060005b828110156108175760008482815181106107d7576107d7613a4c565b6020026020010151905060006107ed8983610352565b90508084848151811061080257610802613a4c565b602090810291909101015250506001016107bb565b5095945050505050565b60408051606080820183526000808352602083018190529282015290828161084882611d14565b90506000826001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561088a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ae9190613a16565b9050600082516001600160401b038111156108cb576108cb612f39565b60405190808252806020026020018201604052801561091057816020015b60408051808201909152600080825260208201528152602001906001900390816108e95790505b509050610940604051806060016040528060006001600160a01b0316815260200160008152602001606081525090565b6001600160a01b03881681526040810182905260005b8451811015610b1c57604080518082019091526000808252602082015285828151811061098557610985613a4c565b602002602001015181600001906001600160a01b031690816001600160a01b031681525050670de0b6b3a7640000856001600160a01b031663fc57d4df8885815181106109d4576109d4613a4c565b60200260200101516040518263ffffffff1660e01b8152600401610a0791906001600160a01b0391909116815260200190565b602060405180830381865afa158015610a24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a489190613a33565b878481518110610a5a57610a5a613a4c565b60200260200101516001600160a01b031663bbcac5576040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac39190613a33565b610acd9190613bab565b610ad79190613bc2565b60208201526040830151805182919084908110610af657610af6613a4c565b6020026020010181905250806020015188610b119190613be4565b975050600101610956565b506020810195909552509295945050505050565b610b38612db7565b604051637aee632d60e01b81526001600160a01b0383811660048301528491610baf91839190821690637aee632d90602401600060405180830381865afa158015610b87573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261011e9190810190613bf7565b949350505050565b60405163266e0a7f60e01b81526001600160a01b0383811660048301528281166024830152600091859182169063266e0a7f90604401602060405180830381865afa158015610c0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2e9190613a16565b95945050505050565b60606000610c4483611d14565b90506000836001600160a01b03166361252fd16040518163ffffffff1660e01b8152600401600060405180830381865afa158015610c86573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610cae9190810190613c2b565b9050600081516001600160401b03811115610ccb57610ccb612f39565b604051908082528060200260200182016040528015610d1c57816020015b6040805160808101825260008082526020808301829052928201526060808201528252600019909201910181610ce95790505b50905060005b8251811015610817576040805160808101825260008082526020820181905291810191909152606080820152838281518110610d6057610d60613a4c565b60209081029190910101516001600160a01b031681528351849083908110610d8a57610d8a613a4c565b60200260200101516001600160a01b031663f7c618c16040518163ffffffff1660e01b8152600401602060405180830381865afa158015610dcf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610df39190613a16565b6001600160a01b031660208201528351849083908110610e1557610e15613a4c565b6020908102919091010151604051631627ee8960e01b81526001600160a01b038a8116600483015290911690631627ee8990602401602060405180830381865afa158015610e67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8b9190613a33565b816040018181525050610eb88886868581518110610eab57610eab613a4c565b6020026020010151611eb3565b816060018190525080838381518110610ed357610ed3613a4c565b602090810291909101015250600101610d22565b6060826000816001600160401b03811115610f0457610f04612f39565b604051908082528060200260200182016040528015610f3d57816020015b610f2a612e3a565b815260200190600190039081610f225790505b50905060005b8281101561081757610f7b878783818110610f6057610f60613a4c565b9050602002016020810190610f75919061345c565b866118ca565b828281518110610f8d57610f8d613a4c565b6020908102919091010152600101610f43565b60408051808201909152600080825260208201526000826001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ff4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110189190613a16565b90506000816001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561105a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061107e9190613a16565b6040805180820182526001600160a01b03808816808352925163fc57d4df60e01b815260048101939093529293509160208301919084169063fc57d4df90602401602060405180830381865afa1580156110dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111009190613a33565b9052949350505050565b611112612e79565b6000826001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611152573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111769190613a33565b90506000836001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111dc9190613a16565b604051638e8f294b60e01b81526001600160a01b03868116600483015291925082916000918291841690638e8f294b906024016040805180830381865afa15801561122b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061124f9190613cc9565b915091506000876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611293573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b79190613a16565b90506000816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061131d9190613cf5565b60ff1690506000805b600860ff8216116113e3576000886001600160a01b031663e85a29608d8460ff16600881111561135857611358613d18565b6040518363ffffffff1660e01b8152600401611375929190613d2e565b602060405180830381865afa158015611392573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b69190613d69565b6113c15760006113c4565b60015b60ff9081169083161b9290921791506113dc81613d84565b9050611326565b506000808b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611425573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114499190613a33565b11156114b4578a6001600160a01b031663ae9d70b06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561148d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114b19190613a33565b90505b6040518061022001604052808c6001600160a01b031681526020018a81526020018281526020018c6001600160a01b031663f8f9da286040518163ffffffff1660e01b8152600401602060405180830381865afa158015611519573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153d9190613a33565b81526020018c6001600160a01b031663173b99046040518163ffffffff1660e01b8152600401602060405180830381865afa158015611580573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a49190613a33565b81526040516302c3bcbb60e01b81526001600160a01b038e811660048301526020909201918a16906302c3bcbb90602401602060405180830381865afa1580156115f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116169190613a33565b815260405163252c221960e11b81526001600160a01b038e811660048301526020909201918a1690634a58443290602401602060405180830381865afa158015611664573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116889190613a33565b81526020018c6001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116ef9190613a33565b81526020018c6001600160a01b0316638f840ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611732573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117569190613a33565b81526020018c6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611799573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117bd9190613a33565b81526020018c6001600160a01b0316633b1d21a26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611800573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118249190613a33565b81526020018715158152602001868152602001856001600160a01b031681526020018c6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611884573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118a89190613cf5565b60ff168152602001848152602001838152509950505050505050505050919050565b6118d2612e3a565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908516906370a0823190602401602060405180830381865afa15801561191c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119409190613a33565b6040516305eff7ef60e21b81526001600160a01b0385811660048301529192506000918616906317bfdfbc906024016020604051808303816000875af115801561198e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b29190613a33565b604051633af9e66960e01b81526001600160a01b038681166004830152919250600091871690633af9e669906024016020604051808303816000875af1158015611a00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a249190613a33565b90506000806000886001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a69573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a8d9190613a16565b6040516370a0823160e01b81526001600160a01b038a81166004830152919250908216906370a0823190602401602060405180830381865afa158015611ad7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611afb9190613a33565b604051636eb1769f60e11b81526001600160a01b038a811660048301528b811660248301529194509082169063dd62ed3e90604401602060405180830381865afa158015611b4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b719190613a33565b6040805160c0810182526001600160a01b038c168152602081019890985287019590955250506060840191909152608083015260a0820152905092915050565b604051631e6db74760e31b81526001600160a01b038281166004830152606091849182169063f36dba3890602401600060405180830381865afa158015611bfc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610baf9190810190613da3565b80516060906000816001600160401b03811115611c4357611c43612f39565b604051908082528060200260200182016040528015611c7c57816020015b611c69612e79565b815260200190600190039081611c615790505b50905060005b82811015611cd157611cac858281518110611c9f57611c9f613a4c565b602002602001015161110a565b828281518110611cbe57611cbe613a4c565b6020908102919091010152600101611c82565b509392505050565b6000611d077f000000000000000000000000000000000000000000000000000000000000000063ffffffff16565b905090565b4390565b4290565b60606000826001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015611d56573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d7e9190810190613e31565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031603611dbf5792915050565b8051600090815b81811015611ea9576000848281518110611de257611de2613a4c565b60200260200101516001600160a01b03166322abdbf56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e4b9190613a33565b1115611ea157838181518110611e6357611e63613a4c565b6020026020010151848481518110611e7d57611e7d613a4c565b6001600160a01b0390921660209283029190910190910152611e9e83613ebf565b92505b600101611dc6565b5050815292915050565b6060600083516001600160401b03811115611ed057611ed0612f39565b604051908082528060200260200182016040528015611f1557816020015b6040805180820190915260008082526020820152815260200190600190039081611eee5790505b50905060005b84518110156106e557611f51604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b611f7e604051806060016040528060006001600160e01b0316815260200160008152602001600081525090565b7f00000000000000000000000000000000000000000000000000000000000000001561210157856001600160a01b0316638f693ec7888581518110611fc557611fc5613a4c565b60200260200101516040518263ffffffff1660e01b8152600401611ff891906001600160a01b0391909116815260200190565b606060405180830381865afa158015612015573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120399190613eef565b604085015260208401526001600160e01b0316825286516001600160a01b0387169063818149459089908690811061207357612073613a4c565b60200260200101516040518263ffffffff1660e01b81526004016120a691906001600160a01b0391909116815260200190565b606060405180830381865afa1580156120c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120e79190613eef565b604084015260208301526001600160e01b0316815261226c565b856001600160a01b0316632c427b5788858151811061212257612122613a4c565b60200260200101516040518263ffffffff1660e01b815260040161215591906001600160a01b0391909116815260200190565b606060405180830381865afa158015612172573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121969190613f38565b63ffffffff90811660408601521660208401526001600160e01b0316825286516001600160a01b038716906392a18235908990869081106121d9576121d9613a4c565b60200260200101516040518263ffffffff1660e01b815260040161220c91906001600160a01b0391909116815260200190565b606060405180830381865afa158015612229573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061224d9190613f38565b63ffffffff90811660408501521660208301526001600160e01b031681525b6000604051806020016040528089868151811061228b5761228b613a4c565b60200260200101516001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122f49190613a33565b815250905061231e88858151811061230e5761230e613a4c565b6020026020010151888584612413565b61234288858151811061233357612333613a4c565b60200260200101518884612614565b600061236a89868151811061235957612359613a4c565b6020026020010151898c878661280b565b905060006123938a878151811061238357612383613a4c565b60200260200101518a8d87612a3b565b60408051808201909152600080825260208201529091508a87815181106123bc576123bc613a4c565b60209081029190910101516001600160a01b031681526123dc8284613be4565b6020820152875181908990899081106123f7576123f7613a4c565b6020026020010181905250505050505050806001019050611f1b565b604051637c05a7c560e01b81526001600160a01b03858116600483015260009190851690637c05a7c590602401602060405180830381865afa15801561245d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124819190613a33565b9050600061248d611cd9565b9050600084604001511180156124a65750836040015181115b156124b2575060408301515b60006124c2828660200151612c5f565b90506000811180156124d45750600083115b156125fd576000612546886001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561251c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125409190613a33565b86612c72565b905060006125548386612c90565b90506000808311612574576040518060200160405280600081525061257e565b61257e8284612c9c565b905060006125a760405180602001604052808b600001516001600160e01b031681525083612ce1565b90506125e28160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612d0d565b6001600160e01b03168952505050506020850182905261260b565b801561260b57602085018290525b50505050505050565b604051631d31307360e21b81526001600160a01b038481166004830152600091908416906374c4c1cc90602401602060405180830381865afa15801561265e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126829190613a33565b9050600061268e611cd9565b9050600083604001511180156126a75750826040015181115b156126b3575060408201515b60006126c3828560200151612c5f565b90506000811180156126d55750600083115b156127f5576000866001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561271a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061273e9190613a33565b9050600061274c8386612c90565b9050600080831161276c5760405180602001604052806000815250612776565b6127768284612c9c565b9050600061279f60405180602001604052808a600001516001600160e01b031681525083612ce1565b90506127da8160000151604051806040016040528060138152602001726e657720696e646578206f766572666c6f777360681b815250612d0d565b6001600160e01b031688525050505060208401829052612803565b801561280357602084018290525b505050505050565b604080516020808201835284516001600160e01b031682528251908101928390526336fe846560e11b9092526001600160a01b0387811660248401528581166044840152600092839181908916636dfd08ca60648301602060405180830381865afa15801561287e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128a29190613a33565b905280519091501580156129245750866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129139190613f7b565b6001600160e01b0316826000015110155b1561299757866001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061298b9190613f7b565b6001600160e01b031681525b60006129a38383612d49565b6040516395dd919360e01b81526001600160a01b038981166004830152919250600091612a1e91908c16906395dd919390602401602060405180830381865afa1580156129f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a189190613a33565b87612c72565b90506000612a2c8284612d75565b9b9a5050505050505050505050565b604080516020808201835283516001600160e01b0316825282519081019283905263552c097160e01b9092526001600160a01b038681166024840152848116604484015260009283918190881663552c097160648301602060405180830381865afa158015612aae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ad29190613a33565b90528051909150158015612b545750856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b439190613f7b565b6001600160e01b0316826000015110155b15612bc757856001600160a01b031663160c3a036040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bbb9190613f7b565b6001600160e01b031681525b6000612bd38383612d49565b6040516370a0823160e01b81526001600160a01b0388811660048301529192506000918a16906370a0823190602401602060405180830381865afa158015612c1f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c439190613a33565b90506000612c518284612d75565b9a9950505050505050505050565b6000612c6b8284613f96565b9392505050565b6000612c6b612c8984670de0b6b3a7640000612c90565b8351612d9f565b6000612c6b8284613bab565b6040805160208101909152600081526040518060200160405280612cd8612cd2866ec097ce7bc90715b34b9f1000000000612c90565b85612d9f565b90529392505050565b6040805160208101909152600081526040518060200160405280612cd885600001518560000151612dab565b6000816001600160e01b03841115612d415760405162461bcd60e51b8152600401612d389190613fa9565b60405180910390fd5b509192915050565b6040805160208101909152600081526040518060200160405280612cd885600001518560000151612c5f565b60006ec097ce7bc90715b34b9f1000000000612d95848460000151612c90565b612c6b9190613bc2565b6000612c6b8284613bc2565b6000612c6b8284613be4565b604051806101a001604052806060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160608152602001606081526020016060815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001606081525090565b6040518060c0016040528060006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180610220016040528060006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000815260200160006001600160a01b031681526020016000815260200160008152602001600081525090565b6001600160a01b0381168114612f2657600080fd5b50565b8035612f3481612f11565b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b0381118282101715612f7157612f71612f39565b60405290565b604051606081016001600160401b0381118282101715612f7157612f71612f39565b604051601f8201601f191681016001600160401b0381118282101715612fc157612fc1612f39565b604052919050565b60006001600160401b03821115612fe257612fe2612f39565b50601f01601f191660200190565b6000806040838503121561300357600080fd5b823561300e81612f11565b91506020838101356001600160401b038082111561302b57600080fd5b9085019060a0828803121561303f57600080fd5b613047612f4f565b82358281111561305657600080fd5b83019150601f8201881361306957600080fd5b813561307c61307782612fc9565b612f99565b818152898683860101111561309057600080fd5b8186850187830137600086838301015280835250506130b0848401612f29565b848201526130c060408401612f29565b60408201526060830135606082015260808301356080820152809450505050509250929050565b60005b838110156131025781810151838201526020016130ea565b50506000910152565b600081518084526131238160208601602086016130e7565b601f01601f19169290920160200192915050565b80516001600160a01b031682526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c083015260e081015160e0830152610100808201518184015250610120808201518184015250610140808201518184015250610160808201516131c28285018215159052565b505061018081810151908301526101a0808201516001600160a01b0316908301526101c080820151908301526101e0808201519083015261020090810151910152565b60008151808452602080850194506020840160005b838110156132415761322d878351613137565b61022096909601959082019060010161321a565b509495945050505050565b60006101a082518185526132628286018261310b565b915050602083015161327f60208601826001600160a01b03169052565b50604083015161329a60408601826001600160a01b03169052565b50606083015160608501526080830151608085015260a083015184820360a08601526132c6828261310b565b91505060c083015184820360c08601526132e0828261310b565b91505060e083015184820360e08601526132fa828261310b565b91505061010080840151613318828701826001600160a01b03169052565b505061012083810151908501526101408084015190850152610160808401519085015261018080840151858303828701526133538382613205565b9695505050505050565b602081526000612c6b602083018461324c565b60008083601f84011261338257600080fd5b5081356001600160401b0381111561339957600080fd5b6020830191508360208260051b85010111156133b457600080fd5b9250929050565b600080602083850312156133ce57600080fd5b82356001600160401b038111156133e457600080fd5b6133f085828601613370565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b8281101561344f5761343f84835180516001600160a01b03168252602090810151910152565b9284019290850190600101613419565b5091979650505050505050565b60006020828403121561346e57600080fd5b8135612c6b81612f11565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156134d057603f198886030184526134be85835161324c565b945092850192908501906001016134a2565b5092979650505050505050565b602080825282516001600160a01b03168282015282810151604080840191909152808401516060808501528051608085018190526000939291830191849160a08701905b8084101561355b5761354782865180516001600160a01b03168252602090810151910152565b938501936001939093019290820190613521565b50979650505050505050565b6000806040838503121561357a57600080fd5b823561358581612f11565b9150602083013561359581612f11565b809150509250929050565b6000806000606084860312156135b557600080fd5b83356135c081612f11565b925060208401356135d081612f11565b915060408401356135e081612f11565b809150509250925092565b600060208083018184528085518083526040925060408601915060408160051b8701018488016000805b848110156136b857898403603f19018652825180516001600160a01b03908116865289820151168986015287810151888601526060908101516080918601829052805191860182905289019060a086019084905b808210156136a35761368f83855180516001600160a01b03168252602090810151910152565b928b0192918a019160019190910190613669565b50509689019694505091870191600101613615565b50919998505050505050505050565b6000806000604084860312156136dc57600080fd5b83356001600160401b038111156136f257600080fd5b6136fe86828701613370565b90945092505060208401356135e081612f11565b80516001600160a01b031682526020808201519083015260408082015190830152606080820151908301526080808201519083015260a090810151910152565b6020808252825182820181905260009190848201906040850190845b8181101561379457613781838551613712565b9284019260c0929092019160010161376e565b50909695505050505050565b81516001600160a01b031681526020808301519082015260408101610620565b61022081016106208284613137565b60c081016106208284613712565b6020808252825182820181905260009190848201906040850190845b818110156137945783516001600160a01b0316835292840192918401916001016137f9565b60006001600160401b0382111561383757613837612f39565b5060051b60200190565b6000602080838503121561385457600080fd5b82356001600160401b0381111561386a57600080fd5b8301601f8101851361387b57600080fd5b80356138896130778261381e565b81815260059190911b820183019083810190878311156138a857600080fd5b928401925b828410156138cf5783356138c081612f11565b825292840192908401906138ad565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561379457613909838551613137565b9284019261022092909201916001016138f6565b600082601f83011261392e57600080fd5b815161393c61307782612fc9565b81815284602083860101111561395157600080fd5b610baf8260208301602087016130e7565b60006020828403121561397457600080fd5b81516001600160401b038082111561398b57600080fd5b908301906060828603121561399f57600080fd5b6139a7612f77565b8251828111156139b657600080fd5b6139c28782860161391d565b8252506020830151828111156139d757600080fd5b6139e38782860161391d565b6020830152506040830151828111156139fb57600080fd5b613a078782860161391d565b60408301525095945050505050565b600060208284031215613a2857600080fd5b8151612c6b81612f11565b600060208284031215613a4557600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600060a08284031215613a7457600080fd5b613a7c612f4f565b905081516001600160401b03811115613a9457600080fd5b613aa08482850161391d565b8252506020820151613ab181612f11565b60208201526040820151613ac481612f11565b80604083015250606082015160608201526080820151608082015292915050565b60006020808385031215613af857600080fd5b82516001600160401b0380821115613b0f57600080fd5b818501915085601f830112613b2357600080fd5b8151613b316130778261381e565b81815260059190911b83018401908481019088831115613b5057600080fd5b8585015b83811015613b8857805185811115613b6c5760008081fd5b613b7a8b89838a0101613a62565b845250918601918601613b54565b5098975050505050505050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761062057610620613b95565b600082613bdf57634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561062057610620613b95565b600060208284031215613c0957600080fd5b81516001600160401b03811115613c1f57600080fd5b610baf84828501613a62565b60006020808385031215613c3e57600080fd5b82516001600160401b03811115613c5457600080fd5b8301601f81018513613c6557600080fd5b8051613c736130778261381e565b81815260059190911b82018301908381019087831115613c9257600080fd5b928401925b828410156138cf578351613caa81612f11565b82529284019290840190613c97565b80518015158114612f3457600080fd5b60008060408385031215613cdc57600080fd5b613ce583613cb9565b9150602083015190509250929050565b600060208284031215613d0757600080fd5b815160ff81168114612c6b57600080fd5b634e487b7160e01b600052602160045260246000fd5b6001600160a01b03831681526040810160098310613d5c57634e487b7160e01b600052602160045260246000fd5b8260208301529392505050565b600060208284031215613d7b57600080fd5b612c6b82613cb9565b600060ff821660ff8103613d9a57613d9a613b95565b60010192915050565b60006020808385031215613db657600080fd5b82516001600160401b03811115613dcc57600080fd5b8301601f81018513613ddd57600080fd5b8051613deb6130778261381e565b81815260059190911b82018301908381019087831115613e0a57600080fd5b928401925b828410156138cf578351613e2281612f11565b82529284019290840190613e0f565b60006020808385031215613e4457600080fd5b82516001600160401b03811115613e5a57600080fd5b8301601f81018513613e6b57600080fd5b8051613e796130778261381e565b81815260059190911b82018301908381019087831115613e9857600080fd5b928401925b828410156138cf578351613eb081612f11565b82529284019290840190613e9d565b600060018201613ed157613ed1613b95565b5060010190565b80516001600160e01b0381168114612f3457600080fd5b600080600060608486031215613f0457600080fd5b613f0d84613ed8565b925060208401519150604084015190509250925092565b805163ffffffff81168114612f3457600080fd5b600080600060608486031215613f4d57600080fd5b613f5684613ed8565b9250613f6460208501613f24565b9150613f7260408501613f24565b90509250925092565b600060208284031215613f8d57600080fd5b612c6b82613ed8565b8181038181111561062057610620613b95565b602081526000612c6b602083018461310b56fea264697066735822122096dca9ef030f65331631c7305d4d9405c1d0b56d48eb3787508d19369d85297764736f6c63430008190033", "devdoc": { "author": "Venus", "kind": "dev", @@ -1198,6 +1216,7 @@ "custom:oz-upgrades-unsafe-allow": "constructor", "params": { "blocksPerYear_": "The number of blocks per year", + "corePoolComptroller_": "The address of the core pool comptroller", "timeBased_": "A boolean indicating whether the contract is based on time or block." } }, @@ -1342,6 +1361,9 @@ "blocksOrSecondsPerYear()": { "notice": "Stores blocksPerYear if isTimeBased is true else secondsPerYear is stored" }, + "corePoolComptroller()": { + "notice": "Address of the core pool comptroller (all markets are returned for this pool, including paused ones)" + }, "getAllPools(address)": { "notice": "Queries all pools with addtional details for each of them" }, @@ -1391,7 +1413,7 @@ "storageLayout": { "storage": [ { - "astId": 9747, + "astId": 1737, "contract": "contracts/Lens/PoolLens.sol:PoolLens", "label": "__gap", "offset": 0, diff --git a/deployments/unichainmainnet/solcInputs/09f8b2889a382752688c03578bc27f8d.json b/deployments/unichainmainnet/solcInputs/09f8b2889a382752688c03578bc27f8d.json new file mode 100644 index 000000000..b2e4f0f5c --- /dev/null +++ b/deployments/unichainmainnet/solcInputs/09f8b2889a382752688c03578bc27f8d.json @@ -0,0 +1,139 @@ +{ + "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/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/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/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/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" + }, + "@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/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/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\ninterface IProtocolShareReserve {\n /// @notice it represents the type of vToken income\n enum IncomeType {\n SPREAD,\n LIQUIDATION,\n ERC4626_WRAPPER_REWARDS,\n FLASHLOAN\n }\n\n function updateAssetsState(\n address comptroller,\n address asset,\n IncomeType incomeType\n ) external;\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/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/venus-protocol/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" + }, + "@venusprotocol/venus-protocol/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/Comptroller.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { IPrime } from \"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\";\n\nimport { ComptrollerInterface, Action } from \"./ComptrollerInterface.sol\";\nimport { ComptrollerStorage } from \"./ComptrollerStorage.sol\";\nimport { ExponentialNoError } from \"./ExponentialNoError.sol\";\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.sol\";\nimport { MaxLoopsLimitHelper } from \"./MaxLoopsLimitHelper.sol\";\nimport { ensureNonzeroAddress } from \"./lib/validators.sol\";\n\n/**\n * @title Comptroller\n * @author Venus\n * @notice The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating,\n * and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts\n * with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows\n * or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing\n * liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow,\n * as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the\n * markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market’s corresponding liquidation threshold,\n * the borrow is eligible for liquidation.\n *\n * The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed\n * the `minLiquidatableCollateral` for the `Comptroller`:\n *\n * - `healAccount()`: This function is called to seize all of a given user’s collateral, requiring the `msg.sender` repay a certain percentage\n * of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed\n * 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt\n * and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool.\n * - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation\n * incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic\n * verifying that the repay amount does not exceed the close factor.\n */\ncontract Comptroller is\n Ownable2StepUpgradeable,\n AccessControlledV8,\n ComptrollerStorage,\n ComptrollerInterface,\n ExponentialNoError,\n MaxLoopsLimitHelper\n{\n // PoolRegistry, immutable to save on gas\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable poolRegistry;\n\n /// @notice Emitted when an account enters a market\n event MarketEntered(VToken indexed vToken, address indexed account);\n\n /// @notice Emitted when an account exits a market\n event MarketExited(VToken indexed vToken, address indexed account);\n\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(VToken vToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa);\n\n /// @notice Emitted when liquidation threshold is changed by admin\n event NewLiquidationThreshold(\n VToken vToken,\n uint256 oldLiquidationThresholdMantissa,\n uint256 newLiquidationThresholdMantissa\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 an action is paused on a market\n event ActionPausedMarket(VToken vToken, Action action, bool pauseState);\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 the collateral threshold (in USD) for non-batch liquidations is changed\n event NewMinLiquidatableCollateral(uint256 oldMinLiquidatableCollateral, uint256 newMinLiquidatableCollateral);\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 a rewards distributor is added\n event NewRewardsDistributor(address indexed rewardsDistributor, address indexed rewardToken);\n\n /// @notice Emitted when a market is supported\n event MarketSupported(VToken vToken);\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 a market\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\n\n /// @notice Emitted when a market is unlisted\n event MarketUnlisted(address indexed vToken);\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 Thrown when collateral factor exceeds the upper bound\n error InvalidCollateralFactor();\n\n /// @notice Thrown when liquidation threshold exceeds the collateral factor\n error InvalidLiquidationThreshold();\n\n /// @notice Thrown when the action is only available to specific sender, but the real sender was different\n error UnexpectedSender(address expectedSender, address actualSender);\n\n /// @notice Thrown when the oracle returns an invalid price for some asset\n error PriceError(address vToken);\n\n /// @notice Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\n error SnapshotError(address vToken, address user);\n\n /// @notice Thrown when the market is not listed\n error MarketNotListed(address market);\n\n /// @notice Thrown when a market has an unexpected comptroller\n error ComptrollerMismatch();\n\n /// @notice Thrown when user is not member of market\n error MarketNotCollateral(address vToken, address user);\n\n /// @notice Thrown when borrow action is not paused\n error BorrowActionNotPaused();\n\n /// @notice Thrown when mint action is not paused\n error MintActionNotPaused();\n\n /// @notice Thrown when redeem action is not paused\n error RedeemActionNotPaused();\n\n /// @notice Thrown when repay action is not paused\n error RepayActionNotPaused();\n\n /// @notice Thrown when seize action is not paused\n error SeizeActionNotPaused();\n\n /// @notice Thrown when exit market action is not paused\n error ExitMarketActionNotPaused();\n\n /// @notice Thrown when transfer action is not paused\n error TransferActionNotPaused();\n\n /// @notice Thrown when enter market action is not paused\n error EnterMarketActionNotPaused();\n\n /// @notice Thrown when liquidate action is not paused\n error LiquidateActionNotPaused();\n\n /// @notice Thrown when borrow cap is not zero\n error BorrowCapIsNotZero();\n\n /// @notice Thrown when supply cap is not zero\n error SupplyCapIsNotZero();\n\n /// @notice Thrown when collateral factor is not zero\n error CollateralFactorIsNotZero();\n\n /**\n * @notice Thrown during the liquidation if user's total collateral amount is lower than\n * a predefined threshold. In this case only batch liquidations (either liquidateAccount\n * or healAccount) are available.\n */\n error MinimalCollateralViolated(uint256 expectedGreaterThan, uint256 actual);\n error CollateralExceedsThreshold(uint256 expectedLessThanOrEqualTo, uint256 actual);\n error InsufficientCollateral(uint256 collateralToSeize, uint256 availableCollateral);\n\n /// @notice Thrown when the account doesn't have enough liquidity to redeem or borrow\n error InsufficientLiquidity();\n\n /// @notice Thrown when trying to liquidate a healthy account\n error InsufficientShortfall();\n\n /// @notice Thrown when trying to repay more than allowed by close factor\n error TooMuchRepay();\n\n /// @notice Thrown if the user is trying to exit a market in which they have an outstanding debt\n error NonzeroBorrowBalance();\n\n /// @notice Thrown when trying to perform an action that is paused\n error ActionPaused(address market, Action action);\n\n /// @notice Thrown when trying to add a market that is already listed\n error MarketAlreadyListed(address market);\n\n /// @notice Thrown if the supply cap is exceeded\n error SupplyCapExceeded(address market, uint256 cap);\n\n /// @notice Thrown if the borrow cap is exceeded\n error BorrowCapExceeded(address market, uint256 cap);\n\n /// @notice Thrown if delegate approval status is already set to the requested value\n error DelegationStatusUnchanged();\n\n /// @param poolRegistry_ Pool registry address\n /// @custom:oz-upgrades-unsafe-allow constructor\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n constructor(address poolRegistry_) {\n ensureNonzeroAddress(poolRegistry_);\n\n poolRegistry = poolRegistry_;\n _disableInitializers();\n }\n\n /**\n * @param loopLimit Limit for the loops can iterate to avoid the DOS\n * @param accessControlManager Access control manager contract address\n */\n function initialize(uint256 loopLimit, address accessControlManager) external initializer {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager);\n\n _setMaxLoopsLimit(loopLimit);\n }\n\n /**\n * @notice Add assets to be included in account liquidity calculation; enabling them to be used as collateral\n * @param vTokens The list of addresses of the vToken markets to be enabled\n * @return errors An array of NO_ERROR for compatibility with Venus core tooling\n * @custom:event MarketEntered is emitted for each market on success\n * @custom:error ActionPaused error is thrown if entering any of the markets is paused\n * @custom:error MarketNotListed error is thrown if any of the markets is not listed\n * @custom:access Not restricted\n */\n function enterMarkets(address[] memory vTokens) external override returns (uint256[] memory) {\n uint256 len = vTokens.length;\n\n uint256[] memory results = new uint256[](len);\n for (uint256 i; i < len; ++i) {\n VToken vToken = VToken(vTokens[i]);\n\n _addToMarket(vToken, msg.sender);\n results[i] = NO_ERROR;\n }\n\n return results;\n }\n\n /**\n * @notice Unlist a market by setting isListed to false\n * @dev Checks if all actions are paused, borrow/supply caps is set to 0 and collateral factor is to 0.\n * @param market The address of the market (token) to unlist\n * @return uint256 Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event MarketUnlisted is emitted on success\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error BorrowActionNotPaused error is thrown if borrow action is not paused\n * @custom:error MintActionNotPaused error is thrown if mint action is not paused\n * @custom:error RedeemActionNotPaused error is thrown if redeem action is not paused\n * @custom:error RepayActionNotPaused error is thrown if repay action is not paused\n * @custom:error EnterMarketActionNotPaused error is thrown if enter market action is not paused\n * @custom:error LiquidateActionNotPaused error is thrown if liquidate action is not paused\n * @custom:error BorrowCapIsNotZero error is thrown if borrow cap is not zero\n * @custom:error SupplyCapIsNotZero error is thrown if supply cap is not zero\n * @custom:error CollateralFactorIsNotZero error is thrown if collateral factor is not zero\n */\n function unlistMarket(address market) external returns (uint256) {\n _checkAccessAllowed(\"unlistMarket(address)\");\n\n Market storage _market = markets[market];\n\n if (!_market.isListed) {\n revert MarketNotListed(market);\n }\n\n if (!actionPaused(market, Action.BORROW)) {\n revert BorrowActionNotPaused();\n }\n\n if (!actionPaused(market, Action.MINT)) {\n revert MintActionNotPaused();\n }\n\n if (!actionPaused(market, Action.REDEEM)) {\n revert RedeemActionNotPaused();\n }\n\n if (!actionPaused(market, Action.REPAY)) {\n revert RepayActionNotPaused();\n }\n\n if (!actionPaused(market, Action.SEIZE)) {\n revert SeizeActionNotPaused();\n }\n\n if (!actionPaused(market, Action.ENTER_MARKET)) {\n revert EnterMarketActionNotPaused();\n }\n\n if (!actionPaused(market, Action.LIQUIDATE)) {\n revert LiquidateActionNotPaused();\n }\n\n if (!actionPaused(market, Action.TRANSFER)) {\n revert TransferActionNotPaused();\n }\n\n if (!actionPaused(market, Action.EXIT_MARKET)) {\n revert ExitMarketActionNotPaused();\n }\n\n if (borrowCaps[market] != 0) {\n revert BorrowCapIsNotZero();\n }\n\n if (supplyCaps[market] != 0) {\n revert SupplyCapIsNotZero();\n }\n\n if (_market.collateralFactorMantissa != 0) {\n revert CollateralFactorIsNotZero();\n }\n\n _market.isListed = false;\n emit MarketUnlisted(market);\n\n return NO_ERROR;\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 * @custom:event DelegateUpdated emits on success\n * @custom:error ZeroAddressNotAllowed is thrown when delegate address is zero\n * @custom:error DelegationStatusUnchanged is thrown if approval status is already set to the requested value\n * @custom:access Not restricted\n */\n function updateDelegate(address delegate, bool approved) external {\n ensureNonzeroAddress(delegate);\n if (approvedDelegates[msg.sender][delegate] == approved) {\n revert DelegationStatusUnchanged();\n }\n\n approvedDelegates[msg.sender][delegate] = approved;\n emit DelegateUpdated(msg.sender, delegate, approved);\n }\n\n /**\n * @notice Removes asset from sender's account liquidity calculation; disabling them as collateral\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event MarketExited is emitted on success\n * @custom:error ActionPaused error is thrown if exiting the market is paused\n * @custom:error NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function exitMarket(address vTokenAddress) external override returns (uint256) {\n _checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\n VToken vToken = VToken(vTokenAddress);\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\n (uint256 tokensHeld, uint256 amountOwed, ) = _safeGetAccountSnapshot(vToken, msg.sender);\n\n /* Fail if the sender has a borrow balance */\n if (amountOwed != 0) {\n revert NonzeroBorrowBalance();\n }\n\n /* Fail if the sender is not permitted to redeem all of their tokens */\n _checkRedeemAllowed(vTokenAddress, msg.sender, tokensHeld);\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 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 // load into memory for faster iteration\n VToken[] memory userAssetList = accountAssets[msg.sender];\n uint256 len = userAssetList.length;\n\n uint256 assetIndex = len;\n for (uint256 i; i < len; ++i) {\n if (userAssetList[i] == vToken) {\n assetIndex = i;\n break;\n }\n }\n\n // We *must* have found the asset in the list or our redundant data structure is broken\n assert(assetIndex < len);\n\n // copy last item in list to location of item to be removed, reduce length by 1\n VToken[] storage storedList = accountAssets[msg.sender];\n storedList[assetIndex] = storedList[storedList.length - 1];\n storedList.pop();\n\n emit MarketExited(vToken, msg.sender);\n\n return NO_ERROR;\n }\n\n /*** Policy Hooks ***/\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 * @custom:error ActionPaused error is thrown if supplying to this market is paused\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\n * @custom:access Not restricted\n */\n function preMintHook(address vToken, address minter, uint256 mintAmount) external override {\n _checkActionPauseState(vToken, Action.MINT);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n uint256 supplyCap = supplyCaps[vToken];\n // Skipping the cap check for uncapped coins to save some gas\n if (supplyCap != type(uint256).max) {\n uint256 vTokenSupply = VToken(vToken).totalSupply();\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\n if (nextTotalSupply > supplyCap) {\n revert SupplyCapExceeded(vToken, supplyCap);\n }\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, minter);\n }\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external override {\n _checkActionPauseState(vToken, Action.REDEEM);\n\n _checkRedeemAllowed(vToken, redeemer, redeemTokens);\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, redeemer);\n }\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 if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(redeemer, vToken);\n }\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 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 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 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 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 * @custom:error ActionPaused error is thrown if borrowing is paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if there is not enough collateral to borrow\n * @custom:error BorrowCapExceeded is thrown if the borrow cap will be exceeded should this borrow succeed\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted if vToken is enabled as collateral, otherwise only vToken\n */\n /// disable-eslint\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external override {\n _checkActionPauseState(vToken, Action.BORROW);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n if (!markets[vToken].accountMembership[borrower]) {\n // only vTokens may call borrowAllowed if borrower not in market\n _checkSenderIs(vToken);\n\n // attempt to add borrower to the market or revert\n _addToMarket(VToken(msg.sender), borrower);\n }\n\n // Update the prices of tokens\n updatePrices(borrower);\n\n if (oracle.getUnderlyingPrice(vToken) == 0) {\n revert PriceError(address(vToken));\n }\n\n uint256 borrowCap = borrowCaps[vToken];\n // Skipping the cap check for uncapped coins to save some gas\n if (borrowCap != type(uint256).max) {\n uint256 totalBorrows = VToken(vToken).totalBorrows();\n uint256 badDebt = VToken(vToken).badDebt();\n uint256 nextTotalBorrows = totalBorrows + borrowAmount + badDebt;\n if (nextTotalBorrows > borrowCap) {\n revert BorrowCapExceeded(vToken, borrowCap);\n }\n }\n\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n borrower,\n VToken(vToken),\n 0,\n borrowAmount,\n _getCollateralFactor\n );\n\n if (snapshot.shortfall > 0) {\n revert InsufficientLiquidity();\n }\n\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\n }\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 borrower The account which would borrowed the asset\n * @custom:error ActionPaused error is thrown if repayments are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:access Not restricted\n */\n function preRepayHook(address vToken, address borrower) external override {\n _checkActionPauseState(vToken, Action.REPAY);\n\n oracle.updatePrice(vToken);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\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 borrower The address of the borrower\n * @param repayAmount The amount of underlying being repaid\n * @param skipLiquidityCheck Allows the borrow to be liquidated regardless of the account liquidity\n * @custom:error ActionPaused error is thrown if liquidations are paused in this market\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\n * @custom:error TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor\n * @custom:error MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations\n * @custom:error InsufficientShortfall is thrown when trying to liquidate a healthy account\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n */\n function preLiquidateHook(\n address vTokenBorrowed,\n address vTokenCollateral,\n address borrower,\n uint256 repayAmount,\n bool skipLiquidityCheck\n ) external override {\n // Pause Action.LIQUIDATE on BORROWED TOKEN to prevent liquidating it.\n // If we want to pause liquidating to vTokenCollateral, we should pause\n // Action.SEIZE on it\n _checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\n\n // Update the prices of tokens\n updatePrices(borrower);\n\n if (!markets[vTokenBorrowed].isListed) {\n revert MarketNotListed(address(vTokenBorrowed));\n }\n if (!markets[vTokenCollateral].isListed) {\n revert MarketNotListed(address(vTokenCollateral));\n }\n\n uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\n\n /* Allow accounts to be liquidated if it is a forced liquidation */\n if (skipLiquidityCheck || isForcedLiquidationEnabled[vTokenBorrowed]) {\n if (repayAmount > borrowBalance) {\n revert TooMuchRepay();\n }\n return;\n }\n\n /* The borrower must have shortfall and collateral > threshold in order to be liquidatable */\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral <= minLiquidatableCollateral) {\n /* The liquidator should use either liquidateAccount or healAccount */\n revert MinimalCollateralViolated(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n /* The liquidator may not repay more than what is allowed by the closeFactor */\n uint256 maxClose = mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance);\n if (repayAmount > maxClose) {\n revert TooMuchRepay();\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 seizerContract Contract that tries to seize the asset (either borrowed vToken or Comptroller)\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @custom:error ActionPaused error is thrown if seizing this type of collateral is paused\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\n * @custom:error ComptrollerMismatch error is when seizer contract or seized asset belong to different pools\n * @custom:access Not restricted\n */\n function preSeizeHook(\n address vTokenCollateral,\n address seizerContract,\n address liquidator,\n address borrower\n ) external override {\n // Pause Action.SEIZE on COLLATERAL to prevent seizing it.\n // If we want to pause liquidating vTokenBorrowed, we should pause\n // Action.LIQUIDATE on it\n _checkActionPauseState(vTokenCollateral, Action.SEIZE);\n\n Market storage market = markets[vTokenCollateral];\n\n if (!market.isListed) {\n revert MarketNotListed(vTokenCollateral);\n }\n\n if (seizerContract == address(this)) {\n // If Comptroller is the seizer, just check if collateral's comptroller\n // is equal to the current address\n if (address(VToken(vTokenCollateral).comptroller()) != address(this)) {\n revert ComptrollerMismatch();\n }\n } else {\n // If the seizer is not the Comptroller, check that the seizer is a\n // listed market, and that the markets' comptrollers match\n if (!markets[seizerContract].isListed) {\n revert MarketNotListed(seizerContract);\n }\n if (VToken(vTokenCollateral).comptroller() != VToken(seizerContract).comptroller()) {\n revert ComptrollerMismatch();\n }\n }\n\n if (!market.accountMembership[borrower]) {\n revert MarketNotCollateral(vTokenCollateral, borrower);\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vTokenCollateral);\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, borrower);\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, liquidator);\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external override {\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 _checkRedeemAllowed(vToken, src, transferTokens);\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, src);\n rewardsDistributor.distributeSupplierRewardToken(vToken, dst);\n }\n }\n\n /*** Pool-level operations ***/\n\n /**\n * @notice Seizes all the remaining collateral, makes msg.sender repay the existing\n * borrows, and treats the rest of the debt as bad debt (for each market).\n * The sender has to repay a certain percentage of the debt, computed as\n * collateral / (borrows * liquidationIncentive).\n * @param user account to heal\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for healing\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function healAccount(address user) external {\n VToken[] memory userAssets = getAssetsIn(user);\n uint256 userAssetsCount = userAssets.length;\n\n address liquidator = msg.sender;\n {\n ResilientOracleInterface oracle_ = oracle;\n // We need all user's markets to be fresh for the computations to be correct\n for (uint256 i; i < userAssetsCount; ++i) {\n userAssets[i].accrueInterest();\n oracle_.updatePrice(address(userAssets[i]));\n }\n }\n\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(user, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n // percentage = collateral / (borrows * liquidation incentive)\n Exp memory collateral = Exp({ mantissa: snapshot.totalCollateral });\n Exp memory scaledBorrows = mul_(\n Exp({ mantissa: snapshot.borrows }),\n Exp({ mantissa: liquidationIncentiveMantissa })\n );\n\n Exp memory percentage = div_(collateral, scaledBorrows);\n if (lessThanExp(Exp({ mantissa: MANTISSA_ONE }), percentage)) {\n revert CollateralExceedsThreshold(scaledBorrows.mantissa, collateral.mantissa);\n }\n\n for (uint256 i; i < userAssetsCount; ++i) {\n VToken market = userAssets[i];\n\n (uint256 tokens, uint256 borrowBalance, ) = _safeGetAccountSnapshot(market, user);\n uint256 repaymentAmount = mul_ScalarTruncate(percentage, borrowBalance);\n\n // Seize the entire collateral\n if (tokens != 0) {\n market.seize(liquidator, user, tokens);\n }\n // Repay a certain percentage of the borrow, forgive the rest\n if (borrowBalance != 0) {\n market.healBorrow(liquidator, user, repaymentAmount);\n }\n }\n }\n\n /**\n * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than\n * a predefined threshold, and the account collateral can be seized to cover all borrows. If\n * the collateral is higher than the threshold, use regular liquidations. If the collateral is\n * below the threshold, and the account is insolvent, use healAccount.\n * @param borrower the borrower address\n * @param orders an array of liquidation orders\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation\n * @custom:error InsufficientCollateral error is thrown when there is not enough collateral to cover the debt\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function liquidateAccount(address borrower, LiquidationOrder[] calldata orders) external {\n // We will accrue interest and update the oracle prices later during the liquidation\n\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\n // You should use the regular vToken.liquidateBorrow(...) call\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n uint256 collateralToSeize = mul_ScalarTruncate(\n Exp({ mantissa: liquidationIncentiveMantissa }),\n snapshot.borrows\n );\n if (collateralToSeize >= snapshot.totalCollateral) {\n // There is not enough collateral to seize. Use healBorrow to repay some part of the borrow\n // and record bad debt.\n revert InsufficientCollateral(collateralToSeize, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n uint256 ordersCount = orders.length;\n\n _ensureMaxLoops(ordersCount / 2);\n\n for (uint256 i; i < ordersCount; ++i) {\n if (!markets[address(orders[i].vTokenBorrowed)].isListed) {\n revert MarketNotListed(address(orders[i].vTokenBorrowed));\n }\n if (!markets[address(orders[i].vTokenCollateral)].isListed) {\n revert MarketNotListed(address(orders[i].vTokenCollateral));\n }\n\n LiquidationOrder calldata order = orders[i];\n order.vTokenBorrowed.forceLiquidateBorrow(\n msg.sender,\n borrower,\n order.repayAmount,\n order.vTokenCollateral,\n true\n );\n }\n\n VToken[] memory borrowMarkets = getAssetsIn(borrower);\n uint256 marketsCount = borrowMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower);\n require(borrowBalance == 0, \"Nonzero borrow balance after liquidation\");\n }\n }\n\n /**\n * @notice Sets the closeFactor to use when liquidating borrows\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\n * @custom:event Emits NewCloseFactor on success\n * @custom:access Controlled by AccessControlManager\n */\n function setCloseFactor(uint256 newCloseFactorMantissa) external {\n _checkAccessAllowed(\"setCloseFactor(uint256)\");\n require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, \"Close factor greater than maximum close factor\");\n require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, \"Close factor smaller than minimum close factor\");\n\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\n closeFactorMantissa = newCloseFactorMantissa;\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\n }\n\n /**\n * @notice Sets the collateralFactor for a market\n * @dev This function is restricted by the AccessControlManager\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 * @custom:event Emits NewCollateralFactor when collateral factor is updated\n * and NewLiquidationThreshold when liquidation threshold is updated\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InvalidCollateralFactor error is thrown when collateral factor is too high\n * @custom:error InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor\n * @custom:error PriceError is thrown when the oracle returns an invalid price for the asset\n * @custom:access Controlled by AccessControlManager\n */\n function setCollateralFactor(\n VToken vToken,\n uint256 newCollateralFactorMantissa,\n uint256 newLiquidationThresholdMantissa\n ) external {\n _checkAccessAllowed(\"setCollateralFactor(address,uint256,uint256)\");\n\n // Verify market is listed\n Market storage market = markets[address(vToken)];\n if (!market.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n // Check collateral factor <= 0.9\n if (newCollateralFactorMantissa > MAX_COLLATERAL_FACTOR_MANTISSA) {\n revert InvalidCollateralFactor();\n }\n\n // Ensure that liquidation threshold <= 1\n if (newLiquidationThresholdMantissa > MANTISSA_ONE) {\n revert InvalidLiquidationThreshold();\n }\n\n // Ensure that liquidation threshold >= CF\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\n revert InvalidLiquidationThreshold();\n }\n\n // If collateral factor != 0, fail if price == 0\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\n revert PriceError(address(vToken));\n }\n\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\n market.collateralFactorMantissa = newCollateralFactorMantissa;\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\n }\n\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\n emit NewLiquidationThreshold(vToken, oldLiquidationThresholdMantissa, newLiquidationThresholdMantissa);\n }\n }\n\n /**\n * @notice Sets liquidationIncentive\n * @dev This function is restricted by the AccessControlManager\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\n * @custom:event Emits NewLiquidationIncentive on success\n * @custom:access Controlled by AccessControlManager\n */\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external {\n require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, \"liquidation incentive should be greater than 1e18\");\n\n _checkAccessAllowed(\"setLiquidationIncentive(uint256)\");\n\n // Save current value for use in log\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\n\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\n /**\n * @notice Add the market to the markets mapping and set it as listed\n * @dev Only callable by the PoolRegistry\n * @param vToken The address of the market (token) to list\n * @custom:error MarketAlreadyListed is thrown if the market is already listed in this pool\n * @custom:access Only PoolRegistry\n */\n function supportMarket(VToken vToken) external {\n _checkSenderIs(poolRegistry);\n\n if (markets[address(vToken)].isListed) {\n revert MarketAlreadyListed(address(vToken));\n }\n\n require(vToken.isVToken(), \"Comptroller: Invalid vToken\"); // Sanity check to make sure its really a VToken\n\n Market storage newMarket = markets[address(vToken)];\n newMarket.isListed = true;\n newMarket.collateralFactorMantissa = 0;\n newMarket.liquidationThresholdMantissa = 0;\n\n _addMarket(address(vToken));\n\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n rewardsDistributors[i].initializeMarket(address(vToken));\n }\n\n emit MarketSupported(vToken);\n }\n\n /**\n * @notice Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\n * @dev This function is restricted by the AccessControlManager\n * @dev A borrow cap of type(uint256).max corresponds to unlimited borrowing.\n * @dev Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed\n until the total borrows amount goes below the new borrow cap\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 type(uint256).max corresponds to unlimited borrowing.\n * @custom:access Controlled by AccessControlManager\n */\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\n _checkAccessAllowed(\"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 _ensureMaxLoops(numMarkets);\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 * @notice Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\n * @dev This function is restricted by the AccessControlManager\n * @dev A supply cap of type(uint256).max corresponds to unlimited supply.\n * @dev Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed\n until the total supplies amount goes below the new supply cap\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 type(uint256).max corresponds to unlimited supply.\n * @custom:access Controlled by AccessControlManager\n */\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\n _checkAccessAllowed(\"setMarketSupplyCaps(address[],uint256[])\");\n uint256 vTokensCount = vTokens.length;\n\n require(vTokensCount != 0, \"invalid number of markets\");\n require(vTokensCount == newSupplyCaps.length, \"invalid number of markets\");\n\n _ensureMaxLoops(vTokensCount);\n\n for (uint256 i; i < vTokensCount; ++i) {\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\n }\n }\n\n /**\n * @notice Pause/unpause specified actions\n * @dev This function is restricted by the AccessControlManager\n * @param marketsList Markets to pause/unpause the actions on\n * @param actionsList List of action ids to pause/unpause\n * @param paused The new paused state (true=paused, false=unpaused)\n * @custom:access Controlled by AccessControlManager\n */\n function setActionsPaused(VToken[] calldata marketsList, Action[] calldata actionsList, bool paused) external {\n _checkAccessAllowed(\"setActionsPaused(address[],uint256[],bool)\");\n\n uint256 marketsCount = marketsList.length;\n uint256 actionsCount = actionsList.length;\n\n _ensureMaxLoops(marketsCount * actionsCount);\n\n for (uint256 marketIdx; marketIdx < marketsCount; ++marketIdx) {\n for (uint256 actionIdx; actionIdx < actionsCount; ++actionIdx) {\n _setActionPaused(address(marketsList[marketIdx]), actionsList[actionIdx], paused);\n }\n }\n }\n\n /**\n * @notice Set the given collateral threshold for non-batch liquidations. Regular liquidations\n * will fail if the collateral amount is less than this threshold. Liquidators should use batch\n * operations like liquidateAccount or healAccount.\n * @dev This function is restricted by the AccessControlManager\n * @param newMinLiquidatableCollateral The new min liquidatable collateral (in USD).\n * @custom:access Controlled by AccessControlManager\n */\n function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external {\n _checkAccessAllowed(\"setMinLiquidatableCollateral(uint256)\");\n\n uint256 oldMinLiquidatableCollateral = minLiquidatableCollateral;\n minLiquidatableCollateral = newMinLiquidatableCollateral;\n emit NewMinLiquidatableCollateral(oldMinLiquidatableCollateral, newMinLiquidatableCollateral);\n }\n\n /**\n * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor\n * contracts with the same rewardToken, and there could be overlaping among them considering the last reward slot (block or second)\n * @dev Only callable by the admin\n * @param _rewardsDistributor Address of the RewardDistributor contract to add\n * @custom:access Only Governance\n * @custom:event Emits NewRewardsDistributor with distributor address\n */\n function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner {\n require(!rewardsDistributorExists[address(_rewardsDistributor)], \"already exists\");\n\n uint256 rewardsDistributorsLen = rewardsDistributors.length;\n _ensureMaxLoops(rewardsDistributorsLen + 1);\n\n rewardsDistributors.push(_rewardsDistributor);\n rewardsDistributorExists[address(_rewardsDistributor)] = true;\n\n uint256 marketsCount = allMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n _rewardsDistributor.initializeMarket(address(allMarkets[i]));\n }\n\n emit NewRewardsDistributor(address(_rewardsDistributor), address(_rewardsDistributor.rewardToken()));\n }\n\n /**\n * @notice Sets a new price oracle for the Comptroller\n * @dev Only callable by the admin\n * @param newOracle Address of the new price oracle to set\n * @custom:event Emits NewPriceOracle on success\n * @custom:error ZeroAddressNotAllowed is thrown when the new oracle address is zero\n */\n function setPriceOracle(ResilientOracleInterface newOracle) external onlyOwner {\n ensureNonzeroAddress(address(newOracle));\n\n ResilientOracleInterface oldOracle = oracle;\n oracle = newOracle;\n emit NewPriceOracle(oldOracle, newOracle);\n }\n\n /**\n * @notice Set the for loop iteration limit to avoid DOS\n * @param limit Limit for the max loops can execute at a time\n */\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\n _setMaxLoopsLimit(limit);\n }\n\n /**\n * @notice Sets the prime token contract for the comptroller\n * @param _prime Address of the Prime contract\n */\n function setPrimeToken(IPrime _prime) external onlyOwner {\n ensureNonzeroAddress(address(_prime));\n\n emit NewPrimeToken(prime, _prime);\n prime = _prime;\n }\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 * @param vTokenBorrowed Borrowed vToken\n * @param enable Whether to enable forced liquidations\n */\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\n _checkAccessAllowed(\"setForcedLiquidation(address,bool)\");\n ensureNonzeroAddress(vTokenBorrowed);\n\n if (!markets[vTokenBorrowed].isListed) {\n revert MarketNotListed(vTokenBorrowed);\n }\n\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\n }\n\n /**\n * @notice Determine the current account liquidity with respect to liquidation threshold requirements\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\n * @param account The account get liquidity for\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Account liquidity in excess of liquidation threshold requirements,\n * @return shortfall Account shortfall below liquidation threshold requirements\n */\n function getAccountLiquidity(\n address account\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getLiquidationThreshold);\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\n }\n\n /**\n * @notice Determine the current account liquidity with respect to collateral requirements\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\n * @param account The account get liquidity for\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Account liquidity in excess of collateral requirements,\n * @return shortfall Account shortfall below collateral requirements\n */\n function getBorrowingPower(\n address account\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getCollateralFactor);\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\n }\n\n /**\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Hypothetical account liquidity in excess of collateral requirements,\n * @return shortfall 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 error, uint256 liquidity, uint256 shortfall) {\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n account,\n VToken(vTokenModify),\n redeemTokens,\n borrowAmount,\n _getCollateralFactor\n );\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\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 markets The list of market addresses\n */\n function getAllMarkets() external view override returns (VToken[] memory) {\n return allMarkets;\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 /*** Assets You Are In ***/\n\n /**\n * @notice Returns whether the given account is entered in a given market\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 market specified, 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 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 error Always NO_ERROR for compatibility with Venus core tooling\n * @return tokensToSeize Number of vTokenCollateral tokens to be seized in a liquidation\n * @custom:error PriceError if the oracle returns an invalid price\n */\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view override returns (uint256 error, uint256 tokensToSeize) {\n /* Read oracle prices for borrowed and collateral markets */\n uint256 priceBorrowedMantissa = _safeGetUnderlyingPrice(VToken(vTokenBorrowed));\n uint256 priceCollateralMantissa = _safeGetUnderlyingPrice(VToken(vTokenCollateral));\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 uint256 exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\n uint256 seizeTokens;\n Exp memory numerator;\n Exp memory denominator;\n Exp memory ratio;\n\n numerator = mul_(Exp({ mantissa: liquidationIncentiveMantissa }), Exp({ mantissa: priceBorrowedMantissa }));\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\n ratio = div_(numerator, denominator);\n\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\n\n return (NO_ERROR, seizeTokens);\n }\n\n /**\n * @notice Returns reward speed given a vToken\n * @param vToken The vToken to get the reward speeds for\n * @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors\n */\n function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {\n uint256 rewardsDistributorsLength = rewardsDistributors.length;\n rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);\n for (uint256 i; i < rewardsDistributorsLength; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n address rewardToken = address(rewardsDistributor.rewardToken());\n rewardSpeeds[i] = RewardSpeeds({\n rewardToken: rewardToken,\n supplySpeed: rewardsDistributor.rewardTokenSupplySpeeds(vToken),\n borrowSpeed: rewardsDistributor.rewardTokenBorrowSpeeds(vToken)\n });\n }\n return rewardSpeeds;\n }\n\n /**\n * @notice Return all reward distributors for this pool\n * @return Array of RewardDistributor addresses\n */\n function getRewardDistributors() external view returns (RewardsDistributor[] memory) {\n return rewardsDistributors;\n }\n\n /**\n * @notice A marker method that returns true for a valid Comptroller contract\n * @return Always true\n */\n function isComptroller() external pure override returns (bool) {\n return true;\n }\n\n /**\n * @notice Update the prices of all the tokens associated with the provided account\n * @param account Address of the account to get associated tokens with\n */\n function updatePrices(address account) public {\n VToken[] memory vTokens = getAssetsIn(account);\n uint256 vTokensCount = vTokens.length;\n\n ResilientOracleInterface oracle_ = oracle;\n\n for (uint256 i; i < vTokensCount; ++i) {\n oracle_.updatePrice(address(vTokens[i]));\n }\n }\n\n /**\n * @notice Checks if a certain action is paused on a market\n * @param market vToken address\n * @param action Action to check\n * @return paused True if the action is paused otherwise false\n */\n function actionPaused(address market, Action action) public view returns (bool) {\n return _actionPaused[market][action];\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 list with the assets the account has entered\n */\n function getAssetsIn(address account) public 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 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 */\n function _addToMarket(VToken vToken, address borrower) internal {\n _checkActionPauseState(address(vToken), Action.ENTER_MARKET);\n Market storage marketToJoin = markets[address(vToken)];\n\n if (!marketToJoin.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n if (marketToJoin.accountMembership[borrower]) {\n // already joined\n return;\n }\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\n /**\n * @notice Internal function to validate that a market hasn't already been added\n * and if it hasn't adds it\n * @param vToken The market to support\n */\n function _addMarket(address vToken) internal {\n uint256 marketsCount = allMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n if (allMarkets[i] == VToken(vToken)) {\n revert MarketAlreadyListed(vToken);\n }\n }\n allMarkets.push(VToken(vToken));\n marketsCount = allMarkets.length;\n _ensureMaxLoops(marketsCount);\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 _setActionPaused(address market, Action action, bool paused) internal {\n require(markets[market].isListed, \"cannot pause a market that is not listed\");\n _actionPaused[market][action] = paused;\n emit ActionPausedMarket(VToken(market), action, paused);\n }\n\n /**\n * @dev Internal function to check that vTokens can be safely redeemed for the underlying asset.\n * @param vToken Address of the vTokens to redeem\n * @param redeemer Account redeeming the tokens\n * @param redeemTokens The number of tokens to redeem\n */\n function _checkRedeemAllowed(address vToken, address redeemer, uint256 redeemTokens) internal {\n Market storage market = markets[vToken];\n\n if (!market.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\n if (!market.accountMembership[redeemer]) {\n return;\n }\n\n // Update the prices of tokens\n updatePrices(redeemer);\n\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n redeemer,\n VToken(vToken),\n redeemTokens,\n 0,\n _getCollateralFactor\n );\n if (snapshot.shortfall > 0) {\n revert InsufficientLiquidity();\n }\n }\n\n /**\n * @notice Get the total collateral, weighted collateral, borrow balance, liquidity, shortfall\n * @param account The account to get the snapshot for\n * @param weight The function to compute the weight of the collateral – either collateral factor or\n * liquidation threshold. Accepts the address of the vToken and returns the weight as Exp.\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\n * without calculating accumulated interest.\n * @return snapshot Account liquidity snapshot\n */\n function _getCurrentLiquiditySnapshot(\n address account,\n function(VToken) internal view returns (Exp memory) weight\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\n return _getHypotheticalLiquiditySnapshot(account, VToken(address(0)), 0, 0, weight);\n }\n\n /**\n * @notice Determine what the supply/borrow balances 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 weight The function to compute the weight of the collateral – either collateral factor or\n liquidation threshold. Accepts the address of the VToken and returns the weight\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\n * without calculating accumulated interest.\n * @return snapshot Account liquidity snapshot\n */\n function _getHypotheticalLiquiditySnapshot(\n address account,\n VToken vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount,\n function(VToken) internal view returns (Exp memory) weight\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\n // For each asset the account is in\n VToken[] memory assets = getAssetsIn(account);\n uint256 assetsCount = assets.length;\n\n for (uint256 i; i < assetsCount; ++i) {\n VToken asset = assets[i];\n\n // Read the balances and exchange rate from the vToken\n (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) = _safeGetAccountSnapshot(\n asset,\n account\n );\n\n // Get the normalized price of the asset\n Exp memory oraclePrice = Exp({ mantissa: _safeGetUnderlyingPrice(asset) });\n\n // Pre-compute conversion factors from vTokens -> usd\n Exp memory vTokenPrice = mul_(Exp({ mantissa: exchangeRateMantissa }), oraclePrice);\n Exp memory weightedVTokenPrice = mul_(weight(asset), vTokenPrice);\n\n // weightedCollateral += weightedVTokenPrice * vTokenBalance\n snapshot.weightedCollateral = mul_ScalarTruncateAddUInt(\n weightedVTokenPrice,\n vTokenBalance,\n snapshot.weightedCollateral\n );\n\n // totalCollateral += vTokenPrice * vTokenBalance\n snapshot.totalCollateral = mul_ScalarTruncateAddUInt(vTokenPrice, vTokenBalance, snapshot.totalCollateral);\n\n // borrows += oraclePrice * borrowBalance\n snapshot.borrows = mul_ScalarTruncateAddUInt(oraclePrice, borrowBalance, snapshot.borrows);\n\n // Calculate effects of interacting with vTokenModify\n if (asset == vTokenModify) {\n // redeem effect\n // effects += tokensToDenom * redeemTokens\n snapshot.effects = mul_ScalarTruncateAddUInt(weightedVTokenPrice, redeemTokens, snapshot.effects);\n\n // borrow effect\n // effects += oraclePrice * borrowAmount\n snapshot.effects = mul_ScalarTruncateAddUInt(oraclePrice, borrowAmount, snapshot.effects);\n }\n }\n\n uint256 borrowPlusEffects = snapshot.borrows + snapshot.effects;\n // These are safe, as the underflow condition is checked first\n unchecked {\n if (snapshot.weightedCollateral > borrowPlusEffects) {\n snapshot.liquidity = snapshot.weightedCollateral - borrowPlusEffects;\n snapshot.shortfall = 0;\n } else {\n snapshot.liquidity = 0;\n snapshot.shortfall = borrowPlusEffects - snapshot.weightedCollateral;\n }\n }\n\n return snapshot;\n }\n\n /**\n * @dev Retrieves price from oracle for an asset and checks it is nonzero\n * @param asset Address for asset to query price\n * @return Underlying price\n */\n function _safeGetUnderlyingPrice(VToken asset) internal view returns (uint256) {\n uint256 oraclePriceMantissa = oracle.getUnderlyingPrice(address(asset));\n if (oraclePriceMantissa == 0) {\n revert PriceError(address(asset));\n }\n return oraclePriceMantissa;\n }\n\n /**\n * @dev Return collateral factor for a market\n * @param asset Address for asset\n * @return Collateral factor as exponential\n */\n function _getCollateralFactor(VToken asset) internal view returns (Exp memory) {\n return Exp({ mantissa: markets[address(asset)].collateralFactorMantissa });\n }\n\n /**\n * @dev Retrieves liquidation threshold for a market as an exponential\n * @param asset Address for asset to liquidation threshold\n * @return Liquidation threshold as exponential\n */\n function _getLiquidationThreshold(VToken asset) internal view returns (Exp memory) {\n return Exp({ mantissa: markets[address(asset)].liquidationThresholdMantissa });\n }\n\n /**\n * @dev Returns supply and borrow balances of user in vToken, reverts on failure\n * @param vToken Market to query\n * @param user Account address\n * @return vTokenBalance Balance of vTokens, the same as vToken.balanceOf(user)\n * @return borrowBalance Borrowed amount, including the interest\n * @return exchangeRateMantissa Stored exchange rate\n */\n function _safeGetAccountSnapshot(\n VToken vToken,\n address user\n ) internal view returns (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) {\n uint256 err;\n (err, vTokenBalance, borrowBalance, exchangeRateMantissa) = vToken.getAccountSnapshot(user);\n if (err != 0) {\n revert SnapshotError(address(vToken), user);\n }\n return (vTokenBalance, borrowBalance, exchangeRateMantissa);\n }\n\n /// @notice Reverts if the call is not from expectedSender\n /// @param expectedSender Expected transaction sender\n function _checkSenderIs(address expectedSender) internal view {\n if (msg.sender != expectedSender) {\n revert UnexpectedSender(expectedSender, msg.sender);\n }\n }\n\n /// @notice Reverts if a certain action is paused on a market\n /// @param market Market to check\n /// @param action Action to check\n function _checkActionPauseState(address market, Action action) private view {\n if (actionPaused(market, action)) {\n revert ActionPaused(market, action);\n }\n }\n}\n" + }, + "contracts/ComptrollerInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.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\n/**\n * @title ComptrollerInterface\n * @author Venus\n * @notice Interface implemented by the `Comptroller` contract.\n */\ninterface ComptrollerInterface {\n /*** Assets You Are In ***/\n\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\n\n function exitMarket(address vToken) external returns (uint256);\n\n /*** Policy Hooks ***/\n\n function preMintHook(address vToken, address minter, uint256 mintAmount) external;\n\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external;\n\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external;\n\n function preRepayHook(address vToken, address borrower) external;\n\n function preLiquidateHook(\n address vTokenBorrowed,\n address vTokenCollateral,\n address borrower,\n uint256 repayAmount,\n bool skipLiquidityCheck\n ) external;\n\n function preSeizeHook(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower\n ) external;\n\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\n\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\n\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\n\n function repayBorrowVerify(\n address vToken,\n address payer,\n address borrower,\n uint repayAmount,\n uint borrowerIndex\n ) external;\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 seizeVerify(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint seizeTokens\n ) external;\n\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\n\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external;\n\n function isComptroller() external view returns (bool);\n\n /*** Liquidity/Liquidation Calculations ***/\n\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 repayAmount\n ) external view returns (uint256, uint256);\n\n function getAllMarkets() external view returns (VToken[] memory);\n\n function actionPaused(address market, Action action) external view returns (bool);\n}\n\n/**\n * @title ComptrollerViewInterface\n * @author Venus\n * @notice Interface implemented by the `Comptroller` contract, including only some util view functions.\n */\ninterface ComptrollerViewInterface {\n function markets(address) external view returns (bool, uint256);\n\n function oracle() external view returns (ResilientOracleInterface);\n\n function getAssetsIn(address) external view returns (VToken[] memory);\n\n function closeFactorMantissa() external view returns (uint256);\n\n function liquidationIncentiveMantissa() external view returns (uint256);\n\n function minLiquidatableCollateral() external view returns (uint256);\n\n function getRewardDistributors() external view returns (RewardsDistributor[] memory);\n\n function getAllMarkets() external view returns (VToken[] memory);\n\n function borrowCaps(address) external view returns (uint256);\n\n function supplyCaps(address) external view returns (uint256);\n\n function approvedDelegates(address user, address delegate) external view returns (bool);\n}\n" + }, + "contracts/ComptrollerStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.sol\";\nimport { IPrime } from \"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\";\nimport { Action } from \"./ComptrollerInterface.sol\";\n\n/**\n * @title ComptrollerStorage\n * @author Venus\n * @notice Storage layout for the `Comptroller` contract.\n */\ncontract ComptrollerStorage {\n struct LiquidationOrder {\n VToken vTokenCollateral;\n VToken vTokenBorrowed;\n uint256 repayAmount;\n }\n\n struct AccountLiquiditySnapshot {\n uint256 totalCollateral;\n uint256 weightedCollateral;\n uint256 borrows;\n uint256 effects;\n uint256 liquidity;\n uint256 shortfall;\n }\n\n struct RewardSpeeds {\n address rewardToken;\n uint256 supplySpeed;\n uint256 borrowSpeed;\n }\n\n struct Market {\n // Whether or not this market is listed\n bool isListed;\n // 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 uint256 collateralFactorMantissa;\n // 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 uint256 liquidationThresholdMantissa;\n // Per-market mapping of \"accounts in this asset\"\n mapping(address => bool) accountMembership;\n }\n\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 Per-account mapping of \"assets you are in\"\n */\n mapping(address => VToken[]) public accountAssets;\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 /// @notice A list of all markets\n VToken[] public allMarkets;\n\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\n mapping(address => uint256) public borrowCaps;\n\n /// @notice Minimal collateral required for regular (non-batch) liquidations\n uint256 public minLiquidatableCollateral;\n\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\n mapping(address => uint256) public supplyCaps;\n\n /// @notice True if a certain action is paused on a certain market\n mapping(address => mapping(Action => bool)) internal _actionPaused;\n\n // List of Reward Distributors added\n RewardsDistributor[] internal rewardsDistributors;\n\n // Used to check if rewards distributor is added\n mapping(address => bool) internal rewardsDistributorExists;\n\n /// @notice Flag indicating whether forced liquidation enabled for a market\n mapping(address => bool) public isForcedLiquidationEnabled;\n\n uint256 internal constant NO_ERROR = 0;\n\n // closeFactorMantissa must be strictly greater than this value\n uint256 internal constant MIN_CLOSE_FACTOR_MANTISSA = 0.05e18; // 0.05\n\n // closeFactorMantissa must not exceed this value\n uint256 internal constant MAX_CLOSE_FACTOR_MANTISSA = 0.9e18; // 0.9\n\n // No collateralFactorMantissa may exceed this value\n uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.95e18; // 0.95\n\n /// Prime token address\n IPrime public prime;\n\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 /**\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[47] private __gap;\n}\n" + }, + "contracts/ErrorReporter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n/**\n * @title TokenErrorReporter\n * @author Venus\n * @notice Errors that can be thrown by the `VToken` contract.\n */\ncontract TokenErrorReporter {\n uint256 public constant NO_ERROR = 0; // support legacy return codes\n\n error TransferNotAllowed();\n\n error MintFreshnessCheck();\n\n error RedeemFreshnessCheck();\n error RedeemTransferOutNotPossible();\n\n error BorrowFreshnessCheck();\n error BorrowCashNotAvailable();\n error DelegateNotApproved();\n\n error RepayBorrowFreshnessCheck();\n\n error HealBorrowUnauthorized();\n error ForceLiquidateBorrowUnauthorized();\n\n error LiquidateFreshnessCheck();\n error LiquidateCollateralFreshnessCheck();\n error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\n error LiquidateLiquidatorIsBorrower();\n error LiquidateCloseAmountIsZero();\n error LiquidateCloseAmountIsUintMax();\n\n error LiquidateSeizeLiquidatorIsBorrower();\n\n error ProtocolSeizeShareTooBig();\n\n error SetReserveFactorFreshCheck();\n error SetReserveFactorBoundsCheck();\n\n error AddReservesFactorFreshCheck(uint256 actualAddAmount);\n\n error ReduceReservesFreshCheck();\n error ReduceReservesCashNotAvailable();\n error ReduceReservesCashValidation();\n\n error SetInterestRateModelFreshCheck();\n}\n" + }, + "contracts/ExponentialNoError.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from \"./lib/constants.sol\";\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 struct Exp {\n uint256 mantissa;\n }\n\n struct Double {\n uint256 mantissa;\n }\n\n uint256 internal constant EXP_SCALE = EXP_SCALE_;\n uint256 internal constant DOUBLE_SCALE = 1e36;\n uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;\n uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;\n\n /**\n * @dev Truncates the given exp to a whole number value.\n * For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15\n */\n function truncate(Exp memory exp) internal pure returns (uint256) {\n // Note: We are not using careful math here as we're performing a division that cannot fail\n return exp.mantissa / EXP_SCALE;\n }\n\n /**\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\n */\n // solhint-disable-next-line func-name-mixedcase\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\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 // solhint-disable-next-line func-name-mixedcase\n function mul_ScalarTruncateAddUInt(Exp memory a, uint256 scalar, uint256 addend) internal pure returns (uint256) {\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 function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\n require(n <= type(uint224).max, errorMessage);\n return uint224(n);\n }\n\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\n require(n <= type(uint32).max, 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_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a + b;\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_(uint256 a, uint256 b) internal pure returns (uint256) {\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) / EXP_SCALE });\n }\n\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\n return Exp({ mantissa: mul_(a.mantissa, b) });\n }\n\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\n return mul_(a, b.mantissa) / EXP_SCALE;\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) / DOUBLE_SCALE });\n }\n\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: mul_(a.mantissa, b) });\n }\n\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\n return mul_(a, b.mantissa) / DOUBLE_SCALE;\n }\n\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a * b;\n }\n\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });\n }\n\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\n return Exp({ mantissa: div_(a.mantissa, b) });\n }\n\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\n return div_(mul_(a, EXP_SCALE), 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, DOUBLE_SCALE), b.mantissa) });\n }\n\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(a.mantissa, b) });\n }\n\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\n return div_(mul_(a, DOUBLE_SCALE), b.mantissa);\n }\n\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a / b;\n }\n\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });\n }\n}\n" + }, + "contracts/InterestRateModel.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n/**\n * @title Compound's InterestRateModel Interface\n * @author Compound\n */\nabstract contract InterestRateModel {\n /**\n * @notice Calculates the current borrow interest rate per slot (block or second)\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 amount of reserves the market has\n * @param badDebt The amount of badDebt in the market\n * @return The borrow rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\n */\n function getBorrowRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) external view virtual returns (uint256);\n\n /**\n * @notice Calculates the current supply interest rate per slot (block or second)\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 amount of reserves the market has\n * @param reserveFactorMantissa The current reserve factor the market has\n * @param badDebt The amount of badDebt in the market\n * @return The supply rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\n */\n function getSupplyRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 reserveFactorMantissa,\n uint256 badDebt\n ) external view virtual returns (uint256);\n\n /**\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\n * @return Always true\n */\n function isInterestRateModel() external pure virtual returns (bool) {\n return true;\n }\n}\n" + }, + "contracts/Lens/PoolLens.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IERC20Metadata } from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { ExponentialNoError } from \"../ExponentialNoError.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { Action, ComptrollerInterface, ComptrollerViewInterface } from \"../ComptrollerInterface.sol\";\nimport { PoolRegistryInterface } from \"../Pool/PoolRegistryInterface.sol\";\nimport { PoolRegistry } from \"../Pool/PoolRegistry.sol\";\nimport { RewardsDistributor } from \"../Rewards/RewardsDistributor.sol\";\nimport { TimeManagerV8 } from \"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\";\n\n/**\n * @title PoolLens\n * @author Venus\n * @notice The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information\n * for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be\n * looked up for specific pools and markets:\n- the vToken balance of a given user;\n- the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address;\n- the vToken address in a pool for a given asset;\n- a list of all pools that support an asset;\n- the underlying asset price of a vToken;\n- the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\n */\ncontract PoolLens is ExponentialNoError, TimeManagerV8 {\n /**\n * @dev Struct for PoolDetails.\n */\n struct PoolData {\n string name;\n address creator;\n address comptroller;\n uint256 blockPosted;\n uint256 timestampPosted;\n string category;\n string logoURL;\n string description;\n address priceOracle;\n uint256 closeFactor;\n uint256 liquidationIncentive;\n uint256 minLiquidatableCollateral;\n VTokenMetadata[] vTokens;\n }\n\n /**\n * @dev Struct for VToken.\n */\n struct VTokenMetadata {\n address vToken;\n uint256 exchangeRateCurrent;\n uint256 supplyRatePerBlockOrTimestamp;\n uint256 borrowRatePerBlockOrTimestamp;\n uint256 reserveFactorMantissa;\n uint256 supplyCaps;\n uint256 borrowCaps;\n uint256 totalBorrows;\n uint256 totalReserves;\n uint256 totalSupply;\n uint256 totalCash;\n bool isListed;\n uint256 collateralFactorMantissa;\n address underlyingAssetAddress;\n uint256 vTokenDecimals;\n uint256 underlyingDecimals;\n uint256 pausedActions;\n }\n\n /**\n * @dev Struct for VTokenBalance.\n */\n struct VTokenBalances {\n address vToken;\n uint256 balanceOf;\n uint256 borrowBalanceCurrent;\n uint256 balanceOfUnderlying;\n uint256 tokenBalance;\n uint256 tokenAllowance;\n }\n\n /**\n * @dev Struct for underlyingPrice of VToken.\n */\n struct VTokenUnderlyingPrice {\n address vToken;\n uint256 underlyingPrice;\n }\n\n /**\n * @dev Struct with pending reward info for a market.\n */\n struct PendingReward {\n address vTokenAddress;\n uint256 amount;\n }\n\n /**\n * @dev Struct with reward distribution totals for a single reward token and distributor.\n */\n struct RewardSummary {\n address distributorAddress;\n address rewardTokenAddress;\n uint256 totalRewards;\n PendingReward[] pendingRewards;\n }\n\n /**\n * @dev Struct used in RewardDistributor to save last updated market state.\n */\n struct RewardTokenState {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block number or timestamp the index was last updated at\n uint256 blockOrTimestamp;\n // The block number or timestamp at which to stop rewards\n uint256 lastRewardingBlockOrTimestamp;\n }\n\n /**\n * @dev Struct with bad debt of a market denominated\n */\n struct BadDebt {\n address vTokenAddress;\n uint256 badDebtUsd;\n }\n\n /**\n * @dev Struct with bad debt total denominated in usd for a pool and an array of BadDebt structs for each market\n */\n struct BadDebtSummary {\n address comptroller;\n uint256 totalBadDebtUsd;\n BadDebt[] badDebts;\n }\n\n /// @notice Address of the core pool comptroller (all markets are returned for this pool, including paused ones)\n address public immutable corePoolComptroller;\n\n /**\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\n * @param blocksPerYear_ The number of blocks per year\n * @param corePoolComptroller_ The address of the core pool comptroller\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor(\n bool timeBased_,\n uint256 blocksPerYear_,\n address corePoolComptroller_\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\n corePoolComptroller = corePoolComptroller_;\n }\n\n /**\n * @notice Queries the user's supply/borrow balances in vTokens\n * @param vTokens The list of vToken addresses\n * @param account The user Account\n * @return A list of structs containing balances data\n */\n function vTokenBalancesAll(VToken[] calldata vTokens, address account) external returns (VTokenBalances[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenBalances[] memory res = new VTokenBalances[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenBalances(vTokens[i], account);\n }\n return res;\n }\n\n /**\n * @notice Queries all pools with addtional details for each of them\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @return Arrays of all Venus pools' data\n */\n function getAllPools(address poolRegistryAddress) external view returns (PoolData[] memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n PoolRegistry.VenusPool[] memory venusPools = poolRegistryInterface.getAllPools();\n uint256 poolLength = venusPools.length;\n\n PoolData[] memory poolDataItems = new PoolData[](poolLength);\n\n for (uint256 i; i < poolLength; ++i) {\n PoolRegistry.VenusPool memory venusPool = venusPools[i];\n PoolData memory poolData = getPoolDataFromVenusPool(poolRegistryAddress, venusPool);\n poolDataItems[i] = poolData;\n }\n\n return poolDataItems;\n }\n\n /**\n * @notice Queries the details of a pool identified by Comptroller address\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param comptroller The Comptroller implementation address\n * @return PoolData structure containing the details of the pool\n */\n function getPoolByComptroller(\n address poolRegistryAddress,\n address comptroller\n ) external view returns (PoolData memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return getPoolDataFromVenusPool(poolRegistryAddress, poolRegistryInterface.getPoolByComptroller(comptroller));\n }\n\n /**\n * @notice Returns vToken holding the specified underlying asset in the specified pool\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param comptroller The pool comptroller\n * @param asset The underlyingAsset of VToken\n * @return Address of the vToken\n */\n function getVTokenForAsset(\n address poolRegistryAddress,\n address comptroller,\n address asset\n ) external view returns (address) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return poolRegistryInterface.getVTokenForAsset(comptroller, asset);\n }\n\n /**\n * @notice Returns all pools that support the specified underlying asset\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param asset The underlying asset of vToken\n * @return A list of Comptroller contracts\n */\n function getPoolsSupportedByAsset(\n address poolRegistryAddress,\n address asset\n ) external view returns (address[] memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return poolRegistryInterface.getPoolsSupportedByAsset(asset);\n }\n\n /**\n * @notice Returns the price data for the underlying assets of the specified vTokens\n * @param vTokens The list of vToken addresses\n * @return An array containing the price data for each asset\n */\n function vTokenUnderlyingPriceAll(\n VToken[] calldata vTokens\n ) external view returns (VTokenUnderlyingPrice[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenUnderlyingPrice[] memory res = new VTokenUnderlyingPrice[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenUnderlyingPrice(vTokens[i]);\n }\n return res;\n }\n\n /**\n * @notice Returns the pending rewards for a user for a given pool.\n * @param account The user account.\n * @param comptrollerAddress address\n * @return Pending rewards array\n */\n function getPendingRewards(\n address account,\n address comptrollerAddress\n ) external view returns (RewardSummary[] memory) {\n VToken[] memory markets = _getMarkets(ComptrollerInterface(comptrollerAddress));\n RewardsDistributor[] memory rewardsDistributors = ComptrollerViewInterface(comptrollerAddress)\n .getRewardDistributors();\n RewardSummary[] memory rewardSummary = new RewardSummary[](rewardsDistributors.length);\n for (uint256 i; i < rewardsDistributors.length; ++i) {\n RewardSummary memory reward;\n reward.distributorAddress = address(rewardsDistributors[i]);\n reward.rewardTokenAddress = address(rewardsDistributors[i].rewardToken());\n reward.totalRewards = rewardsDistributors[i].rewardTokenAccrued(account);\n reward.pendingRewards = _calculateNotDistributedAwards(account, markets, rewardsDistributors[i]);\n rewardSummary[i] = reward;\n }\n return rewardSummary;\n }\n\n /**\n * @notice Returns a summary of a pool's bad debt broken down by market\n *\n * @param comptrollerAddress Address of the comptroller\n *\n * @return badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and\n * a break down of bad debt by market\n */\n function getPoolBadDebt(address comptrollerAddress) external view returns (BadDebtSummary memory) {\n uint256 totalBadDebtUsd;\n\n // Get every listed market in the pool\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\n VToken[] memory markets = _getMarkets(ComptrollerInterface(comptrollerAddress));\n ResilientOracleInterface priceOracle = comptroller.oracle();\n\n BadDebt[] memory badDebts = new BadDebt[](markets.length);\n\n BadDebtSummary memory badDebtSummary;\n badDebtSummary.comptroller = comptrollerAddress;\n badDebtSummary.badDebts = badDebts;\n\n // // Calculate the bad debt is USD per market\n for (uint256 i; i < markets.length; ++i) {\n BadDebt memory badDebt;\n badDebt.vTokenAddress = address(markets[i]);\n badDebt.badDebtUsd =\n (VToken(address(markets[i])).badDebt() * priceOracle.getUnderlyingPrice(address(markets[i]))) /\n EXP_SCALE;\n badDebtSummary.badDebts[i] = badDebt;\n totalBadDebtUsd = totalBadDebtUsd + badDebt.badDebtUsd;\n }\n\n badDebtSummary.totalBadDebtUsd = totalBadDebtUsd;\n\n return badDebtSummary;\n }\n\n /**\n * @notice Queries the user's supply/borrow balances in the specified vToken\n * @param vToken vToken address\n * @param account The user Account\n * @return A struct containing the balances data\n */\n function vTokenBalances(VToken vToken, address account) public returns (VTokenBalances memory) {\n uint256 balanceOf = vToken.balanceOf(account);\n uint256 borrowBalanceCurrent = vToken.borrowBalanceCurrent(account);\n uint256 balanceOfUnderlying = vToken.balanceOfUnderlying(account);\n uint256 tokenBalance;\n uint256 tokenAllowance;\n\n IERC20 underlying = IERC20(vToken.underlying());\n tokenBalance = underlying.balanceOf(account);\n tokenAllowance = underlying.allowance(account, address(vToken));\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 Queries additional information for the pool\n * @param poolRegistryAddress Address of the PoolRegistry\n * @param venusPool The VenusPool Object from PoolRegistry\n * @return Enriched PoolData\n */\n function getPoolDataFromVenusPool(\n address poolRegistryAddress,\n PoolRegistry.VenusPool memory venusPool\n ) public view returns (PoolData memory) {\n // Get tokens in the Pool\n ComptrollerInterface comptrollerInstance = ComptrollerInterface(venusPool.comptroller);\n\n VToken[] memory vTokens = _getMarkets(comptrollerInstance);\n\n VTokenMetadata[] memory vTokenMetadataItems = vTokenMetadataAll(vTokens);\n\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n\n PoolRegistry.VenusPoolMetaData memory venusPoolMetaData = poolRegistryInterface.getVenusPoolMetadata(\n venusPool.comptroller\n );\n\n ComptrollerViewInterface comptrollerViewInstance = ComptrollerViewInterface(venusPool.comptroller);\n\n PoolData memory poolData = PoolData({\n name: venusPool.name,\n creator: venusPool.creator,\n comptroller: venusPool.comptroller,\n blockPosted: venusPool.blockPosted,\n timestampPosted: venusPool.timestampPosted,\n category: venusPoolMetaData.category,\n logoURL: venusPoolMetaData.logoURL,\n description: venusPoolMetaData.description,\n vTokens: vTokenMetadataItems,\n priceOracle: address(comptrollerViewInstance.oracle()),\n closeFactor: comptrollerViewInstance.closeFactorMantissa(),\n liquidationIncentive: comptrollerViewInstance.liquidationIncentiveMantissa(),\n minLiquidatableCollateral: comptrollerViewInstance.minLiquidatableCollateral()\n });\n\n return poolData;\n }\n\n /**\n * @notice Returns the metadata of VToken\n * @param vToken The address of vToken\n * @return VTokenMetadata struct\n */\n function vTokenMetadata(VToken vToken) public view returns (VTokenMetadata memory) {\n uint256 exchangeRateCurrent = vToken.exchangeRateStored();\n address comptrollerAddress = address(vToken.comptroller());\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\n (bool isListed, uint256 collateralFactorMantissa) = comptroller.markets(address(vToken));\n\n address underlyingAssetAddress = vToken.underlying();\n uint256 underlyingDecimals = IERC20Metadata(underlyingAssetAddress).decimals();\n\n uint256 pausedActions;\n for (uint8 i; i <= uint8(type(Action).max); ++i) {\n uint256 paused = ComptrollerInterface(comptrollerAddress).actionPaused(address(vToken), Action(i)) ? 1 : 0;\n pausedActions |= paused << i;\n }\n\n uint256 supplyRatePerBlock;\n\n if (vToken.totalSupply() > 0) {\n supplyRatePerBlock = vToken.supplyRatePerBlock();\n }\n\n return\n VTokenMetadata({\n vToken: address(vToken),\n exchangeRateCurrent: exchangeRateCurrent,\n supplyRatePerBlockOrTimestamp: supplyRatePerBlock,\n borrowRatePerBlockOrTimestamp: vToken.borrowRatePerBlock(),\n reserveFactorMantissa: vToken.reserveFactorMantissa(),\n supplyCaps: comptroller.supplyCaps(address(vToken)),\n borrowCaps: comptroller.borrowCaps(address(vToken)),\n totalBorrows: vToken.totalBorrows(),\n totalReserves: vToken.totalReserves(),\n totalSupply: vToken.totalSupply(),\n totalCash: vToken.getCash(),\n isListed: isListed,\n collateralFactorMantissa: collateralFactorMantissa,\n underlyingAssetAddress: underlyingAssetAddress,\n vTokenDecimals: vToken.decimals(),\n underlyingDecimals: underlyingDecimals,\n pausedActions: pausedActions\n });\n }\n\n /**\n * @notice Returns the metadata of all VTokens\n * @param vTokens The list of vToken addresses\n * @return An array of VTokenMetadata structs\n */\n function vTokenMetadataAll(VToken[] memory vTokens) public view returns (VTokenMetadata[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenMetadata[] memory res = new VTokenMetadata[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenMetadata(vTokens[i]);\n }\n return res;\n }\n\n /**\n * @notice Returns the price data for the underlying asset of the specified vToken\n * @param vToken vToken address\n * @return The price data for each asset\n */\n function vTokenUnderlyingPrice(VToken vToken) public view returns (VTokenUnderlyingPrice memory) {\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(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 Returns markets from a comptroller. For the core pool, all markets are returned.\n * For other pools, markets with zero internalCash are filtered.\n * @param comptroller The comptroller to query\n * @return An array of VToken addresses\n */\n function _getMarkets(ComptrollerInterface comptroller) internal view returns (VToken[] memory) {\n VToken[] memory allMarkets = comptroller.getAllMarkets();\n\n if (address(comptroller) == corePoolComptroller) {\n return allMarkets;\n }\n\n // Single-loop filter: pack active markets to the front of allMarkets\n uint256 count;\n uint256 len = allMarkets.length;\n for (uint256 i; i < len; ++i) {\n if (allMarkets[i].internalCash() > 0) {\n allMarkets[count] = allMarkets[i];\n ++count;\n }\n }\n\n // Trim the array to the active count\n assembly {\n mstore(allMarkets, count)\n }\n\n return allMarkets;\n }\n\n function _calculateNotDistributedAwards(\n address account,\n VToken[] memory markets,\n RewardsDistributor rewardsDistributor\n ) internal view returns (PendingReward[] memory) {\n PendingReward[] memory pendingRewards = new PendingReward[](markets.length);\n\n for (uint256 i; i < markets.length; ++i) {\n // Market borrow and supply state we will modify update in-memory, in order to not modify storage\n RewardTokenState memory borrowState;\n RewardTokenState memory supplyState;\n\n if (isTimeBased) {\n (\n borrowState.index,\n borrowState.blockOrTimestamp,\n borrowState.lastRewardingBlockOrTimestamp\n ) = rewardsDistributor.rewardTokenBorrowStateTimeBased(address(markets[i]));\n (\n supplyState.index,\n supplyState.blockOrTimestamp,\n supplyState.lastRewardingBlockOrTimestamp\n ) = rewardsDistributor.rewardTokenSupplyStateTimeBased(address(markets[i]));\n } else {\n (\n borrowState.index,\n borrowState.blockOrTimestamp,\n borrowState.lastRewardingBlockOrTimestamp\n ) = rewardsDistributor.rewardTokenBorrowState(address(markets[i]));\n (\n supplyState.index,\n supplyState.blockOrTimestamp,\n supplyState.lastRewardingBlockOrTimestamp\n ) = rewardsDistributor.rewardTokenSupplyState(address(markets[i]));\n }\n\n Exp memory marketBorrowIndex = Exp({ mantissa: markets[i].borrowIndex() });\n\n // Update market supply and borrow index in-memory\n updateMarketBorrowIndex(address(markets[i]), rewardsDistributor, borrowState, marketBorrowIndex);\n updateMarketSupplyIndex(address(markets[i]), rewardsDistributor, supplyState);\n\n // Calculate pending rewards\n uint256 borrowReward = calculateBorrowerReward(\n address(markets[i]),\n rewardsDistributor,\n account,\n borrowState,\n marketBorrowIndex\n );\n uint256 supplyReward = calculateSupplierReward(\n address(markets[i]),\n rewardsDistributor,\n account,\n supplyState\n );\n\n PendingReward memory pendingReward;\n pendingReward.vTokenAddress = address(markets[i]);\n pendingReward.amount = borrowReward + supplyReward;\n pendingRewards[i] = pendingReward;\n }\n return pendingRewards;\n }\n\n function updateMarketBorrowIndex(\n address vToken,\n RewardsDistributor rewardsDistributor,\n RewardTokenState memory borrowState,\n Exp memory marketBorrowIndex\n ) internal view {\n uint256 borrowSpeed = rewardsDistributor.rewardTokenBorrowSpeeds(vToken);\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n if (\n borrowState.lastRewardingBlockOrTimestamp > 0 &&\n blockNumberOrTimestamp > borrowState.lastRewardingBlockOrTimestamp\n ) {\n blockNumberOrTimestamp = borrowState.lastRewardingBlockOrTimestamp;\n }\n\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, borrowState.blockOrTimestamp);\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\n // Remove the total earned interest rate since the opening of the market from total borrows\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, borrowSpeed);\n Double memory ratio = borrowAmount > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\n } else if (deltaBlocksOrTimestamp > 0) {\n borrowState.blockOrTimestamp = blockNumberOrTimestamp;\n }\n }\n\n function updateMarketSupplyIndex(\n address vToken,\n RewardsDistributor rewardsDistributor,\n RewardTokenState memory supplyState\n ) internal view {\n uint256 supplySpeed = rewardsDistributor.rewardTokenSupplySpeeds(vToken);\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n if (\n supplyState.lastRewardingBlockOrTimestamp > 0 &&\n blockNumberOrTimestamp > supplyState.lastRewardingBlockOrTimestamp\n ) {\n blockNumberOrTimestamp = supplyState.lastRewardingBlockOrTimestamp;\n }\n\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, supplyState.blockOrTimestamp);\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\n uint256 supplyTokens = VToken(vToken).totalSupply();\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, supplySpeed);\n Double memory ratio = supplyTokens > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\n } else if (deltaBlocksOrTimestamp > 0) {\n supplyState.blockOrTimestamp = blockNumberOrTimestamp;\n }\n }\n\n function calculateBorrowerReward(\n address vToken,\n RewardsDistributor rewardsDistributor,\n address borrower,\n RewardTokenState memory borrowState,\n Exp memory marketBorrowIndex\n ) internal view returns (uint256) {\n Double memory borrowIndex = Double({ mantissa: borrowState.index });\n Double memory borrowerIndex = Double({\n mantissa: rewardsDistributor.rewardTokenBorrowerIndex(vToken, borrower)\n });\n if (borrowerIndex.mantissa == 0 && borrowIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\n // Covers the case where users borrowed tokens before the market's borrow state index was set\n borrowerIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\n }\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\n return borrowerDelta;\n }\n\n function calculateSupplierReward(\n address vToken,\n RewardsDistributor rewardsDistributor,\n address supplier,\n RewardTokenState memory supplyState\n ) internal view returns (uint256) {\n Double memory supplyIndex = Double({ mantissa: supplyState.index });\n Double memory supplierIndex = Double({\n mantissa: rewardsDistributor.rewardTokenSupplierIndex(vToken, supplier)\n });\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\n // Covers the case where users supplied tokens before the market's supply state index was set\n supplierIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\n }\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\n return supplierDelta;\n }\n}\n" + }, + "contracts/lib/constants.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\n/// @dev The approximate number of seconds per year\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\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" + }, + "contracts/lib/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 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" + }, + "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" + }, + "contracts/Pool/PoolRegistry.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\n\nimport { PoolRegistryInterface } from \"./PoolRegistryInterface.sol\";\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { ensureNonzeroAddress } from \"../lib/validators.sol\";\n\n/**\n * @title PoolRegistry\n * @author Venus\n * @notice The Isolated Pools architecture centers around the `PoolRegistry` contract. The `PoolRegistry` maintains a directory of isolated lending\n * pools and can perform actions like creating and registering new pools, adding new markets to existing pools, setting and updating the pool's required\n * metadata, and providing the getter methods to get information on the pools.\n *\n * Isolated lending has three main components: PoolRegistry, pools, and markets. The PoolRegistry is responsible for managing pools.\n * It can create new pools, update pool metadata and manage markets within pools. PoolRegistry contains getter methods to get the details of\n * any existing pool like `getVTokenForAsset` and `getPoolsSupportedByAsset`. It also contains methods for updating pool metadata (`updatePoolMetadata`)\n * and setting pool name (`setPoolName`).\n *\n * The directory of pools is managed through two mappings: `_poolByComptroller` which is a hashmap with the comptroller address as the key and `VenusPool` as\n * the value and `_poolsByID` which is an array of comptroller addresses. Individual pools can be accessed by calling `getPoolByComptroller` with the pool's\n * comptroller address. `_poolsByID` is used to iterate through all of the pools.\n *\n * PoolRegistry also contains a map of asset addresses called `_supportedPools` that maps to an array of assets suppored by each pool. This array of pools by\n * asset is retrieved by calling `getPoolsSupportedByAsset`.\n *\n * PoolRegistry registers new isolated pools in the directory with the `createRegistryPool` method. Isolated pools are composed of independent markets with\n * specific assets and custom risk management configurations according to their markets.\n */\ncontract PoolRegistry is Ownable2StepUpgradeable, AccessControlledV8, PoolRegistryInterface {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n struct AddMarketInput {\n VToken vToken;\n uint256 collateralFactor;\n uint256 liquidationThreshold;\n uint256 initialSupply;\n address vTokenReceiver;\n uint256 supplyCap;\n uint256 borrowCap;\n }\n\n uint256 internal constant MAX_POOL_NAME_LENGTH = 100;\n\n /**\n * @notice Maps pool's comptroller address to metadata.\n */\n mapping(address => VenusPoolMetaData) public metadata;\n\n /**\n * @dev Maps pool ID to pool's comptroller address\n */\n mapping(uint256 => address) private _poolsByID;\n\n /**\n * @dev Total number of pools created.\n */\n uint256 private _numberOfPools;\n\n /**\n * @dev Maps comptroller address to Venus pool Index.\n */\n mapping(address => VenusPool) private _poolByComptroller;\n\n /**\n * @dev Maps pool's comptroller address to asset to vToken.\n */\n mapping(address => mapping(address => address)) private _vTokens;\n\n /**\n * @dev Maps asset to list of supported pools.\n */\n mapping(address => address[]) private _supportedPools;\n\n /**\n * @notice Emitted when a new Venus pool is added to the directory.\n */\n event PoolRegistered(address indexed comptroller, VenusPool pool);\n\n /**\n * @notice Emitted when a pool name is set.\n */\n event PoolNameSet(address indexed comptroller, string oldName, string newName);\n\n /**\n * @notice Emitted when a pool metadata is updated.\n */\n event PoolMetadataUpdated(\n address indexed comptroller,\n VenusPoolMetaData oldMetadata,\n VenusPoolMetaData newMetadata\n );\n\n /**\n * @notice Emitted when a Market is added to the pool.\n */\n event MarketAdded(address indexed comptroller, address indexed vTokenAddress);\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the deployer to owner\n * @param accessControlManager_ AccessControlManager contract address\n */\n function initialize(address accessControlManager_) external initializer {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n }\n\n /**\n * @notice Adds a new Venus pool to the directory\n * @dev Price oracle must be configured before adding a pool\n * @param name The name of the pool\n * @param comptroller Pool's Comptroller contract\n * @param closeFactor The pool's close factor (scaled by 1e18)\n * @param liquidationIncentive The pool's liquidation incentive (scaled by 1e18)\n * @param minLiquidatableCollateral Minimal collateral for regular (non-batch) liquidations flow\n * @return index The index of the registered Venus pool\n * @custom:error ZeroAddressNotAllowed is thrown when Comptroller address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\n */\n function addPool(\n string calldata name,\n Comptroller comptroller,\n uint256 closeFactor,\n uint256 liquidationIncentive,\n uint256 minLiquidatableCollateral\n ) external virtual returns (uint256 index) {\n _checkAccessAllowed(\"addPool(string,address,uint256,uint256,uint256)\");\n // Input validation\n ensureNonzeroAddress(address(comptroller));\n ensureNonzeroAddress(address(comptroller.oracle()));\n\n uint256 poolId = _registerPool(name, address(comptroller));\n\n // Set Venus pool parameters\n comptroller.setCloseFactor(closeFactor);\n comptroller.setLiquidationIncentive(liquidationIncentive);\n comptroller.setMinLiquidatableCollateral(minLiquidatableCollateral);\n\n return poolId;\n }\n\n /**\n * @notice Add a market to an existing pool and then mint to provide initial supply\n * @param input The structure describing the parameters for adding a market to a pool\n * @custom:error ZeroAddressNotAllowed is thrown when vToken address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when vTokenReceiver address is zero\n */\n function addMarket(AddMarketInput memory input) external {\n _checkAccessAllowed(\"addMarket(AddMarketInput)\");\n ensureNonzeroAddress(address(input.vToken));\n ensureNonzeroAddress(input.vTokenReceiver);\n require(input.initialSupply > 0, \"PoolRegistry: initialSupply is zero\");\n\n VToken vToken = input.vToken;\n address vTokenAddress = address(vToken);\n address comptrollerAddress = address(vToken.comptroller());\n Comptroller comptroller = Comptroller(comptrollerAddress);\n address underlyingAddress = vToken.underlying();\n IERC20Upgradeable underlying = IERC20Upgradeable(underlyingAddress);\n\n require(_poolByComptroller[comptrollerAddress].creator != address(0), \"PoolRegistry: Pool not registered\");\n // solhint-disable-next-line reason-string\n require(\n _vTokens[comptrollerAddress][underlyingAddress] == address(0),\n \"PoolRegistry: Market already added for asset comptroller combination\"\n );\n\n comptroller.supportMarket(vToken);\n comptroller.setCollateralFactor(vToken, input.collateralFactor, input.liquidationThreshold);\n\n uint256[] memory newSupplyCaps = new uint256[](1);\n uint256[] memory newBorrowCaps = new uint256[](1);\n VToken[] memory vTokens = new VToken[](1);\n\n newSupplyCaps[0] = input.supplyCap;\n newBorrowCaps[0] = input.borrowCap;\n vTokens[0] = vToken;\n\n comptroller.setMarketSupplyCaps(vTokens, newSupplyCaps);\n comptroller.setMarketBorrowCaps(vTokens, newBorrowCaps);\n\n _vTokens[comptrollerAddress][underlyingAddress] = vTokenAddress;\n _supportedPools[underlyingAddress].push(comptrollerAddress);\n\n uint256 amountToSupply = _transferIn(underlying, msg.sender, input.initialSupply);\n underlying.forceApprove(vTokenAddress, 0);\n underlying.forceApprove(vTokenAddress, amountToSupply);\n vToken.mintBehalf(input.vTokenReceiver, amountToSupply);\n\n emit MarketAdded(comptrollerAddress, vTokenAddress);\n }\n\n /**\n * @notice Modify existing Venus pool name\n * @param comptroller Pool's Comptroller\n * @param name New pool name\n */\n function setPoolName(address comptroller, string calldata name) external {\n _checkAccessAllowed(\"setPoolName(address,string)\");\n _ensureValidName(name);\n VenusPool storage pool = _poolByComptroller[comptroller];\n string memory oldName = pool.name;\n pool.name = name;\n emit PoolNameSet(comptroller, oldName, name);\n }\n\n /**\n * @notice Update metadata of an existing pool\n * @param comptroller Pool's Comptroller\n * @param metadata_ New pool metadata\n */\n function updatePoolMetadata(address comptroller, VenusPoolMetaData calldata metadata_) external {\n _checkAccessAllowed(\"updatePoolMetadata(address,VenusPoolMetaData)\");\n VenusPoolMetaData memory oldMetadata = metadata[comptroller];\n metadata[comptroller] = metadata_;\n emit PoolMetadataUpdated(comptroller, oldMetadata, metadata_);\n }\n\n /**\n * @notice Returns arrays of all Venus pools' data\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\n * @return A list of all pools within PoolRegistry, with details for each pool\n */\n function getAllPools() external view override returns (VenusPool[] memory) {\n uint256 numberOfPools_ = _numberOfPools; // storage load to save gas\n VenusPool[] memory _pools = new VenusPool[](numberOfPools_);\n for (uint256 i = 1; i <= numberOfPools_; ++i) {\n address comptroller = _poolsByID[i];\n _pools[i - 1] = (_poolByComptroller[comptroller]);\n }\n return _pools;\n }\n\n /**\n * @param comptroller The comptroller proxy address associated to the pool\n * @return Returns Venus pool\n */\n function getPoolByComptroller(address comptroller) external view override returns (VenusPool memory) {\n return _poolByComptroller[comptroller];\n }\n\n /**\n * @param comptroller comptroller of Venus pool\n * @return Returns Metadata of Venus pool\n */\n function getVenusPoolMetadata(address comptroller) external view override returns (VenusPoolMetaData memory) {\n return metadata[comptroller];\n }\n\n function getVTokenForAsset(address comptroller, address asset) external view override returns (address) {\n return _vTokens[comptroller][asset];\n }\n\n function getPoolsSupportedByAsset(address asset) external view override returns (address[] memory) {\n return _supportedPools[asset];\n }\n\n /**\n * @dev Adds a new Venus pool to the directory (without checking msg.sender).\n * @param name The name of the pool\n * @param comptroller The pool's Comptroller proxy contract address\n * @return The index of the registered Venus pool\n */\n function _registerPool(string calldata name, address comptroller) internal returns (uint256) {\n VenusPool storage storedPool = _poolByComptroller[comptroller];\n\n require(storedPool.creator == address(0), \"PoolRegistry: Pool already exists in the directory.\");\n _ensureValidName(name);\n\n ++_numberOfPools;\n uint256 numberOfPools_ = _numberOfPools; // cache on stack to save storage read gas\n\n VenusPool memory pool = VenusPool(name, msg.sender, comptroller, block.number, block.timestamp);\n\n _poolsByID[numberOfPools_] = comptroller;\n _poolByComptroller[comptroller] = pool;\n\n emit PoolRegistered(comptroller, pool);\n return numberOfPools_;\n }\n\n function _transferIn(IERC20Upgradeable token, address from, uint256 amount) internal returns (uint256) {\n uint256 balanceBefore = token.balanceOf(address(this));\n token.safeTransferFrom(from, address(this), amount);\n uint256 balanceAfter = token.balanceOf(address(this));\n return balanceAfter - balanceBefore;\n }\n\n function _ensureValidName(string calldata name) internal pure {\n require(bytes(name).length <= MAX_POOL_NAME_LENGTH, \"Pool's name is too large\");\n }\n}\n" + }, + "contracts/Pool/PoolRegistryInterface.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 /**\n * @notice Struct for a Venus interest rate pool metadata.\n */\n struct VenusPoolMetaData {\n string category;\n string logoURL;\n string description;\n }\n\n /// @notice Get all pools in PoolRegistry\n function getAllPools() external view returns (VenusPool[] memory);\n\n /// @notice Get a pool by comptroller address\n function getPoolByComptroller(address comptroller) external view returns (VenusPool memory);\n\n /// @notice Get the address of the VToken contract in the Pool where the underlying token is the provided 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 /// @notice Get the metadata of a Pool by comptroller address\n function getVenusPoolMetadata(address comptroller) external view returns (VenusPoolMetaData memory);\n}\n" + }, + "contracts/Rewards/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\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 { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { TimeManagerV8 } from \"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\";\n\nimport { ExponentialNoError } from \"../ExponentialNoError.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { MaxLoopsLimitHelper } from \"../MaxLoopsLimitHelper.sol\";\nimport { RewardsDistributorStorage } from \"./RewardsDistributorStorage.sol\";\n\n/**\n * @title `RewardsDistributor`\n * @author Venus\n * @notice Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol.\n * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward\n * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool.\n * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward\n * token to be released each slot (block or second) for borrowers and suppliers, which is distributed based on a user’s percentage of the borrows or supplies\n * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting\n * their contributor reward token speed, which similarly allocates a fixed amount of reward token per slot (block or second).\n *\n * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed\n * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized\n * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\n */\ncontract RewardsDistributor is\n ExponentialNoError,\n Ownable2StepUpgradeable,\n AccessControlledV8,\n MaxLoopsLimitHelper,\n RewardsDistributorStorage,\n TimeManagerV8\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice The initial REWARD TOKEN index for a market\n uint224 public constant INITIAL_INDEX = 1e36;\n\n /// @notice Emitted when REWARD TOKEN is distributed to a supplier\n event DistributedSupplierRewardToken(\n VToken indexed vToken,\n address indexed supplier,\n uint256 rewardTokenDelta,\n uint256 rewardTokenTotal,\n uint256 rewardTokenSupplyIndex\n );\n\n /// @notice Emitted when REWARD TOKEN is distributed to a borrower\n event DistributedBorrowerRewardToken(\n VToken indexed vToken,\n address indexed borrower,\n uint256 rewardTokenDelta,\n uint256 rewardTokenTotal,\n uint256 rewardTokenBorrowIndex\n );\n\n /// @notice Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\n event RewardTokenSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /// @notice Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\n event RewardTokenBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /// @notice Emitted when REWARD TOKEN is granted by admin\n event RewardTokenGranted(address indexed recipient, uint256 amount);\n\n /// @notice Emitted when a new REWARD TOKEN speed is set for a contributor\n event ContributorRewardTokenSpeedUpdated(address indexed contributor, uint256 newSpeed);\n\n /// @notice Emitted when a market is initialized\n event MarketInitialized(address indexed vToken);\n\n /// @notice Emitted when a reward token supply index is updated\n event RewardTokenSupplyIndexUpdated(address indexed vToken);\n\n /// @notice Emitted when a reward token borrow index is updated\n event RewardTokenBorrowIndexUpdated(address indexed vToken, Exp marketBorrowIndex);\n\n /// @notice Emitted when a reward for contributor is updated\n event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued);\n\n /// @notice Emitted when a reward token last rewarding block for supply is updated\n event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\n\n /// @notice Emitted when a reward token last rewarding block for borrow is updated\n event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\n\n /// @notice Emitted when a reward token last rewarding timestamp for supply is updated\n event SupplyLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\n\n /// @notice Emitted when a reward token last rewarding timestamp for borrow is updated\n event BorrowLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\n\n modifier onlyComptroller() {\n require(address(comptroller) == msg.sender, \"Only comptroller can call this function\");\n _;\n }\n\n /**\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\n * @param blocksPerYear_ The number of blocks per year\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /**\n * @notice RewardsDistributor initializer\n * @dev Initializes the deployer to owner\n * @param comptroller_ Comptroller to attach the reward distributor to\n * @param rewardToken_ Reward token to distribute\n * @param loopsLimit_ Maximum number of iterations for the loops in this contract\n * @param accessControlManager_ AccessControlManager contract address\n */\n function initialize(\n Comptroller comptroller_,\n IERC20Upgradeable rewardToken_,\n uint256 loopsLimit_,\n address accessControlManager_\n ) external initializer {\n comptroller = comptroller_;\n rewardToken = rewardToken_;\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n\n _setMaxLoopsLimit(loopsLimit_);\n }\n\n /**\n * @notice Initializes the market state for a specific vToken\n * @param vToken The address of the vToken to be initialized\n * @custom:event MarketInitialized emits on success\n * @custom:access Only Comptroller\n */\n function initializeMarket(address vToken) external onlyComptroller {\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n isTimeBased\n ? _initializeMarketTimestampBased(vToken, blockNumberOrTimestamp)\n : _initializeMarketBlockBased(vToken, safe32(blockNumberOrTimestamp, \"block number exceeds 32 bits\"));\n\n emit MarketInitialized(vToken);\n }\n\n /*** Reward Token Distribution ***/\n\n /**\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them\n * Borrowers will begin to accrue after the first interaction with the protocol.\n * @dev This function should only be called when the user has a borrow position in the market\n * (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook)\n * We avoid an external call to check if they are in the market to save gas because this function is called in many places\n * @param vToken The market in which the borrower is interacting\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\n * @param marketBorrowIndex The current global borrow index of vToken\n */\n function distributeBorrowerRewardToken(\n address vToken,\n address borrower,\n Exp memory marketBorrowIndex\n ) external onlyComptroller {\n _distributeBorrowerRewardToken(vToken, borrower, marketBorrowIndex);\n }\n\n function updateRewardTokenSupplyIndex(address vToken) external onlyComptroller {\n _updateRewardTokenSupplyIndex(vToken);\n }\n\n /**\n * @notice Transfer REWARD TOKEN to the recipient\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\n * @param recipient The address of the recipient to transfer REWARD TOKEN to\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\n */\n function grantRewardToken(address recipient, uint256 amount) external onlyOwner {\n uint256 amountLeft = _grantRewardToken(recipient, amount);\n require(amountLeft == 0, \"insufficient rewardToken for grant\");\n emit RewardTokenGranted(recipient, amount);\n }\n\n function updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) external onlyComptroller {\n _updateRewardTokenBorrowIndex(vToken, marketBorrowIndex);\n }\n\n /**\n * @notice Set REWARD TOKEN borrow and supply speeds for the specified markets\n * @param vTokens The markets whose REWARD TOKEN speed to update\n * @param supplySpeeds New supply-side REWARD TOKEN speed for the corresponding market\n * @param borrowSpeeds New borrow-side REWARD TOKEN speed for the corresponding market\n */\n function setRewardTokenSpeeds(\n VToken[] memory vTokens,\n uint256[] memory supplySpeeds,\n uint256[] memory borrowSpeeds\n ) external {\n _checkAccessAllowed(\"setRewardTokenSpeeds(address[],uint256[],uint256[])\");\n uint256 numTokens = vTokens.length;\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \"invalid setRewardTokenSpeeds\");\n\n for (uint256 i; i < numTokens; ++i) {\n _setRewardTokenSpeed(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\n }\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding block for the specified markets, used when contract is block based\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\n * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market\n * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market\n */\n function setLastRewardingBlocks(\n VToken[] calldata vTokens,\n uint32[] calldata supplyLastRewardingBlocks,\n uint32[] calldata borrowLastRewardingBlocks\n ) external {\n _checkAccessAllowed(\"setLastRewardingBlocks(address[],uint32[],uint32[])\");\n require(!isTimeBased, \"Block-based operation only\");\n\n uint256 numTokens = vTokens.length;\n require(\n numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length,\n \"RewardsDistributor::setLastRewardingBlocks invalid input\"\n );\n\n for (uint256 i; i < numTokens; ) {\n _setLastRewardingBlock(vTokens[i], supplyLastRewardingBlocks[i], borrowLastRewardingBlocks[i]);\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding block timestamp for the specified markets, used when contract is time based\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\n * @param supplyLastRewardingBlockTimestamps New supply-side REWARD TOKEN last rewarding block timestamp for the corresponding market\n * @param borrowLastRewardingBlockTimestamps New borrow-side REWARD TOKEN last rewarding block timestamp for the corresponding market\n */\n function setLastRewardingBlockTimestamps(\n VToken[] calldata vTokens,\n uint256[] calldata supplyLastRewardingBlockTimestamps,\n uint256[] calldata borrowLastRewardingBlockTimestamps\n ) external {\n _checkAccessAllowed(\"setLastRewardingBlockTimestamps(address[],uint256[],uint256[])\");\n require(isTimeBased, \"Time-based operation only\");\n\n uint256 numTokens = vTokens.length;\n require(\n numTokens == supplyLastRewardingBlockTimestamps.length &&\n numTokens == borrowLastRewardingBlockTimestamps.length,\n \"RewardsDistributor::setLastRewardingBlockTimestamps invalid input\"\n );\n\n for (uint256 i; i < numTokens; ) {\n _setLastRewardingBlockTimestamp(\n vTokens[i],\n supplyLastRewardingBlockTimestamps[i],\n borrowLastRewardingBlockTimestamps[i]\n );\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Set REWARD TOKEN speed for a single contributor\n * @param contributor The contributor whose REWARD TOKEN speed to update\n * @param rewardTokenSpeed New REWARD TOKEN speed for contributor\n */\n function setContributorRewardTokenSpeed(address contributor, uint256 rewardTokenSpeed) external onlyOwner {\n // note that REWARD TOKEN speed could be set to 0 to halt liquidity rewards for a contributor\n updateContributorRewards(contributor);\n if (rewardTokenSpeed == 0) {\n // release storage\n delete lastContributorBlock[contributor];\n } else {\n lastContributorBlock[contributor] = getBlockNumberOrTimestamp();\n }\n rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed;\n\n emit ContributorRewardTokenSpeedUpdated(contributor, rewardTokenSpeed);\n }\n\n function distributeSupplierRewardToken(address vToken, address supplier) external onlyComptroller {\n _distributeSupplierRewardToken(vToken, supplier);\n }\n\n /**\n * @notice Claim all the rewardToken accrued by holder in all markets\n * @param holder The address to claim REWARD TOKEN for\n */\n function claimRewardToken(address holder) external {\n return claimRewardToken(holder, comptroller.getAllMarkets());\n }\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) external onlyOwner {\n _setMaxLoopsLimit(limit);\n }\n\n /**\n * @notice Calculate additional accrued REWARD TOKEN for a contributor since last accrual\n * @param contributor The address to calculate contributor rewards for\n */\n function updateContributorRewards(address contributor) public {\n uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor];\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, lastContributorBlock[contributor]);\n if (deltaBlocksOrTimestamp > 0 && rewardTokenSpeed > 0) {\n uint256 newAccrued = mul_(deltaBlocksOrTimestamp, rewardTokenSpeed);\n uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued);\n\n rewardTokenAccrued[contributor] = contributorAccrued;\n lastContributorBlock[contributor] = blockNumberOrTimestamp;\n\n emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]);\n }\n }\n\n /**\n * @notice Claim all the rewardToken accrued by holder in the specified markets\n * @param holder The address to claim REWARD TOKEN for\n * @param vTokens The list of markets to claim REWARD TOKEN in\n */\n function claimRewardToken(address holder, VToken[] memory vTokens) public {\n uint256 vTokensCount = vTokens.length;\n\n _ensureMaxLoops(vTokensCount);\n\n for (uint256 i; i < vTokensCount; ++i) {\n VToken vToken = vTokens[i];\n require(comptroller.isMarketListed(vToken), \"market must be listed\");\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\n _distributeBorrowerRewardToken(address(vToken), holder, borrowIndex);\n _updateRewardTokenSupplyIndex(address(vToken));\n _distributeSupplierRewardToken(address(vToken), holder);\n }\n rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]);\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding block for a single market.\n * @param vToken market's whose reward token last rewarding block to be updated\n * @param supplyLastRewardingBlock New supply-side REWARD TOKEN last rewarding block for market\n * @param borrowLastRewardingBlock New borrow-side REWARD TOKEN last rewarding block for market\n */\n function _setLastRewardingBlock(\n VToken vToken,\n uint32 supplyLastRewardingBlock,\n uint32 borrowLastRewardingBlock\n ) internal {\n require(comptroller.isMarketListed(vToken), \"rewardToken market is not listed\");\n\n uint256 blockNumber = getBlockNumberOrTimestamp();\n\n require(supplyLastRewardingBlock > blockNumber, \"setting last rewarding block in the past is not allowed\");\n require(borrowLastRewardingBlock > blockNumber, \"setting last rewarding block in the past is not allowed\");\n\n uint32 currentSupplyLastRewardingBlock = rewardTokenSupplyState[address(vToken)].lastRewardingBlock;\n uint32 currentBorrowLastRewardingBlock = rewardTokenBorrowState[address(vToken)].lastRewardingBlock;\n\n require(\n currentSupplyLastRewardingBlock == 0 || currentSupplyLastRewardingBlock > blockNumber,\n \"this RewardsDistributor is already locked\"\n );\n require(\n currentBorrowLastRewardingBlock == 0 || currentBorrowLastRewardingBlock > blockNumber,\n \"this RewardsDistributor is already locked\"\n );\n\n if (currentSupplyLastRewardingBlock != supplyLastRewardingBlock) {\n rewardTokenSupplyState[address(vToken)].lastRewardingBlock = supplyLastRewardingBlock;\n emit SupplyLastRewardingBlockUpdated(address(vToken), supplyLastRewardingBlock);\n }\n\n if (currentBorrowLastRewardingBlock != borrowLastRewardingBlock) {\n rewardTokenBorrowState[address(vToken)].lastRewardingBlock = borrowLastRewardingBlock;\n emit BorrowLastRewardingBlockUpdated(address(vToken), borrowLastRewardingBlock);\n }\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding timestamp for a single market.\n * @param vToken market's whose reward token last rewarding timestamp to be updated\n * @param supplyLastRewardingBlockTimestamp New supply-side REWARD TOKEN last rewarding timestamp for market\n * @param borrowLastRewardingBlockTimestamp New borrow-side REWARD TOKEN last rewarding timestamp for market\n */\n function _setLastRewardingBlockTimestamp(\n VToken vToken,\n uint256 supplyLastRewardingBlockTimestamp,\n uint256 borrowLastRewardingBlockTimestamp\n ) internal {\n require(comptroller.isMarketListed(vToken), \"rewardToken market is not listed\");\n\n uint256 blockTimestamp = getBlockNumberOrTimestamp();\n\n require(\n supplyLastRewardingBlockTimestamp > blockTimestamp,\n \"setting last rewarding timestamp in the past is not allowed\"\n );\n require(\n borrowLastRewardingBlockTimestamp > blockTimestamp,\n \"setting last rewarding timestamp in the past is not allowed\"\n );\n\n uint256 currentSupplyLastRewardingBlockTimestamp = rewardTokenSupplyStateTimeBased[address(vToken)]\n .lastRewardingTimestamp;\n uint256 currentBorrowLastRewardingBlockTimestamp = rewardTokenBorrowStateTimeBased[address(vToken)]\n .lastRewardingTimestamp;\n\n require(\n currentSupplyLastRewardingBlockTimestamp == 0 || currentSupplyLastRewardingBlockTimestamp > blockTimestamp,\n \"this RewardsDistributor is already locked\"\n );\n require(\n currentBorrowLastRewardingBlockTimestamp == 0 || currentBorrowLastRewardingBlockTimestamp > blockTimestamp,\n \"this RewardsDistributor is already locked\"\n );\n\n if (currentSupplyLastRewardingBlockTimestamp != supplyLastRewardingBlockTimestamp) {\n rewardTokenSupplyStateTimeBased[address(vToken)].lastRewardingTimestamp = supplyLastRewardingBlockTimestamp;\n emit SupplyLastRewardingBlockTimestampUpdated(address(vToken), supplyLastRewardingBlockTimestamp);\n }\n\n if (currentBorrowLastRewardingBlockTimestamp != borrowLastRewardingBlockTimestamp) {\n rewardTokenBorrowStateTimeBased[address(vToken)].lastRewardingTimestamp = borrowLastRewardingBlockTimestamp;\n emit BorrowLastRewardingBlockTimestampUpdated(address(vToken), borrowLastRewardingBlockTimestamp);\n }\n }\n\n /**\n * @notice Set REWARD TOKEN speed for a single market.\n * @param vToken market's whose reward token rate to be updated\n * @param supplySpeed New supply-side REWARD TOKEN speed for market\n * @param borrowSpeed New borrow-side REWARD TOKEN speed for market\n */\n function _setRewardTokenSpeed(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\n require(comptroller.isMarketListed(vToken), \"rewardToken market is not listed\");\n\n if (rewardTokenSupplySpeeds[address(vToken)] != supplySpeed) {\n // Supply speed updated so let's update supply state to ensure that\n // 1. REWARD TOKEN accrued properly for the old speed, and\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\n _updateRewardTokenSupplyIndex(address(vToken));\n\n // Update speed and emit event\n rewardTokenSupplySpeeds[address(vToken)] = supplySpeed;\n emit RewardTokenSupplySpeedUpdated(vToken, supplySpeed);\n }\n\n if (rewardTokenBorrowSpeeds[address(vToken)] != borrowSpeed) {\n // Borrow speed updated so let's update borrow state to ensure that\n // 1. REWARD TOKEN accrued properly for the old speed, and\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\n\n // Update speed and emit event\n rewardTokenBorrowSpeeds[address(vToken)] = borrowSpeed;\n emit RewardTokenBorrowSpeedUpdated(vToken, borrowSpeed);\n }\n }\n\n /**\n * @notice Calculate REWARD TOKEN 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 REWARD TOKEN to\n */\n function _distributeSupplierRewardToken(address vToken, address supplier) internal {\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\n\n uint256 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\n uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier];\n\n // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN\n rewardTokenSupplierIndex[vToken][supplier] = supplyIndex;\n\n if (supplierIndex == 0 && supplyIndex >= INITIAL_INDEX) {\n // Covers the case where users supplied tokens before the market's supply state index was set.\n // Rewards the user with REWARD TOKEN accrued from the start of when supplier rewards were first\n // set for the market.\n supplierIndex = INITIAL_INDEX;\n }\n\n // Calculate change in the cumulative sum of the REWARD TOKEN per vToken accrued\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\n\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\n\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerVToken\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\n\n uint256 supplierAccrued = add_(rewardTokenAccrued[supplier], supplierDelta);\n rewardTokenAccrued[supplier] = supplierAccrued;\n\n emit DistributedSupplierRewardToken(VToken(vToken), supplier, supplierDelta, supplierAccrued, supplyIndex);\n }\n\n /**\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them.\n * @param vToken The market in which the borrower is interacting\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\n * @param marketBorrowIndex The current global borrow index of vToken\n */\n function _distributeBorrowerRewardToken(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\n\n uint256 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\n uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower];\n\n // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN\n rewardTokenBorrowerIndex[vToken][borrower] = borrowIndex;\n\n if (borrowerIndex == 0 && borrowIndex >= INITIAL_INDEX) {\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\n // Rewards the user with REWARD TOKEN accrued from the start of when borrower rewards were first\n // set for the market.\n borrowerIndex = INITIAL_INDEX;\n }\n\n // Calculate change in the cumulative sum of the REWARD TOKEN per borrowed unit accrued\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\n\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\n\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerBorrowedUnit\n if (borrowerAmount != 0) {\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\n\n uint256 borrowerAccrued = add_(rewardTokenAccrued[borrower], borrowerDelta);\n rewardTokenAccrued[borrower] = borrowerAccrued;\n\n emit DistributedBorrowerRewardToken(VToken(vToken), borrower, borrowerDelta, borrowerAccrued, borrowIndex);\n }\n }\n\n /**\n * @notice Transfer REWARD TOKEN to the user.\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all.\n * @param user The address of the user to transfer REWARD TOKEN to\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\n * @return The amount of REWARD TOKEN which was NOT transferred to the user\n */\n function _grantRewardToken(address user, uint256 amount) internal returns (uint256) {\n uint256 rewardTokenRemaining = rewardToken.balanceOf(address(this));\n if (amount > 0 && amount <= rewardTokenRemaining) {\n rewardToken.safeTransfer(user, amount);\n return 0;\n }\n return amount;\n }\n\n /**\n * @notice Accrue REWARD TOKEN to the market by updating the supply index\n * @param vToken The market whose supply index to update\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\n */\n function _updateRewardTokenSupplyIndex(address vToken) internal {\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\n\n uint256 supplySpeed = rewardTokenSupplySpeeds[vToken];\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n if (!isTimeBased) {\n safe32(blockNumberOrTimestamp, \"block number exceeds 32 bits\");\n }\n\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\n ? supplyStateTimeBased.lastRewardingTimestamp\n : uint256(supplyState.lastRewardingBlock);\n\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\n }\n\n uint256 deltaBlocksOrTimestamp = sub_(\n blockNumberOrTimestamp,\n (isTimeBased ? supplyStateTimeBased.timestamp : uint256(supplyState.block))\n );\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\n uint256 supplyTokens = VToken(vToken).totalSupply();\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, supplySpeed);\n Double memory ratio = supplyTokens > 0\n ? fraction(accruedSinceUpdate, supplyTokens)\n : Double({ mantissa: 0 });\n uint224 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\n uint224 index = safe224(\n add_(Double({ mantissa: supplyIndex }), ratio).mantissa,\n \"new index exceeds 224 bits\"\n );\n\n if (isTimeBased) {\n supplyStateTimeBased.index = index;\n supplyStateTimeBased.timestamp = blockNumberOrTimestamp;\n } else {\n supplyState.index = index;\n supplyState.block = uint32(blockNumberOrTimestamp);\n }\n } else if (deltaBlocksOrTimestamp > 0) {\n isTimeBased ? supplyStateTimeBased.timestamp = blockNumberOrTimestamp : supplyState.block = uint32(\n blockNumberOrTimestamp\n );\n }\n\n emit RewardTokenSupplyIndexUpdated(vToken);\n }\n\n /**\n * @notice Accrue REWARD TOKEN to the market by updating the borrow index\n * @param vToken The market whose borrow index to update\n * @param marketBorrowIndex The current global borrow index of vToken\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\n */\n function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\n\n uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken];\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n if (!isTimeBased) {\n safe32(blockNumberOrTimestamp, \"block number exceeds 32 bits\");\n }\n\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\n ? borrowStateTimeBased.lastRewardingTimestamp\n : uint256(borrowState.lastRewardingBlock);\n\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\n }\n\n uint256 deltaBlocksOrTimestamp = sub_(\n blockNumberOrTimestamp,\n (isTimeBased ? borrowStateTimeBased.timestamp : uint256(borrowState.block))\n );\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, borrowSpeed);\n Double memory ratio = borrowAmount > 0\n ? fraction(accruedSinceUpdate, borrowAmount)\n : Double({ mantissa: 0 });\n uint224 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\n uint224 index = safe224(\n add_(Double({ mantissa: borrowIndex }), ratio).mantissa,\n \"new index exceeds 224 bits\"\n );\n\n if (isTimeBased) {\n borrowStateTimeBased.index = index;\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\n } else {\n borrowState.index = index;\n borrowState.block = uint32(blockNumberOrTimestamp);\n }\n } else if (deltaBlocksOrTimestamp > 0) {\n if (isTimeBased) {\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\n } else {\n borrowState.block = uint32(blockNumberOrTimestamp);\n }\n }\n\n emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex);\n }\n\n /**\n * @notice Initializes the market state for a specific vToken called when contract is block-based\n * @param vToken The address of the vToken to be initialized\n * @param blockNumber current block number\n */\n function _initializeMarketBlockBased(address vToken, uint32 blockNumber) internal {\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n RewardToken storage borrowState = rewardTokenBorrowState[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 = INITIAL_INDEX;\n }\n\n if (borrowState.index == 0) {\n // Initialize borrow state index with default value\n borrowState.index = INITIAL_INDEX;\n }\n\n /*\n * Update market state block numbers\n */\n supplyState.block = borrowState.block = blockNumber;\n }\n\n /**\n * @notice Initializes the market state for a specific vToken called when contract is time-based\n * @param vToken The address of the vToken to be initialized\n * @param blockTimestamp current block timestamp\n */\n function _initializeMarketTimestampBased(address vToken, uint256 blockTimestamp) internal {\n TimeBasedRewardToken storage supplyState = rewardTokenSupplyStateTimeBased[vToken];\n TimeBasedRewardToken storage borrowState = rewardTokenBorrowStateTimeBased[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 = INITIAL_INDEX;\n }\n\n if (borrowState.index == 0) {\n // Initialize borrow state index with default value\n borrowState.index = INITIAL_INDEX;\n }\n\n /*\n * Update market state block timestamp\n */\n supplyState.timestamp = borrowState.timestamp = blockTimestamp;\n }\n}\n" + }, + "contracts/Rewards/RewardsDistributorStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\nimport { Comptroller } from \"../Comptroller.sol\";\n\n/**\n * @title RewardsDistributorStorage\n * @author Venus\n * @dev Storage for RewardsDistributor\n */\ncontract RewardsDistributorStorage {\n struct RewardToken {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block number the index was last updated at\n uint32 block;\n // The block number at which to stop rewards\n uint32 lastRewardingBlock;\n }\n\n struct TimeBasedRewardToken {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block timestamp the index was last updated at\n uint256 timestamp;\n // The block timestamp at which to stop rewards\n uint256 lastRewardingTimestamp;\n }\n\n /// @notice The REWARD TOKEN market supply state for each market\n mapping(address => RewardToken) public rewardTokenSupplyState;\n\n /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\n mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex;\n\n /// @notice The REWARD TOKEN accrued but not yet transferred to each user\n mapping(address => uint256) public rewardTokenAccrued;\n\n /// @notice The rate at which rewardToken is distributed to the corresponding borrow market per slot (block or second)\n mapping(address => uint256) public rewardTokenBorrowSpeeds;\n\n /// @notice The rate at which rewardToken is distributed to the corresponding supply market per slot (block or second)\n mapping(address => uint256) public rewardTokenSupplySpeeds;\n\n /// @notice The REWARD TOKEN market borrow state for each market\n mapping(address => RewardToken) public rewardTokenBorrowState;\n\n /// @notice The portion of REWARD TOKEN that each contributor receives per slot (block or second)\n mapping(address => uint256) public rewardTokenContributorSpeeds;\n\n /// @notice Last slot (block or second) at which a contributor's REWARD TOKEN rewards have been allocated\n mapping(address => uint256) public lastContributorBlock;\n\n /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\n mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex;\n\n Comptroller internal comptroller;\n\n IERC20Upgradeable public rewardToken;\n\n /// @notice The REWARD TOKEN market supply state for each market\n mapping(address => TimeBasedRewardToken) public rewardTokenSupplyStateTimeBased;\n\n /// @notice The REWARD TOKEN market borrow state for each market\n mapping(address => TimeBasedRewardToken) public rewardTokenBorrowStateTimeBased;\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[37] private __gap;\n}\n" + }, + "contracts/VToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\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 { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { IProtocolShareReserve } from \"@venusprotocol/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\";\n\nimport { VTokenInterface } from \"./VTokenInterfaces.sol\";\nimport { ComptrollerInterface, ComptrollerViewInterface } from \"./ComptrollerInterface.sol\";\nimport { TokenErrorReporter } from \"./ErrorReporter.sol\";\nimport { InterestRateModel } from \"./InterestRateModel.sol\";\nimport { ExponentialNoError } from \"./ExponentialNoError.sol\";\nimport { TimeManagerV8 } from \"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\";\nimport { ensureNonzeroAddress } from \"./lib/validators.sol\";\n\n/**\n * @title VToken\n * @author Venus\n * @notice Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview,\n * each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of\n * the pool. The main actions a user regularly interacts with in a market are:\n\n- mint/redeem of vTokens;\n- transfer of vTokens;\n- borrow/repay a loan on an underlying asset;\n- liquidate a borrow or liquidate/heal an account.\n\n * A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`.\n * The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted\n * `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken`\n * as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that\n * a user may borrow up to a portion of their collateral determined by the market’s collateral factor. However, if their borrowed amount exceeds an amount\n * calculated using the market’s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also\n * pay off interest accrued on the borrow.\n * \n * The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller`\n * and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a\n * total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`.\n * Both functions settle all of an account’s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of\n * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\n */\ncontract VToken is\n Ownable2StepUpgradeable,\n AccessControlledV8,\n VTokenInterface,\n ExponentialNoError,\n TokenErrorReporter,\n TimeManagerV8\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5%\n\n // Maximum fraction of interest that can be set aside for reserves\n uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18;\n\n // Maximum borrow rate that can ever be applied per slot(block or second)\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n uint256 internal immutable MAX_BORROW_RATE_MANTISSA;\n\n /**\n * Reentrancy Guard **\n */\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 * @param timeBased_ A boolean indicating whether the contract is based on time or block.\n * @param blocksPerYear_ The number of blocks per year\n * @param maxBorrowRateMantissa_ The maximum value of borrowing rate mantissa\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor(\n bool timeBased_,\n uint256 blocksPerYear_,\n uint256 maxBorrowRateMantissa_\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n require(maxBorrowRateMantissa_ <= 1e18, \"Max borrow rate must be <= 1e18\");\n\n MAX_BORROW_RATE_MANTISSA = maxBorrowRateMantissa_;\n _disableInitializers();\n }\n\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_ ERC-20 name of this token\n * @param symbol_ ERC-20 symbol of this token\n * @param decimals_ ERC-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param accessControlManager_ AccessControlManager contract address\n * @param riskManagement Addresses of risk & income related contracts\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\n * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\n */\n function initialize(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address admin_,\n address accessControlManager_,\n RiskManagementInit memory riskManagement,\n uint256 reserveFactorMantissa_\n ) external initializer {\n ensureNonzeroAddress(admin_);\n\n // Initialize the market\n _initialize(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_,\n accessControlManager_,\n riskManagement,\n reserveFactorMantissa_\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 * @return success True if the transfer succeeded, reverts otherwise\n * @custom:event Emits Transfer event on success\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\n * @custom:access Not restricted\n */\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\n _transferTokens(msg.sender, msg.sender, dst, amount);\n return true;\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 success True if the transfer succeeded, reverts otherwise\n * @custom:event Emits Transfer event on success\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\n * @custom:access Not restricted\n */\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\n _transferTokens(msg.sender, src, dst, amount);\n return true;\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 (uint256.max means infinite)\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function approve(address spender, uint256 amount) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n transferAllowances[src][spender] = amount;\n emit Approval(src, spender, amount);\n return true;\n }\n\n /**\n * @notice Increase approval for `spender`\n * @param spender The address of the account which may transfer tokens\n * @param addedValue The number of additional tokens spender can transfer\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function increaseAllowance(address spender, uint256 addedValue) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n uint256 newAllowance = transferAllowances[src][spender];\n newAllowance += addedValue;\n transferAllowances[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n return true;\n }\n\n /**\n * @notice Decreases approval for `spender`\n * @param spender The address of the account which may transfer tokens\n * @param subtractedValue The number of tokens to remove from total approval\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n uint256 currentAllowance = transferAllowances[src][spender];\n require(currentAllowance >= subtractedValue, \"decreased allowance below zero\");\n unchecked {\n currentAllowance -= subtractedValue;\n }\n\n transferAllowances[src][spender] = currentAllowance;\n\n emit Approval(src, spender, currentAllowance);\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 amount The amount of underlying owned by `owner`\n */\n function balanceOfUnderlying(address owner) external override returns (uint256) {\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\n return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\n }\n\n /**\n * @notice Returns the current total borrows plus accrued interest\n * @return totalBorrows The total borrows with interest\n */\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\n accrueInterest();\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 borrowBalance The calculated balance\n */\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\n accrueInterest();\n return _borrowBalanceStored(account);\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function mint(uint256 mintAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _mintFresh(msg.sender, msg.sender, mintAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param minter User whom the supply will be attributed to\n * @param mintAmount The amount of the underlying asset to supply\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when minter address is zero\n */\n function mintBehalf(address minter, uint256 mintAmount) external override nonReentrant returns (uint256) {\n ensureNonzeroAddress(minter);\n\n accrueInterest();\n\n _mintFresh(msg.sender, minter, mintAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\n * @custom:access Not restricted\n */\n function redeem(uint256 redeemTokens) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _redeemFresh(msg.sender, msg.sender, redeemTokens, 0);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function redeemBehalf(address redeemer, uint256 redeemTokens) external override nonReentrant returns (uint256) {\n _ensureSenderIsDelegateOf(redeemer);\n\n accrueInterest();\n\n _redeemFresh(redeemer, msg.sender, redeemTokens, 0);\n return NO_ERROR;\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 receive from redeeming vTokens\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n */\n function redeemUnderlying(uint256 redeemAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _redeemFresh(msg.sender, msg.sender, 0, redeemAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function redeemUnderlyingBehalf(\n address redeemer,\n uint256 redeemAmount\n ) external override nonReentrant returns (uint256) {\n _ensureSenderIsDelegateOf(redeemer);\n\n accrueInterest();\n\n _redeemFresh(redeemer, msg.sender, 0, redeemAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Borrow event; may emit AccrueInterest\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\n * @custom:access Not restricted\n */\n function borrow(uint256 borrowAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _borrowFresh(msg.sender, msg.sender, borrowAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:error DelegateNotApproved is thrown if caller is not approved delegate\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\n * @custom:event Emits Borrow event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function borrowBehalf(address borrower, uint256 borrowAmount) external override returns (uint256) {\n _ensureSenderIsDelegateOf(borrower);\n accrueInterest();\n\n _borrowFresh(borrower, msg.sender, borrowAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function repayBorrow(uint256 repayAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _repayBorrowFresh(msg.sender, msg.sender, repayAmount);\n return NO_ERROR;\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, or type(uint256).max for the full outstanding amount\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _repayBorrowFresh(msg.sender, borrower, repayAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\n * @custom:access Not restricted\n */\n function liquidateBorrow(\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) external override returns (uint256) {\n _liquidateBorrow(msg.sender, borrower, repayAmount, vTokenCollateral, false);\n return NO_ERROR;\n }\n\n /**\n * @notice sets protocol share accumulated from liquidations\n * @dev must be equal or less than liquidation incentive - 1\n * @param newProtocolSeizeShareMantissa_ new protocol share mantissa\n * @custom:event Emits NewProtocolSeizeShare event on success\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:error ProtocolSeizeShareTooBig is thrown when the new seize share is too high\n * @custom:access Controlled by AccessControlManager\n */\n function setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa_) external {\n _checkAccessAllowed(\"setProtocolSeizeShare(uint256)\");\n uint256 liquidationIncentive = ComptrollerViewInterface(address(comptroller)).liquidationIncentiveMantissa();\n if (newProtocolSeizeShareMantissa_ + MANTISSA_ONE > liquidationIncentive) {\n revert ProtocolSeizeShareTooBig();\n }\n\n uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\n protocolSeizeShareMantissa = newProtocolSeizeShareMantissa_;\n emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa_);\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 * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\n * @custom:event Emits NewReserveFactor event; may emit AccrueInterest\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:error SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\n * @custom:access Controlled by AccessControlManager\n */\n function setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant {\n _checkAccessAllowed(\"setReserveFactor(uint256)\");\n\n accrueInterest();\n _setReserveFactorFresh(newReserveFactorMantissa);\n }\n\n /**\n * @notice Accrues interest and reduces reserves by transferring to the protocol reserve contract\n * @dev Gracefully return if reserves already reduced in accrueInterest\n * @param reduceAmount Amount of reduction to reserves\n * @custom:event Emits ReservesReduced event; may emit AccrueInterest\n * @custom:error ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash\n * @custom:error ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\n * @custom:access Not restricted\n */\n function reduceReserves(uint256 reduceAmount) external override nonReentrant {\n accrueInterest();\n if (reduceReservesBlockNumber == getBlockNumberOrTimestamp()) return;\n _reduceReservesFresh(reduceAmount);\n }\n\n /**\n * @notice The sender adds to reserves.\n * @param addAmount The amount of underlying token to add as reserves\n * @custom:event Emits ReservesAdded event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function addReserves(uint256 addAmount) external override nonReentrant {\n accrueInterest();\n _addReservesFresh(addAmount);\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 * @custom:event Emits NewMarketInterestRateModel event; may emit AccrueInterest\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:access Controlled by AccessControlManager\n */\n function setInterestRateModel(InterestRateModel newInterestRateModel) external override {\n _checkAccessAllowed(\"setInterestRateModel(address)\");\n\n accrueInterest();\n _setInterestRateModelFresh(newInterestRateModel);\n }\n\n /**\n * @notice Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially\n * \"forgiving\" the borrower. Healing is a situation that should rarely happen. However, some pools\n * may list risky assets or be configured improperly – we want to still handle such cases gracefully.\n * We assume that Comptroller does the seizing, so this function is only available to Comptroller.\n * @dev This function does not call any Comptroller hooks (like \"healAllowed\"), because we assume\n * the Comptroller does all the necessary checks before calling this function.\n * @param payer account who repays the debt\n * @param borrower account to heal\n * @param repayAmount amount to repay\n * @custom:event Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\n * @custom:error HealBorrowUnauthorized is thrown when the request does not come from Comptroller\n * @custom:access Only Comptroller\n */\n function healBorrow(address payer, address borrower, uint256 repayAmount) external override nonReentrant {\n if (repayAmount != 0) {\n comptroller.preRepayHook(address(this), borrower);\n }\n\n if (msg.sender != address(comptroller)) {\n revert HealBorrowUnauthorized();\n }\n\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n uint256 totalBorrowsNew = totalBorrows;\n\n uint256 actualRepayAmount;\n if (repayAmount != 0) {\n // _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\n // We violate checks-effects-interactions here to account for tokens that take transfer fees\n actualRepayAmount = _doTransferIn(payer, repayAmount);\n totalBorrowsNew = totalBorrowsNew - actualRepayAmount;\n emit RepayBorrow(\n payer,\n borrower,\n actualRepayAmount,\n accountBorrowsPrev - actualRepayAmount,\n totalBorrowsNew\n );\n }\n\n // The transaction will fail if trying to repay too much\n uint256 badDebtDelta = accountBorrowsPrev - actualRepayAmount;\n if (badDebtDelta != 0) {\n uint256 badDebtOld = badDebt;\n uint256 badDebtNew = badDebtOld + badDebtDelta;\n totalBorrowsNew = totalBorrowsNew - badDebtDelta;\n badDebt = badDebtNew;\n\n // We treat healing as \"repayment\", where vToken is the payer\n emit RepayBorrow(address(this), borrower, badDebtDelta, 0, totalBorrowsNew);\n emit BadDebtIncreased(borrower, badDebtDelta, badDebtOld, badDebtNew);\n }\n\n accountBorrows[borrower].principal = 0;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n emit HealBorrow(payer, borrower, repayAmount);\n }\n\n /**\n * @notice The extended version of liquidations, callable only by Comptroller. May skip\n * the close factor check. The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\n * @custom:error ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\n * @custom:access Only Comptroller\n */\n function forceLiquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) external override {\n if (msg.sender != address(comptroller)) {\n revert ForceLiquidateBorrowUnauthorized();\n }\n _liquidateBorrow(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\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 * @custom:event Emits Transfer, ReservesAdded events\n * @custom:error LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:access Not restricted\n */\n function seize(address liquidator, address borrower, uint256 seizeTokens) external override nonReentrant {\n _seize(msg.sender, liquidator, borrower, seizeTokens);\n }\n\n /**\n * @notice Updates bad debt\n * @dev Called only when bad debt is recovered from auction. Updates internal cash balance.\n * @param recoveredAmount_ The amount of bad debt recovered\n * @custom:event Emits BadDebtRecovered event\n * @custom:access Only Shortfall contract\n */\n function badDebtRecovered(uint256 recoveredAmount_) external {\n require(msg.sender == shortfall, \"only shortfall contract can update bad debt\");\n require(recoveredAmount_ <= badDebt, \"more than bad debt recovered from auction\");\n\n uint256 badDebtOld = badDebt;\n uint256 badDebtNew = badDebtOld - recoveredAmount_;\n badDebt = badDebtNew;\n internalCash += recoveredAmount_;\n\n emit BadDebtRecovered(badDebtOld, badDebtNew);\n }\n\n /**\n * @notice Sets protocol share reserve contract address\n * @param protocolShareReserve_ The address of the protocol share reserve contract\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\n * @custom:access Only Governance\n */\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\n _setProtocolShareReserve(protocolShareReserve_);\n }\n\n /**\n * @notice Sets shortfall contract address\n * @param shortfall_ The address of the shortfall contract\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\n * @custom:access Only Governance\n */\n function setShortfallContract(address shortfall_) external onlyOwner {\n _setShortfallContract(shortfall_);\n }\n\n /**\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\n * @param token The address of the ERC-20 token to sweep\n * @custom:access Only Governance\n */\n function sweepToken(IERC20Upgradeable token) external override {\n require(msg.sender == owner(), \"VToken::sweepToken: only admin can sweep tokens\");\n require(address(token) != underlying, \"VToken::sweepToken: can not sweep underlying token\");\n uint256 balance = token.balanceOf(address(this));\n token.safeTransfer(owner(), balance);\n\n emit SweepToken(address(token));\n }\n\n /**\n * @notice Sync internalCash with the actual underlying token balance\n * @dev Used for one-time migration after upgrade to initialize internalCash\n * @custom:event Emits CashSynced\n * @custom:access Controlled by AccessControlManager\n */\n function syncCash() external override nonReentrant {\n _checkAccessAllowed(\"syncCash()\");\n uint256 oldInternalCash = internalCash;\n uint256 actualCash = IERC20Upgradeable(underlying).balanceOf(address(this));\n internalCash = actualCash;\n emit CashSynced(oldInternalCash, actualCash);\n }\n\n /**\n * @notice A public function to set new threshold of slot(block or second) difference after which funds will be sent to the protocol share reserve\n * @param _newReduceReservesBlockOrTimestampDelta slot(block or second) difference value\n * @custom:access Only Governance\n */\n function setReduceReservesBlockDelta(uint256 _newReduceReservesBlockOrTimestampDelta) external {\n _checkAccessAllowed(\"setReduceReservesBlockDelta(uint256)\");\n require(_newReduceReservesBlockOrTimestampDelta > 0, \"Invalid Input\");\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, _newReduceReservesBlockOrTimestampDelta);\n reduceReservesBlockDelta = _newReduceReservesBlockOrTimestampDelta;\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 amount 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 amount 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 error Always NO_ERROR for compatibility with Venus core tooling\n * @return vTokenBalance User's balance of vTokens\n * @return borrowBalance Amount owed in terms of underlying\n * @return exchangeRate Stored exchange rate\n */\n function getAccountSnapshot(\n address account\n )\n external\n view\n override\n returns (uint256 error, uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRate)\n {\n return (NO_ERROR, accountTokens[account], _borrowBalanceStored(account), _exchangeRateStored());\n }\n\n /**\n * @notice Get the internally tracked cash balance of this vToken in the underlying asset\n * @return cash The quantity of underlying asset tracked internally by this contract\n */\n function getCash() external view override returns (uint256) {\n return _getCashPrior();\n }\n\n /**\n * @notice Returns the current per slot(block or second) borrow interest rate for this vToken\n * @return rate The borrow interest rate per slot(block or second), scaled by 1e18\n */\n function borrowRatePerBlock() external view override returns (uint256) {\n return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt);\n }\n\n /**\n * @notice Returns the current per-slot(block or second) supply interest rate for this v\n * @return rate The supply interest rate per slot(block or second), scaled by 1e18\n */\n function supplyRatePerBlock() external view override returns (uint256) {\n return\n interestRateModel.getSupplyRate(\n _getCashPrior(),\n totalBorrows,\n totalReserves,\n reserveFactorMantissa,\n badDebt\n );\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 borrowBalance The calculated balance\n */\n function borrowBalanceStored(address account) external view override returns (uint256) {\n return _borrowBalanceStored(account);\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 exchangeRate Calculated exchange rate scaled by 1e18\n */\n function exchangeRateStored() external view override returns (uint256) {\n return _exchangeRateStored();\n }\n\n /**\n * @notice Accrue interest then return the up-to-date exchange rate\n * @return exchangeRate Calculated exchange rate scaled by 1e18\n */\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\n accrueInterest();\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 slot(block or second)\n * up to the current slot(block or second) and writes new checkpoint to storage and\n * reduce spread reserves to protocol share reserve\n * if currentSlot - reduceReservesBlockNumber >= slotDelta\n * @return Always NO_ERROR\n * @custom:event Emits AccrueInterest event on success\n * @custom:access Not restricted\n */\n function accrueInterest() public virtual override returns (uint256) {\n /* Remember the initial block number or timestamp */\n uint256 currentSlotNumber = getBlockNumberOrTimestamp();\n uint256 accrualSlotNumberPrior = accrualBlockNumber;\n\n /* Short-circuit accumulating 0 interest */\n if (accrualSlotNumberPrior == currentSlotNumber) {\n return NO_ERROR;\n }\n\n /* Read the previous values out of storage */\n uint256 cashPrior = _getCashPrior();\n uint256 borrowsPrior = totalBorrows;\n uint256 reservesPrior = totalReserves;\n uint256 borrowIndexPrior = borrowIndex;\n\n /* Calculate the current borrow interest rate */\n uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt);\n require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, \"borrow rate is absurdly high\");\n\n /* Calculate the number of slots elapsed since the last accrual */\n uint256 slotDelta = currentSlotNumber - accrualSlotNumberPrior;\n\n /*\n * Calculate the interest accumulated into borrows and reserves and the new index:\n * simpleInterestFactor = borrowRate * slotDelta\n * interestAccumulated = simpleInterestFactor * totalBorrows\n * totalBorrowsNew = interestAccumulated + totalBorrows\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\n */\n\n Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), slotDelta);\n uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\n uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;\n uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\n Exp({ mantissa: reserveFactorMantissa }),\n interestAccumulated,\n reservesPrior\n );\n uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the previously calculated values into storage */\n accrualBlockNumber = currentSlotNumber;\n borrowIndex = borrowIndexNew;\n totalBorrows = totalBorrowsNew;\n totalReserves = totalReservesNew;\n\n if (currentSlotNumber - reduceReservesBlockNumber >= reduceReservesBlockDelta) {\n reduceReservesBlockNumber = currentSlotNumber;\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 NO_ERROR;\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 or timestamp\n * @param payer The address of the account which is sending the assets for supply\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 */\n function _mintFresh(address payer, address minter, uint256 mintAmount) internal {\n /* Fail if mint not allowed */\n comptroller.preMintHook(address(this), minter, mintAmount);\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert MintFreshnessCheck();\n }\n\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\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 * `_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 uint256 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 uint256 mintTokens = div_(actualMintAmount, exchangeRate);\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 * And write them into storage\n */\n totalSupply = totalSupply + mintTokens;\n uint256 balanceAfter = accountTokens[minter] + mintTokens;\n accountTokens[minter] = balanceAfter;\n\n /* We emit a Mint event, and a Transfer event */\n emit Mint(minter, actualMintAmount, mintTokens, balanceAfter);\n emit Transfer(address(0), minter, mintTokens);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.mintVerify(address(this), minter, actualMintAmount, mintTokens);\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 Comptroller.updateDelegate)\n * @dev Assumes interest has already been accrued up to the current slot(block or second)\n * @param redeemer The address of the account which is redeeming the tokens\n * @param receiver The receiver of the underlying 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 */\n function _redeemFresh(address redeemer, address receiver, uint256 redeemTokensIn, uint256 redeemAmountIn) internal {\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \"one of redeemTokensIn or redeemAmountIn must be zero\");\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert RedeemFreshnessCheck();\n }\n\n /* exchangeRate = invoke Exchange Rate Stored() */\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\n\n uint256 redeemTokens;\n uint256 redeemAmount;\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 */\n redeemTokens = redeemTokensIn;\n } else {\n /*\n * We get the current exchange rate and calculate the amount to be redeemed:\n * redeemTokens = redeemAmountIn / exchangeRate\n */\n redeemTokens = div_(redeemAmountIn, exchangeRate);\n\n uint256 _redeemAmount = mul_(redeemTokens, exchangeRate);\n if (_redeemAmount != 0 && _redeemAmount != redeemAmountIn) redeemTokens++; // round up\n }\n\n // redeemAmount = exchangeRate * redeemTokens\n redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokens);\n\n // Revert if amount is zero\n if (redeemAmount == 0) {\n revert(\"redeemAmount is zero\");\n }\n\n /* Fail if redeem not allowed */\n comptroller.preRedeemHook(address(this), redeemer, redeemTokens);\n\n /* Fail gracefully if protocol has insufficient cash */\n if (_getCashPrior() - totalReserves < redeemAmount) {\n revert RedeemTransferOutNotPossible();\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We write the previously calculated values into storage.\n * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\n */\n totalSupply = totalSupply - redeemTokens;\n uint256 balanceAfter = accountTokens[redeemer] - redeemTokens;\n accountTokens[redeemer] = balanceAfter;\n\n /*\n * We invoke _doTransferOut for the receiver and the redeemAmount.\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 _doTransferOut(receiver, redeemAmount);\n\n /* We emit a Transfer event, and a Redeem event */\n emit Transfer(redeemer, address(this), redeemTokens);\n emit Redeem(redeemer, redeemAmount, redeemTokens, balanceAfter);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.redeemVerify(address(this), redeemer, redeemAmount, redeemTokens);\n }\n\n /**\n * @notice Users or their delegates borrow assets from the protocol\n * @param borrower User who borrows the assets\n * @param receiver The receiver of the tokens, if called by a delegate\n * @param borrowAmount The amount of the underlying asset to borrow\n */\n function _borrowFresh(address borrower, address receiver, uint256 borrowAmount) internal {\n /* Fail if borrow not allowed */\n comptroller.preBorrowHook(address(this), borrower, borrowAmount);\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert BorrowFreshnessCheck();\n }\n\n /* Fail gracefully if protocol has insufficient underlying cash */\n if (_getCashPrior() - totalReserves < borrowAmount) {\n revert BorrowCashNotAvailable();\n }\n\n /*\n * We calculate the new borrower and total borrow balances, failing on overflow:\n * accountBorrowNew = accountBorrow + borrowAmount\n * totalBorrowsNew = totalBorrows + borrowAmount\n */\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;\n uint256 totalBorrowsNew = totalBorrows + borrowAmount;\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We write the previously calculated values into storage.\n * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\n `*/\n accountBorrows[borrower].principal = accountBorrowsNew;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n /*\n * We invoke _doTransferOut for the receiver and the borrowAmount.\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, accountBorrowsNew, totalBorrowsNew);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\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 underlying tokens being returned, or type(uint256).max for the full outstanding amount\n * @return (uint) the actual repayment amount.\n */\n function _repayBorrowFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256) {\n /* Fail if repayBorrow not allowed */\n comptroller.preRepayHook(address(this), borrower);\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert RepayBorrowFreshnessCheck();\n }\n\n /* We fetch the amount the borrower owes, with accumulated interest */\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n\n uint256 repayAmountFinal = repayAmount >= accountBorrowsPrev ? accountBorrowsPrev : 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 * 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 uint256 actualRepayAmount = _doTransferIn(payer, repayAmountFinal);\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 uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\n uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;\n\n /* We write the previously calculated values into storage */\n accountBorrows[borrower].principal = accountBorrowsNew;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n /* We emit a RepayBorrow event */\n emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.repayBorrowVerify(address(this), payer, borrower, actualRepayAmount, borrowIndex);\n\n return actualRepayAmount;\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n */\n function _liquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) internal nonReentrant {\n accrueInterest();\n\n uint256 error = vTokenCollateral.accrueInterest();\n if (error != NO_ERROR) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\n revert LiquidateAccrueCollateralInterestFailed(error);\n }\n\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\n }\n\n /**\n * @notice The liquidator liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n */\n function _liquidateBorrowFresh(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) internal {\n /* Fail if liquidate not allowed */\n comptroller.preLiquidateHook(\n address(this),\n address(vTokenCollateral),\n borrower,\n repayAmount,\n skipLiquidityCheck\n );\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert LiquidateFreshnessCheck();\n }\n\n /* Verify vTokenCollateral market's slot(block or second) number equals current slot(block or second) number */\n if (vTokenCollateral.accrualBlockNumber() != getBlockNumberOrTimestamp()) {\n revert LiquidateCollateralFreshnessCheck();\n }\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n revert LiquidateLiquidatorIsBorrower();\n }\n\n /* Fail if repayAmount = 0 */\n if (repayAmount == 0) {\n revert LiquidateCloseAmountIsZero();\n }\n\n /* Fail if repayAmount = type(uint256).max */\n if (repayAmount == type(uint256).max) {\n revert LiquidateCloseAmountIsUintMax();\n }\n\n /* Fail if repayBorrow fails */\n uint256 actualRepayAmount = _repayBorrowFresh(liquidator, borrower, repayAmount);\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.liquidateCalculateSeizeTokens(\n address(this),\n address(vTokenCollateral),\n actualRepayAmount\n );\n require(amountSeizeError == 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, call _seize internally to avoid re-entrancy, otherwise make an external call\n if (address(vTokenCollateral) == address(this)) {\n _seize(address(this), liquidator, borrower, seizeTokens);\n } else {\n vTokenCollateral.seize(liquidator, borrower, seizeTokens);\n }\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\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 * It's absolutely critical to use msg.sender as the seizer vToken and not a parameter.\n * @param seizerContract The contract seizing the collateral (either borrowed vToken or Comptroller)\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 */\n function _seize(address seizerContract, address liquidator, address borrower, uint256 seizeTokens) internal {\n /* Fail if seize not allowed */\n comptroller.preSeizeHook(address(this), seizerContract, liquidator, borrower);\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n revert LiquidateSeizeLiquidatorIsBorrower();\n }\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 uint256 liquidationIncentiveMantissa = ComptrollerViewInterface(address(comptroller))\n .liquidationIncentiveMantissa();\n uint256 numerator = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));\n uint256 protocolSeizeTokens = div_(numerator, Exp({ mantissa: liquidationIncentiveMantissa }));\n uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\n uint256 protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the calculated values into storage */\n totalSupply = totalSupply - protocolSeizeTokens;\n accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\n accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\n\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\n _doTransferOut(protocolShareReserve, protocolSeizeAmount);\n\n // Update the pool asset's state in the protocol share reserve for the above transfer.\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\n address(comptroller),\n underlying,\n IProtocolShareReserve.IncomeType.LIQUIDATION\n );\n\n /* Emit a Transfer event */\n emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\n emit ProtocolSeize(borrower, protocolShareReserve, protocolSeizeAmount);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.seizeVerify(address(this), seizerContract, liquidator, borrower, seizeTokens);\n }\n\n function _setComptroller(ComptrollerInterface newComptroller) internal {\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\n /**\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\n * @dev Admin function to set a new reserve factor\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\n */\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal {\n // Verify market's slot(block or second) number equals current slot(block or second) number\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert SetReserveFactorFreshCheck();\n }\n\n // Check newReserveFactor ≤ maxReserveFactor\n if (newReserveFactorMantissa > MAX_RESERVE_FACTOR_MANTISSA) {\n revert SetReserveFactorBoundsCheck();\n }\n\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\n reserveFactorMantissa = newReserveFactorMantissa;\n\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\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 actualAddAmount The actual amount added, excluding the potential token fees\n */\n function _addReservesFresh(uint256 addAmount) internal returns (uint256) {\n // totalReserves + actualAddAmount\n uint256 totalReservesNew;\n uint256 actualAddAmount;\n\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert AddReservesFactorFreshCheck(actualAddAmount);\n }\n\n actualAddAmount = _doTransferIn(msg.sender, addAmount);\n totalReservesNew = totalReserves + actualAddAmount;\n totalReserves = totalReservesNew;\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\n\n return actualAddAmount;\n }\n\n /**\n * @notice Reduces reserves by transferring to the protocol reserve contract\n * @dev Requires fresh interest accrual\n * @param reduceAmount Amount of reduction to reserves\n */\n function _reduceReservesFresh(uint256 reduceAmount) internal {\n if (reduceAmount == 0) {\n return;\n }\n // totalReserves - reduceAmount\n uint256 totalReservesNew;\n\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert ReduceReservesFreshCheck();\n }\n\n // Fail gracefully if protocol has insufficient underlying cash\n if (_getCashPrior() < reduceAmount) {\n revert ReduceReservesCashNotAvailable();\n }\n\n // Check reduceAmount ≤ reserves[n] (totalReserves)\n if (reduceAmount > totalReserves) {\n revert ReduceReservesCashValidation();\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 // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\n _doTransferOut(protocolShareReserve, reduceAmount);\n\n // Update the pool asset's state in the protocol share reserve for the above transfer.\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\n address(comptroller),\n underlying,\n IProtocolShareReserve.IncomeType.SPREAD\n );\n\n emit SpreadReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\n }\n\n /**\n * @notice updates the interest rate model (*requires fresh interest accrual)\n * @dev Admin function to update the interest rate model\n * @param newInterestRateModel the new interest rate model to use\n */\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal {\n // Used to store old model for use in the event that is emitted on success\n InterestRateModel oldInterestRateModel;\n\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert SetInterestRateModelFreshCheck();\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\n /**\n * Safe Token **\n */\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 returns (uint256) {\n IERC20Upgradeable token = IERC20Upgradeable(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 * @param to Receiver of the underlying tokens\n * @param amount Amount of underlying to transfer\n */\n function _doTransferOut(address to, uint256 amount) internal virtual {\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\n internalCash -= amount;\n token.safeTransfer(to, amount);\n }\n\n /**\n * @notice Transfer `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 */\n function _transferTokens(address spender, address src, address dst, uint256 tokens) internal {\n /* Fail if transfer not allowed */\n comptroller.preTransferHook(address(this), src, dst, tokens);\n\n /* Do not allow self-transfers */\n if (src == dst) {\n revert TransferNotAllowed();\n }\n\n /* Get the allowance, infinite for the account owner */\n uint256 startingAllowance;\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 uint256 allowanceNew = startingAllowance - tokens;\n uint256 srcTokensNew = accountTokens[src] - tokens;\n uint256 dstTokensNew = accountTokens[dst] + tokens;\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n\n accountTokens[src] = srcTokensNew;\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\n /**\n * @notice Initialize the 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_ ERC-20 name of this token\n * @param symbol_ ERC-20 symbol of this token\n * @param decimals_ ERC-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param accessControlManager_ AccessControlManager contract address\n * @param riskManagement Addresses of risk & income related contracts\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\n */\n function _initialize(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address admin_,\n address accessControlManager_,\n RiskManagementInit memory riskManagement,\n uint256 reserveFactorMantissa_\n ) internal onlyInitializing {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\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 _setComptroller(comptroller_);\n\n // Initialize slot(block or second) number and borrow index (slot(block or second) number mocks depend on comptroller being set)\n accrualBlockNumber = getBlockNumberOrTimestamp();\n borrowIndex = MANTISSA_ONE;\n\n // Set the interest rate model (depends on slot(block or second) number / borrow index)\n _setInterestRateModelFresh(interestRateModel_);\n\n _setReserveFactorFresh(reserveFactorMantissa_);\n\n name = name_;\n symbol = symbol_;\n decimals = decimals_;\n _setShortfallContract(riskManagement.shortfall);\n _setProtocolShareReserve(riskManagement.protocolShareReserve);\n protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA;\n\n // Set underlying and sanity check it\n underlying = underlying_;\n IERC20Upgradeable(underlying).totalSupply();\n\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\n _notEntered = true;\n _transferOwnership(admin_);\n }\n\n function _setShortfallContract(address shortfall_) internal {\n ensureNonzeroAddress(shortfall_);\n address oldShortfall = shortfall;\n shortfall = shortfall_;\n emit NewShortfallContract(oldShortfall, shortfall_);\n }\n\n function _setProtocolShareReserve(address payable protocolShareReserve_) internal {\n ensureNonzeroAddress(protocolShareReserve_);\n address oldProtocolShareReserve = address(protocolShareReserve);\n protocolShareReserve = protocolShareReserve_;\n emit NewProtocolShareReserve(oldProtocolShareReserve, address(protocolShareReserve_));\n }\n\n function _ensureSenderIsDelegateOf(address user) internal view {\n if (!ComptrollerViewInterface(address(comptroller)).approvedDelegates(user, msg.sender)) {\n revert DelegateNotApproved();\n }\n }\n\n /**\n * @notice Gets the internally tracked cash balance of this market\n * @dev Returns the internalCash state variable, which is updated on transfers in/out\n * @return The quantity of underlying tokens tracked internally by this contract\n */\n function _getCashPrior() internal view virtual returns (uint256) {\n return internalCash;\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 borrowBalance the calculated balance\n */\n function _borrowBalanceStored(address account) internal view returns (uint256) {\n /* Get borrowBalance and borrowIndex */\n BorrowSnapshot memory 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 0;\n }\n\n /* Calculate new borrow balance using the interest index:\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\n */\n uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;\n\n return principalTimesIndex / borrowSnapshot.interestIndex;\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 exchangeRate Calculated exchange rate scaled by 1e18\n */\n function _exchangeRateStored() internal view virtual returns (uint256) {\n uint256 _totalSupply = totalSupply;\n if (_totalSupply == 0) {\n /*\n * If there are no tokens minted:\n * exchangeRate = initialExchangeRate\n */\n return initialExchangeRateMantissa;\n }\n /*\n * Otherwise:\n * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply\n */\n uint256 totalCash = _getCashPrior();\n uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;\n uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply;\n\n return exchangeRate;\n }\n}\n" + }, + "contracts/VTokenInterfaces.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\nimport { ComptrollerInterface } from \"./ComptrollerInterface.sol\";\nimport { InterestRateModel } from \"./InterestRateModel.sol\";\n\n/**\n * @title VTokenStorage\n * @author Venus\n * @notice Storage layout used by the `VToken` contract\n */\n// solhint-disable-next-line max-states-count\ncontract VTokenStorage {\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 uint256 principal;\n uint256 interestIndex;\n }\n\n /**\n * @dev Guard variable for re-entrancy checks\n */\n bool internal _notEntered;\n\n /**\n * @notice Underlying asset for this VToken\n */\n address public underlying;\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 Protocol share Reserve contract address\n */\n address payable public protocolShareReserve;\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 InterestRateModel public interestRateModel;\n\n // Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\n uint256 internal initialExchangeRateMantissa;\n\n /**\n * @notice Fraction of interest currently set aside for reserves\n */\n uint256 public reserveFactorMantissa;\n\n /**\n * @notice Slot(block or second) number that interest was last accrued at\n */\n uint256 public accrualBlockNumber;\n\n /**\n * @notice Accumulator of the total earned interest rate since the opening of the market\n */\n uint256 public borrowIndex;\n\n /**\n * @notice Total amount of outstanding borrows of the underlying in this market\n */\n uint256 public totalBorrows;\n\n /**\n * @notice Total amount of reserves of the underlying held in this market\n */\n uint256 public totalReserves;\n\n /**\n * @notice Total number of tokens in circulation\n */\n uint256 public totalSupply;\n\n /**\n * @notice Total bad debt of the market\n */\n uint256 public badDebt;\n\n // Official record of token balances for each account\n mapping(address => uint256) internal accountTokens;\n\n // Approved token transfer amounts on behalf of others\n mapping(address => mapping(address => uint256)) internal transferAllowances;\n\n // Mapping of account addresses to outstanding borrow balances\n mapping(address => BorrowSnapshot) internal accountBorrows;\n\n /**\n * @notice Share of seized collateral that is added to reserves\n */\n uint256 public protocolSeizeShareMantissa;\n\n /**\n * @notice Storage of Shortfall contract address\n */\n address public shortfall;\n\n /**\n * @notice delta slot (block or second) after which reserves will be reduced\n */\n uint256 public reduceReservesBlockDelta;\n\n /**\n * @notice last slot (block or second) number at which reserves were reduced\n */\n uint256 public reduceReservesBlockNumber;\n\n /**\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\n * @dev Updated via _doTransferIn(), _doTransferOut(), syncCash(), and badDebtRecovered(). Must be initialized via syncCash() 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[47] private __gap;\n}\n\n/**\n * @title VTokenInterface\n * @author Venus\n * @notice Interface implemented by the `VToken` contract\n */\nabstract contract VTokenInterface is VTokenStorage {\n struct RiskManagementInit {\n address shortfall;\n address payable protocolShareReserve;\n }\n\n /*** Market Events ***/\n\n /**\n * @notice Event emitted when interest is accrued\n */\n event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\n\n /**\n * @notice Event emitted when tokens are minted\n */\n event Mint(address indexed minter, uint256 mintAmount, uint256 mintTokens, uint256 accountBalance);\n\n /**\n * @notice Event emitted when tokens are redeemed\n */\n event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens, uint256 accountBalance);\n\n /**\n * @notice Event emitted when underlying is borrowed\n */\n event Borrow(address indexed borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\n\n /**\n * @notice Event emitted when a borrow is repaid\n */\n event RepayBorrow(\n address indexed payer,\n address indexed borrower,\n uint256 repayAmount,\n uint256 accountBorrows,\n uint256 totalBorrows\n );\n\n /**\n * @notice Event emitted when bad debt is accumulated on a market\n * @param borrower borrower to \"forgive\"\n * @param badDebtDelta amount of new bad debt recorded\n * @param badDebtOld previous bad debt value\n * @param badDebtNew new bad debt value\n */\n event BadDebtIncreased(address indexed borrower, uint256 badDebtDelta, uint256 badDebtOld, uint256 badDebtNew);\n\n /**\n * @notice Event emitted when bad debt is recovered via an auction\n * @param badDebtOld previous bad debt value\n * @param badDebtNew new bad debt value\n */\n event BadDebtRecovered(uint256 badDebtOld, uint256 badDebtNew);\n\n /**\n * @notice Event emitted when a borrow is liquidated\n */\n event LiquidateBorrow(\n address indexed liquidator,\n address indexed borrower,\n uint256 repayAmount,\n address indexed vTokenCollateral,\n uint256 seizeTokens\n );\n\n /*** Admin Events ***/\n\n /**\n * @notice Event emitted when comptroller is changed\n */\n event NewComptroller(ComptrollerInterface indexed oldComptroller, ComptrollerInterface indexed newComptroller);\n\n /**\n * @notice Event emitted when shortfall contract address is changed\n */\n event NewShortfallContract(address indexed oldShortfall, address indexed newShortfall);\n\n /**\n * @notice Event emitted when protocol share reserve contract address is changed\n */\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\n\n /**\n * @notice Event emitted when interestRateModel is changed\n */\n event NewMarketInterestRateModel(\n InterestRateModel indexed oldInterestRateModel,\n InterestRateModel indexed newInterestRateModel\n );\n\n /**\n * @notice Event emitted when protocol seize share is changed\n */\n event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\n\n /**\n * @notice Event emitted when the reserve factor is changed\n */\n event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\n\n /**\n * @notice Event emitted when the reserves are added\n */\n event ReservesAdded(address indexed benefactor, uint256 addAmount, uint256 newTotalReserves);\n\n /**\n * @notice Event emitted when the spread reserves are reduced\n */\n event SpreadReservesReduced(address indexed protocolShareReserve, uint256 reduceAmount, uint256 newTotalReserves);\n\n /**\n * @notice EIP20 Transfer event\n */\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n /**\n * @notice EIP20 Approval event\n */\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /**\n * @notice Event emitted when healing the borrow\n */\n event HealBorrow(address indexed payer, address indexed borrower, uint256 repayAmount);\n\n /**\n * @notice Event emitted when tokens are swept\n */\n event SweepToken(address indexed token);\n\n /**\n * @notice Event emitted when reduce reserves slot (block or second) delta is changed\n */\n event NewReduceReservesBlockDelta(\n uint256 oldReduceReservesBlockOrTimestampDelta,\n uint256 newReduceReservesBlockOrTimestampDelta\n );\n\n /**\n * @notice Event emitted when liquidation reserves are reduced\n */\n event ProtocolSeize(address indexed from, address indexed to, uint256 amount);\n\n /**\n * @notice Event emitted when internalCash is synced with actual token balance\n */\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\n\n /*** User Interface ***/\n\n function mint(uint256 mintAmount) external virtual returns (uint256);\n\n function mintBehalf(address minter, uint256 mintAllowed) external virtual returns (uint256);\n\n function redeem(uint256 redeemTokens) external virtual returns (uint256);\n\n function redeemBehalf(address redeemer, uint256 redeemTokens) external virtual returns (uint256);\n\n function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);\n\n function redeemUnderlyingBehalf(address redeemer, uint256 redeemAmount) external virtual returns (uint256);\n\n function borrow(uint256 borrowAmount) external virtual returns (uint256);\n\n function borrowBehalf(address borrwwer, uint256 borrowAmount) external virtual returns (uint256);\n\n function repayBorrow(uint256 repayAmount) external virtual returns (uint256);\n\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);\n\n function liquidateBorrow(\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) external virtual returns (uint256);\n\n function healBorrow(address payer, address borrower, uint256 repayAmount) external virtual;\n\n function forceLiquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipCloseFactorCheck\n ) external virtual;\n\n function seize(address liquidator, address borrower, uint256 seizeTokens) external virtual;\n\n function transfer(address dst, uint256 amount) external virtual returns (bool);\n\n function transferFrom(address src, address dst, uint256 amount) external virtual returns (bool);\n\n function accrueInterest() external virtual returns (uint256);\n\n function sweepToken(IERC20Upgradeable token) external virtual;\n\n /*** Admin Functions ***/\n\n function setReserveFactor(uint256 newReserveFactorMantissa) external virtual;\n\n function reduceReserves(uint256 reduceAmount) external virtual;\n\n function exchangeRateCurrent() external virtual returns (uint256);\n\n function borrowBalanceCurrent(address account) external virtual returns (uint256);\n\n function setInterestRateModel(InterestRateModel newInterestRateModel) external virtual;\n\n function addReserves(uint256 addAmount) external virtual;\n\n function syncCash() external virtual;\n\n function totalBorrowsCurrent() external virtual returns (uint256);\n\n function balanceOfUnderlying(address owner) external virtual returns (uint256);\n\n function approve(address spender, uint256 amount) external virtual returns (bool);\n\n function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool);\n\n function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool);\n\n function allowance(address owner, address spender) external view virtual returns (uint256);\n\n function balanceOf(address owner) external view virtual returns (uint256);\n\n function getAccountSnapshot(address account) external view virtual returns (uint256, uint256, uint256, uint256);\n\n function borrowRatePerBlock() external view virtual returns (uint256);\n\n function supplyRatePerBlock() external view virtual returns (uint256);\n\n function borrowBalanceStored(address account) external view virtual returns (uint256);\n\n function exchangeRateStored() external view virtual returns (uint256);\n\n function getCash() external view virtual returns (uint256);\n\n /**\n * @notice Indicator that this is a VToken contract (for inspection)\n * @return Always true\n */\n function isVToken() external pure virtual returns (bool) {\n return true;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200, + "details": { + "yul": true + } + }, + "evmVersion": "paris", + "outputSelection": { + "*": { + "*": [ + "storageLayout", + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} diff --git a/deployments/unichainmainnet_addresses.json b/deployments/unichainmainnet_addresses.json index bc149380c..75bbff150 100644 --- a/deployments/unichainmainnet_addresses.json +++ b/deployments/unichainmainnet_addresses.json @@ -15,7 +15,7 @@ "JumpRateModelV2_base0bps_slope900bps_jump20000bps_kink4500bps_timeBased": "0xf781f2D923f37F4dD10c3541D8A1Be04571e7966", "JumpRateModelV2_base0bps_slope900bps_jump30000bps_kink4500bps_timeBased": "0xc2edB1e96e45178b901618B96142C2743Ed0e7B3", "NativeTokenGateway_vWETH_Core": "0x4441aE3bCEd3210edbA35d0F7348C493E79F1C52", - "PoolLens": "0xe192aeDBDBd235DBF33Ea1444f2B908Ea3E78419", + "PoolLens": "0x667fcCdAdF4fAFe22DbE80440A43d180f64d469a", "PoolRegistry": "0x0C52403E16BcB8007C1e54887E1dFC1eC9765D7C", "PoolRegistry_Implementation": "0xBAb8c229B6C19c443b942F228B076Ca0d4f2260E", "PoolRegistry_Proxy": "0x0C52403E16BcB8007C1e54887E1dFC1eC9765D7C", diff --git a/deployments/zksyncmainnet.json b/deployments/zksyncmainnet.json index 5e346e911..1a1423e01 100644 --- a/deployments/zksyncmainnet.json +++ b/deployments/zksyncmainnet.json @@ -5012,7 +5012,7 @@ ] }, "PoolLens": { - "address": "0x69FC4232959131B4992597B739cEC97Ee898aA68", + "address": "0x437afd23d8929c382e0CBED30bf7a0A4310C8071", "abi": [ { "inputs": [ @@ -5025,6 +5025,11 @@ "internalType": "uint256", "name": "blocksPerYear_", "type": "uint256" + }, + { + "internalType": "address", + "name": "corePoolComptroller_", + "type": "address" } ], "stateMutability": "nonpayable", @@ -5053,6 +5058,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "corePoolComptroller", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { diff --git a/deployments/zksyncmainnet/PoolLens.json b/deployments/zksyncmainnet/PoolLens.json index ef67f2fa3..f1b4486b7 100644 --- a/deployments/zksyncmainnet/PoolLens.json +++ b/deployments/zksyncmainnet/PoolLens.json @@ -1,5 +1,5 @@ { - "address": "0x69FC4232959131B4992597B739cEC97Ee898aA68", + "address": "0x437afd23d8929c382e0CBED30bf7a0A4310C8071", "abi": [ { "inputs": [ @@ -12,6 +12,11 @@ "internalType": "uint256", "name": "blocksPerYear_", "type": "uint256" + }, + { + "internalType": "address", + "name": "corePoolComptroller_", + "type": "address" } ], "stateMutability": "nonpayable", @@ -40,6 +45,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "corePoolComptroller", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -1168,107 +1186,107 @@ "type": "function" } ], - "transactionHash": "0xfac1fd7b98aa5cfb77cd0d27e86ed268b5e7a61d733943cea154d8801e490f6e", + "transactionHash": "0x34c60e6149487852ea51a994b1f6b49dfd33e3c7d64f6955014b95324f66b53b", "receipt": { "to": "0x0000000000000000000000000000000000008006", - "from": "0x7f423E50147930e197dAaE9F637198E66746D597", - "contractAddress": "0x69FC4232959131B4992597B739cEC97Ee898aA68", - "transactionIndex": 4, - "gasUsed": "16396148", - "logsBloom": "0x00008000000400080000010000000000000000000000400000000000000000000000000000000000000000000001000000000000000000000000000000000008000100000000040000000028000040000400000000000000000000000000080000000000020100000000000000000840000400000000400000000010000000200000001000200000000004000100000000000100000000001000000000000080800000000000100040000000800100000000000000000000002000010000000000000002008400000000000000000000000014000100000000000000000020000000000000000000000000000000000000000040000000400000000080008000", - "blockHash": "0x00c8980923ce93732373f6e10773875b41b98308271c9d301738a75662fba4ed", - "transactionHash": "0xfac1fd7b98aa5cfb77cd0d27e86ed268b5e7a61d733943cea154d8801e490f6e", + "from": "0xF39495A0AbcD780C367E6abA747dB98DD54187bC", + "contractAddress": "0x437afd23d8929c382e0CBED30bf7a0A4310C8071", + "transactionIndex": 0, + "gasUsed": "7301137", + "logsBloom": "0x20000000000400080000010000000000000001000000400000000000000000000000000000000000000000040001000200000000000000000000000000000000000100000000040000000068000140000400000000000000000000000000080000000000021100000000000000000800000000000000400000000010000000000000001000000000000004000100000000000100000000000000000000000080800400000000100000000000800100000000000000000200002000010000000000800002008000000000000000000000000010000100000000000000000020000000000000000000400000000000000000000040000000000000000080000200", + "blockHash": "0x15cb1c4093e40af087567a3e66834d93f6f5ea7ad9873a798693bdc29d641895", + "transactionHash": "0x34c60e6149487852ea51a994b1f6b49dfd33e3c7d64f6955014b95324f66b53b", "logs": [ { - "transactionIndex": 4, - "blockNumber": 43551227, - "transactionHash": "0xfac1fd7b98aa5cfb77cd0d27e86ed268b5e7a61d733943cea154d8801e490f6e", + "transactionIndex": 0, + "blockNumber": 69333566, + "transactionHash": "0x34c60e6149487852ea51a994b1f6b49dfd33e3c7d64f6955014b95324f66b53b", "address": "0x000000000000000000000000000000000000800A", "topics": [ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", - "0x0000000000000000000000007f423e50147930e197daae9f637198e66746d597", + "0x000000000000000000000000f39495a0abcd780c367e6aba747db98dd54187bc", "0x0000000000000000000000000000000000000000000000000000000000008001" ], - "data": "0x0000000000000000000000000000000000000000000000000004e4eb6141eac0", - "logIndex": 19, - "blockHash": "0x00c8980923ce93732373f6e10773875b41b98308271c9d301738a75662fba4ed" + "data": "0x00000000000000000000000000000000000000000000000000018b47c53cddb0", + "logIndex": 0, + "blockHash": "0x15cb1c4093e40af087567a3e66834d93f6f5ea7ad9873a798693bdc29d641895" }, { - "transactionIndex": 4, - "blockNumber": 43551227, - "transactionHash": "0xfac1fd7b98aa5cfb77cd0d27e86ed268b5e7a61d733943cea154d8801e490f6e", + "transactionIndex": 0, + "blockNumber": 69333566, + "transactionHash": "0x34c60e6149487852ea51a994b1f6b49dfd33e3c7d64f6955014b95324f66b53b", "address": "0x0000000000000000000000000000000000008008", "topics": ["0x27fe8c0b49f49507b9d4fe5968c9f49edfe5c9df277d433a07a0717ede97638d"], - "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000040c0000000000000000000000000000000000000000000000000000000000008008000000000000000000000000000000000000000000000000000000000000800e9293ab8e8d8b79759e1042f6522f359682d5e936bb2ea419718f9c1b1840c4de", - "logIndex": 20, - "blockHash": "0x00c8980923ce93732373f6e10773875b41b98308271c9d301738a75662fba4ed" + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000011a0000000000000000000000000000000000000000000000000000000000008008000000000000000000000000000000000000000000000000000000000000800e81ab79931254247e2306df2cd153721f24a11132c70d9e1b4fa3538e13e80121", + "logIndex": 1, + "blockHash": "0x15cb1c4093e40af087567a3e66834d93f6f5ea7ad9873a798693bdc29d641895" }, { - "transactionIndex": 4, - "blockNumber": 43551227, - "transactionHash": "0xfac1fd7b98aa5cfb77cd0d27e86ed268b5e7a61d733943cea154d8801e490f6e", + "transactionIndex": 0, + "blockNumber": 69333566, + "transactionHash": "0x34c60e6149487852ea51a994b1f6b49dfd33e3c7d64f6955014b95324f66b53b", "address": "0x0000000000000000000000000000000000008008", "topics": [ "0x3a36e47291f4201faf137fab081d92295bce2d53be2c6ca68ba82c7faa9ce241", "0x000000000000000000000000000000000000000000000000000000000000800e", - "0x9293ab8e8d8b79759e1042f6522f359682d5e936bb2ea419718f9c1b1840c4de" + "0x81ab79931254247e2306df2cd153721f24a11132c70d9e1b4fa3538e13e80121" ], - "data": "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000c2ba0c500000000000000000000000200030008c000005790000213d000000000701034f0000000008980436000000007907043c0000000100200190000000400200043d000006070000213d000000000403401900000020040000392e152e100000040f000000000048004b0000000008020019000000000462001900020000000103550000006003300270000000000301001900000b86033001970000001f0530018f00000b88063001980000001f01400039000006070000413d0000000000650435000000000003001f000000000686019f00000000080504330000000001010433000000600110018f0000004001100210000000040020008c000000000004043500000b8601000041000000000058004b000006630000613d00000b8a011001c70000001f07400190000006630000013d000000000606043b00000000067601cf000000000676022f0000010007700089000000000878022f00000000087801cf0000000307700210000000000661034f00000b860100804100000b860010009c00000020064001900000000000020435000000000606043300000000002104350000000002020433000000400010043f000000400020043f00000b860020009c00000b860200804100000b860040009c000000000006004b000006070000c13d00000b8604008041000000000400041400000000001204350000000001000414000000000101043b00001d6c0000a13d000000000113019f000000c003400210000000c001100210000005790000c13d000001000200043d00000ba70010009c0000000003030433000000000707043b00000000066701cf000000000767022f0000010006600089000000000868022f00000000086801cf0000000306600210000000000771034f0000001f0640018f000000000112019f000000000059004b0000000009a90436000000008a08043c000000000801034f000000200740019000000bb6011001c700000ba70020009c000000a00100043d000000000003043500002e1700010430000000000001004b0000000002000039000000000032043500000000080a0019000000000005004b0000001d0200002900000b8600a0009c0000000000670435000000400100043d00000000070704330000001b0d000029000000600e000039000000c002200210000000000200041400000001020040390000001f01000029000000000014043500000000056a001900000000000104350000000000340435000000400040043f0000001f020000290000004000b0043f00000b8600b0009c00000000003104350000242b0000213d00000ba700b0009c000000000300003100000000010a401900000000020b04330000004002200210000000000078043500002a6f0000213d0000001c020000290000001c01000029000000000121019f000000400300043d00000baa0020009c00002a800000613d0000000c05000029000000000001042d000000000131019f0000004003300210000000000012004b00000000002a043500000000010b401900000ba70040009c000000000021004b000000000100041600002a800000013d00002a6d0000413d000000000024043500000b86030000410000001e020000290000000002050019000000000002004b000000000003004bffffffffffffffff00000000090b001900000000057b0019000024310000213d00000000006c0435000000040050008c00000000090c001900000000057c001900000b8600c0009c0000001b020000290000001d0a00002900000000002b043500000bb601000041000000040010043f000000000010043f00000bdc0100004100000000020000190000001e01000029000000000041004b000000000252016f00000baa022001970000001f0220017f000001000100043d0000000005050433000000000031004b000000400030043f0000000000420435000000000604043300002e160001042e00000baa0010009c00000baa06600197000000000004004b000000040130037000000000010c4019000000000bc1001900000baa0110019700000ba700c0009c0000001f040000290000000000230435000000000161019f0000010005500089000000000656022f00000000065601cf00000b860030009c00000020011000390000002002200039000000200100002900000000050000190000004000c0043f000000000cb10019000000600030008c0000000002a10019000000400a00043d0000000003000019000000000035043500000bff0110019700000000015101cf000000000151022f00000b860030019d00000ba70050009c00000000010000390000004000a0043f00000ba70070009c000000400210003900000000020c0433000000000010044300001d720000c13d00000000006b043500000000000604350000001e0a0000290000001a02000029000000400500043d000000600210018f00000ba700a0009c000000000201043300000000010000190000000000560435000000000043043500000020020000290000001d01000029001d00000002001d000000000042004b000000040040008c00000000002c043500000bcb0020009c00000000056800190000001a010000290000001c0a00002900000100033000890000000000e10435000000000032004b00000bc20010009c000000200010008c00000003055002100000000008180436000000007107043c0000000000450435000000000400001900000bad0030009c00000b860300804100002cff0000213d00000bcb0010009c000000000404043300001d720000413d00000b860050009c0000000009090433000000a00200043d000000150200002900000000040000390000000004020433000000600400003900000020040000290000000000510435000000200310003900000040031000390000006001300210000000000161034f001e0000000103530000000100100190000000010100403900000ba70080009c000000000024004b0000001f01300039000000200200003900002d4e0000613d00000006050000290000247a0000613d000024310000413d0000242b0000c13d00000019020000290000001b080000290000001b010000290000004001200039000000200cc00039001c00000001001d000000e00110018f000000400030008c00000000030a401900000020043000390000001802000029000000000300003900000000000704350000001a0300002900000bbb011001c70000001f050000290000006002100039000000800210003900000000080b001900000000056b00190000002002100039001e00000002001d00000000000504350000004101000039000000400400043d0000000006000019000000000454043600000ba70060009c0000000001000412000000440040008c00000baa0030009c000000007807043c000000240040008c00002d4e0000013d00002d050000413d0000247a0000013d0000001e0700035f00001ead0000613d00000b88061001980000001f0510018f00000000002504350000001b0500002900001e440000613d0000001b021000290000001b0560002900000000009804350000001d0020006c000000000015004b000000000d0d043300000018040000290000001c080000290000000000130435000000200120003900000060012000390000000001020433000000000c0000190000000100400190000000010400403900000000001b004b0000006006400190000000000014004b000000400900043d0000001c030000290000000001a100190000000402a00039001c00000002001d000000a002100039000000c002100039000000010330003900000000020a0433000000000ba10019000000000ab100190000000502300210001f00000003001d0000000000150435000000400050043f000000000008004b00000000080000190000000007000019000000000052004b000000040010008c000000000071004b0000000005020433000000000026004b000000400070043f0000000006050433000000c001300210000000000045004b0000000008080433000000000009004b002000000001001d000000000105034f0000000003000414000001200010043f00000024013003700000000105500039000000000202043b000000070400002900002a6d0000213d000025680000213d00000002050000290000000b050000290000000c0a000029000024310000c13d0000001f0030008c000600000002001d000000000151019f00001ead0000013d000000000001042f00000bd9020000410000001c0560002900000bcb0030009c000000200450003900000bc60010009c00000bc60020009c001b00000004001d000000200770003900000000000a004b00000bff066001970000001701000029001a00000001001d0000001f0000002f000000000363019f00000000033701cf000000000737022f000000000708043b000000000636022f00000000063601cf0000000303700210000000000861034f0000000008380436000000007307043c0000001a08000029001700000001001d0000008001200039001500000001001d00000016020000290000001801000029000000ff0110018f00000014020000290000000d02000029000000120200002900000040011000390000001c0500002900000bef020000410000004004000039001d00000001001d00000000001a0435000000e0021000390000022002100039000000400430003900000060043000390000008004300039000000a004300039000000c0043000390000003f021000390000000501100210000a00000001001d0000000b010000290000001f018000390000000303500210000000000249001900000b860090009c00000080031000390000006003100039000000170200002900000baa03300197000000a00310003900000016060000290000000402b000392e152e0b0000040f0000000001b10019000000200500002900000bb40010009c000005790000013d000000000023004b000001400430003900000000090000190000004004100039000000000027004b0000012002100039000000000057004b000000c0024002100000001e0500002900000bae0100404100000bae01100197000001000440008900000bff04300198000000000064004b0000018001100039001e00000001001d0000001f0630018f0000006001100210000000000007004b00000baa0050009c0000004007600039000000200440003900000019010000290000002004200039000000000404043b00000bff0aa00197002000000002001d000000000035004b00000040022000390000000002210436000000000223034f000006070000813d0200000200000000ffffffffffffffe000000000ffffffff00002dc40000a13d000300000002001d0000000e0b000029000e0000000b001d0000000106000029000000020b00002900020000000b001d000100000006001d000000020c00002900020000000c001d000500000002001d000000400c00043d0000000501000029000024250000a13d00000009020000290000000901000029000400000001001d0000001f05500039000000000645001900000000097600190000000008470019000000000445001900000bff055001970000016003100039000000004301043400000032010000390000002002400039000000010300c0390000800b0200003900000bce011001c700000bcd0100004100000bcf01000041000000020010008c000000010010008c0000000004510019000000000305401900000000040a0019001800000002001d0000001e01200029000080050200003900000bc4011001c70000002400100443000000040010044300000ba50100004100000bc30010009c00000ba802200197001b00000005001d00000017040000290000001f0010006c0000006004200039000000400600043d0000001d050000290000000001054019001800000004001d0000000005a10019001a00000005001d0000001e040000290000000001050433000000000102043600000000069600190000001f06a0003900000000069a00190000000000ac004b0000000000d60435000000000dcb001900000000069c00190000000009a6043600000000060c0433000000010220003900000000010340190000001a05600029001600000001001d000000040200002900000019030000290000003f01100039000000000103c01900000bae03008041000000000535022f00000000030940190000000201000367000000050200002900000006010000290000020001100039000000a00110003900000011020000290000000404a00039001400000002001d001900000004001d00000bed02000041001500000002001d0000000002050433000001000210003900000140021000390000018002100039000001a00210003900000beb0010009c000000e0043000390000010004300039000001200430003900000160043000390000018004300039000001a004300039000001c004300039000001e0043000390000020004300039000002200430003900000beb0030009c0000000a03000029000000010030019000000001030040390000000a01000029000b00000002001d000000000291001900000000013101cf000000000131022f000000000029043500000000020404330000001304000029001300000001001d0000001b03000029000000c003100039000000000054043500000000004b043500000be70400004100000b860200004100000000001b0435000000400b00043d0000006005100039000006710000013d000001200200043d000001200110003900000bae0900804100000000014101cf000000000141022f000000000141034f000000070300002900000ba70090009c00000bae0090009c00000bad0010009c000000000602043300000bae04008041001c00000004001d0000002005500039000000400080043f000000000901034f000000000545022f00000000054501cf0000000304500210000000000054004b0000014002200039000000000061043500000bae0080009c000001200120003900000bff02100197000000000052043500000000050404330000000305600210000000000989043600000bff05300198000000000401043300000000033204360000000002210019000000400060043f00000ba8066001972e1525b60000040f000000010100c0390000008007600039000000600760003900000baa07700197000000000223043600000baa0040009c00000000076700190000004001000039000000800020043f000000a00010043f2e152ded0000040f00000ba502000041000000050440021000000000040004150000004403000039000080050100003900000bbc010000410000006001000039000000000201043b0000000006860436000000e0011000390000000000760435000002180000613d0000001c01200029000000050210021000000004021000390000002302100039000000400090043f00000044000000007fffffffffffffff0000000400000000000000010200003900002dca0000213d0000000000460435000700000003001d0000000402c000390007000000000002000400000002001d0000000f0220017f000000200700003900000bf00600004100002a6d0000c13d0000000f0210017f0000000f0c000029000f0000000c001d00002a6f0000c13d00000000030b4019000000000251016f0000000005010019000025a30000613d0000000404c0003900000000004c0435000025660000413d000025660000213d000000010c00002900010000000c001d000200000005001d00000baa051001970000000a02000029000000040300002900000003030000290000000503000029000000050b00002900050000000b001d00000000001c04350000000602000029000800000001001d0000000000a2043500000bff077001970000001f0740003900000000077a0019000000000028004b000000200bb000390000000000dc0435000000000cab0019000000000b0000190000000002930019000900000002001d0000000007870436000000006806043c0000000007090019000000000601034f000500000001001d00000000650504340000000006240049000000a00710003900000baa05500197000001c004200039000001a004200039000001a00310003900000180031000390000014003100039000001200310003900000100031000390000008004200039000000400420003900000000053501cf00000051010000390000001a0a000029000000000062043500000017050000290000000401500039000000000112004b000000000201001900000bcb00a0009c00000000010a00190000001c04000029000000160300002900001ebd0000813d00000bd40020009c000000130300003900000bd3040000410000002001300039000000000021001a00000bc60330019700000bd20010009c00001e450000613d0000000003020433001600000004001d00000000040160190000000000230170000000010200203900001e4b0000c13d000000040250003900000015050000290000001508000029001500000005001d0000001b040000290000004004400039000000000104043300000040055000390000000402300039001b00000003001d000000000426001900000000011200190000000501400210000000a002200039000000000089043500000000070c0433000000000754001900000020076000390000001d0010006b0000000404500039000000200a000029001d00000000001d00000000009a004b000000010600c03900000000060000390000002008800039000000000a000019000000000095043500000000ba0904340000000000ab0435000000000a560049000000000b0b0433000000000956004900000000009a04350000000802000029000000080010006c00000020032000390000000001320019001400000001001d001200000001001d0000000001060433000000000038004b0000001f0150003900000000980804340000000001bc001900000bae00a0009c0000001f019000390000006006200039000000200700008a000000040290003900000bf8020000410000000a0030006c000000e00200043d000001e002200039000000c00100043d000001c002200039000000800100043d000001a00220003900000013020000290000016001100039000001400110003900000100011000390000000e02000029000000c0011000390000000f0200002900000080011000390000006001100039000000ff0020008c000000800000043f00000bf70200004100000bd702000041000d00000002001d00000bf602000041000e00000002001d00000bd00200004100000bf502000041000f00000002001d0000001e0220017f00000bf40200004100000bf302000041001100000002001d00000bf20200004100000bf102000041000000000a0b0019000000e00020043f000000000224019f000000e00400043d000000010400c039001c00000005001d0000002401a00039000000e00000043f000000c00010043f000000ff0010008c000000c00000043f00000bb9010000410000001e0210017f00000bee01000041001e00000004001d001600000003001d0000001f0210017f00000bec01000041000001000010043f00000baa010000410000016002100039000001c002100039000001e0021000390000020002100039001f0baa0020019b001a00000003001d000000000034004b000000002101043400000bae0060009c0000000003090019000000000434022f00000000043401cf0000001f05800190000000000609001900000baa021001970000016003200039000000a001200039000000c001200039000000e00120003900000bea0020009c00000007010000290000000000cb043500000bff0ee00197000000000e00001900000ba700d0009c0000001403000029001c00000000001d0000001405000029000000000008043500000040087000390000001d0900002900000000007204350000000002060019000000040060008c000000170a00002900170000000a001d00000bb90200004100000bb80200004100000bb70200004100000bb501000041000001200100043d0000000404b000390000001b0a000029001b0000000a001d00000be50400004100000000001a004b0000001b0b000029001b0000000b001d00000000020b4019002000000005001d000000000501043b0000000101100367000000200510003900000040051000390000008005100039000000c005100039000006700000613d00000020041000390000000008a80436000000000076004b00000020066000390000000000a90435000000000a0a043300000000053500190000003f0990003900000bff099001970000001f097000390000000087070434000000000809c01900000bae00b0009c00000bae0800404100000bae0a60019700000bae08800197000000000068004b0000001f087000390000000008070433000002190000013d00000020030000290000000004210019001b00000001001d000000010050019000000001050040390000000005000039000700000001001d0000001f05a0018f0000003f04100039000000000074004b00000000002704350000000501200210000000000204c01900000bae0200404100000bae022001970000001f02100039000000000709034f000000000871013f000000000051004b000000000646022f000000000641034f0000012006000039000001200240003900000bbd011001c700000baa0060009c000001400440003900000bae05004041000000000075004b00000bae0550019700000bae06008041000001200400043d00000ba90020009c00000be50100004100000bae0070009c00000bae06200197000000000151034f000000000049004b0000004003200039000000200300003900000baf01000041000002c009000039000000600820003900000000008704350000000087060434000001200050043f00000120014000390000001801200029001900000002001d0000000001210049000000000423034f0000003f0aa00039000000000046004b00000ba6011001c7001f00000001001d0000002402300370000001400000043f0000018009000039000000000301043b000000000303043b0000000005010433000000000703034f000000e0015000390000000006620436000000007606043400000000460404340000014004000039000001200300043d000001200040043f0000003f012000390000012009000039000000000301034f965b047b8b0138944e20a0fbe8993556b41c9ffac27b9733de74f27c00b5ac0affffffffffffff40fffffffffffffde0ffffffffffffffc0fffffffffffffe60fffffffffffffe3f0000000000000001fffffffffffffe9fdb5c65de000000004ada90af00000000e875544600000000a3aefa2c000000003b1d21a2000000008f840ddd000000004a5844320000000002c3bcbb00000000173b990400000000f8f9da2800000000ae9d70b000000000e85a296000000000313ce567000000008e8f294b000000005fe3b56700000000182df0f500000000fffffffffffffddffffffffffffffe5f000000000000003fd88ff1f400000000fc57d4df00000000bbcac557000000007dc0d1d000000000fffffffffffffe7f0000000400000180ffffffffffffff5ffffffffffffffd3f00000024000002c07aee632d000000000000004400000120266e0a7f000000004e487b7100000000552c09710000000095dd919300000000160c3a03000000006dfd08ca0000000018160ddd0000000074c4c1cc0000000008c379a00000000000000001000000006f7773000000000078206f766572666c6e657720696e6465b34b9f100000000000c097ce7bc907150de0b6b3a764000047bd3718000000003c209e9336465bd123bf29dc2df74b6f266b0e7a08c0454b42cbb15ccdc3cad608cc6b5d955391325d622183e25ac5afcd93958e4c903827796b89b91644bc987c05a7c500000000ffffffffffffffdfaa5af0fd0000000092a18235000000002c427b570000000081814945000000008f693ec700000000ffffffffffffff9fffffffffffffffbf1627ee8900000000f7c618c100000000ffffffffffffff7f61252fd1000000000000000400000120b0772d0b00000000dd62ed3e000000006f307dc3000000003af9e6690000000017bfdfbc00000000000000240000000070a0823100000000ffffffffffffff3ffffffffffffffe1f00000040000000000000022000000000000000c000000000000000200000012080000000000000000000002400000120f36dba3800000000fffffffffffffedf0000002000000000ab882de59d99a32eff553aecb10793d015d089f94afb7896310ab089e4439a4c000000001f884fdf000000000d3ae318000000003e3e399c00000000345954dc00000000345954db0000000055dd95150000000047d86a81000000007a27db57000000006857249c000000006857249b0000000047d86a80000000007c84e3b3000000007c51b64200000000b312423900000000aa5dbd2300000000aa5dbd2200000000d77ebf9600000000c7ad089500000000e1d146fb00000000e0a67f1100000000e0a67f1000000000c7ad0894000000007c51b64100000100000001000000000200000000ae0fcab3000000000000000001e1338009c8f7ec0000000000000000ffffffe000000001ffffffe000002e150000043200002e130021042300002e0e0021042100002e0a0000613d00000c04011001c700002df30000413d000000000161043a0000000006060031000000050660027000000000066400190000000506200210000000040100003900002dfb0000413d000000050030008c000000000020044300002de50000613d00002ddb0000013d00002de60000c13d00002dd80000613d000000000105001900002da90000413d000000050030006c00000006026000290000000301200029000000040100002900002d7b0000413d00002dc20000613d000000000625043600002dca0000c13d000000000225001900002dca0000813d00000bfd0010009c00002d5b0000613d00002d4a0000c13d00002d3e0000c13d00002d320000c13d00002d260000c13d00002d1a0000c13d00002d0e0000c13d000000020700002900002d430000613d00002cdd0000613d00002ccc0000c13d00002cd00000613d000000070b00002900070000000b001d000200000007001d00002ce50000613d0000000406b0003900000bba040000410000002404b00039000000010200002900002d370000613d00002c9a0000613d00002c890000c13d00002c8d0000613d000100000002001d00002ca20000613d0000000406c0003900000bb50400004100002d050000213d00002d2b0000613d00002c580000613d00002c470000c13d00002c4b0000613d00002c5f0000613d00002d1f0000613d00002c1a0000613d00002c090000c13d00002c0d0000613d000000030c00002900030000000c001d00002c210000613d00002d130000613d00002bd90000613d00002bc80000c13d00002bcc0000613d000000040b00002900040000000b001d00002be00000613d00002d050000a13d00002cff0000c13d00002d070000613d00002b930000613d00002b820000c13d00002b860000613d000000050c00002900050000000c001d00002b980000013d00002b690000c13d000600000005001d00000baa0320019700000000003c043500000bb50300004100002cff0000813d00000c030030009c00002b420000c13d00002b360000c13d00002b2a0000c13d00002b1e0000c13d00002b120000c13d00002b060000c13d00002afa0000c13d00002aee0000c13d00002ae20000c13d00002ad60000c13d00002aca0000c13d00002abe0000c13d00002ab20000c13d00002aa60000c13d00002a9a0000c13d00002a8d0000613d00002a7c0000c13d0000000b0110017f0000000302000029000000070200002900002b3b0000613d00002a0e0000613d000029fd0000c13d00002a010000613d00002a160000613d00002b2f0000613d000029cf0000613d000029be0000c13d000029c20000613d000029d60000613d00002b230000613d000029900000613d0000297f0000c13d000029830000613d000000030b00002900030000000b001d000029970000613d00002b170000613d000029510000613d000029400000c13d000029440000613d000000040c00002900040000000c001d000029580000613d00002b0b0000613d000029120000613d000029010000c13d000029050000613d000029190000613d00002aff0000613d000028d30000613d000028c20000c13d000028c60000613d000028da0000613d00002af30000613d000028900000613d0000287f0000c13d000028830000613d000000060b00002900060000000b001d000028970000613d000700000002001d00000000020d0433000000000bd1001900002ae70000613d0000284d0000613d0000283c0000c13d00000000090d0019000028400000613d00000000057d0019000000070d00002900070000000d001d00000000010d401900000b8600d0009c000028540000613d00000000002d04350000004000d0043f000000000dc1001900002adb0000613d0000280e0000613d000027fd0000c13d000028010000613d0000000d0c000029000d0000000c001d000028150000613d00002acf0000613d000027cf0000613d000027be0000c13d000027c20000613d000027d60000613d000027450000a13d000000080080008c000000ff0820018f000000010280003900000000028201cf0000000d0800002900002a750000613d0000277b0000613d0000276a0000c13d0000276e0000613d0000000e0a000029000e0000000a001d000d00000008001d000027830000613d0000000004070019000000000152016f000000000081043500000000006a043500000000010b043300002ac30000613d0000272f0000613d0000271e0000c13d000027220000613d000027360000613d0000000b0220017f00002ab70000613d000026ee0000613d000026dd0000c13d000026e10000613d0000000e0c000029000e0000000c001d00000000030c4019000026f30000013d000026c50000c13d0000000d0600002900002aab0000613d000026a50000613d000026940000c13d000026980000613d0000006007400190000d00000006001d000026ab0000013d0000267b0000c13d000000000151016f00000000061b0436000f00000001001d00000000010c043300002a9f0000613d0000265b0000613d0000264a0000c13d0000264e0000613d000026620000613d000a00000002001d00002a6d0000a13d00000000001c004b00002a930000613d000026170000613d000026060000c13d0000260a0000613d0000000f0b000029000f0000000b001d0000261c0000013d000025ee0000c13d000c00000005001d00002a6f0000813d00000c020010009c000f000000000002000025b00000613d0000259f0000c13d000025a30000013d000025930000c13d000025860000613d000025750000c13d000025790000613d0000000001c10019000025980000613d000025500000613d0000253f0000c13d000025430000613d000025570000613d0000258c0000613d000025100000613d000024ff0000c13d000025030000613d000000010b00002900010000000b001d000025170000613d000025660000a13d000025680000c13d0000256e0000613d000024cd0000613d000024bc0000c13d000024c00000613d000024d20000013d000024a30000c13d000025680000813d00000c010020009c0002000000000002000024870000613d000024760000c13d0000246a0000c13d0000245e0000c13d000024520000c13d000024460000c13d0000243a0000c13d000000080300002900000006030000290000000d0400002900000bea0010009c0000246f0000613d000023ed0000613d000023dc0000c13d000023e00000613d000023f60000613d00000bfb02000041000024630000613d000023ae0000613d0000239d0000c13d000023a10000613d000023b60000613d00000bfa02000041000024570000613d0000236f0000613d0000235e0000c13d000023620000613d000023770000613d00000bf9020000410000244b0000613d000023290000613d000023180000c13d0000231c0000613d000000060c00002900060000000c001d00000000020c40190000232f0000013d000022ff0000c13d000b00000005001d00000baa05200197000900000001001d000300000001001d0000000002470019000022d60000413d00000000096200190000000008720019000022dd0000613d000c0000000a001d000000000864001900000000074a04360000000100800190000000010800403900000000080000390000000000a7004b0000003f077000390000000064040434000000000608c01900000bae06004041000000000067004b000000000967013f00000bae0770019700000bae0800804100000000044700190000004007400039000022a10000413d00000000007b004b000000000d8b0019000022a80000613d00000000002b004b000000000b870019000000000a7904360000000100b00190000000010b004039000000000b000039000000000aa9001900000bff0a900197000000000a68013f000000000747001900000000055104360000000008a800190000226e0000413d00000000008b004b000000000d9b0019000022750000613d000000800a10003900000000002a004b000000000a9800190000000000850435000000000a5a00190000001f0a800039000000000a09c01900000bae0a00404100000000006a004b000000000b6a013f0000001f0680003900000000084600190000000076040434000000600050008c00000bad0050009c00000000054200490000000004940019000000000409043300000000019200190000222c0000613d0000221b0000c13d0000221f0000613d0000000c090000290000243f0000613d000c00000009001d000022150000013d000022020000c13d000021d80000413d0000000d010000290000000b0250002900000007050000290000000c03000029000c00000003001d0000000801200029000700000005001d000021ab0000413d0000000004520019000021f20000613d0000000005320436000d00000003001d00000000022300190000218a0000413d0000000014010434000021960000813d0000000003130019000800000004001d0000000a050000290000000904000029000000090440002900000ba8044001970000003f04300039000000050330021000000ba70030009c000a00000003001d0000000013010434000000000304c01900000bae03004041000000000053004b000000000653013f00000bae0520019700000bae033001970000001f0310003900000000019100190000000001090433000024310000a13d000021500000613d0000213f0000c13d000021430000613d0000000d09000029000024330000613d000d00000009001d000021390000013d000021260000c13d0000000000190435000000000231043600000060030000390000242b0000813d00000c000010009c000d0000000000020000000002030433000000000112043600000000310104340000208f0000413d0000000104400039000002200110003900000200061000390000020005500039000001e007100039000001e006500039000001c007100039000001c006500039000001a007100039000001a0065000390000018007100039000001800650003900000160071000390000016006500039000001400710003900000140065000390000012007100039000001200650003900000100071000390000010006500039000000e007100039000000e006500039000000c007100039000000c006500039000000a00650003900000080071000390000008006500039000000600710003900000060065000390000004007100039000000400650003900000000066104360000000076050434000020da0000613d000000000134043600000180052000390000000003240049000000000443001900000bff0350019700000160072000390000016006100039000001400720003900000140061000390000012007200039000001200610003900000100072000390000010006100039000020680000413d0000206f0000613d000000e007200039000000e005100039000020520000413d000020590000613d000000c0072000390000203c0000413d000020430000613d0000000065070434000000a00620003900000000052400490000001f05300039000000800620003900000040062000390000000007430019000020160000413d000000000a87001900000000094800190000201d0000613d00000000730304340000000006420436000001a00400003900000000530104340000020002200039000001e004200039000001e003100039000001c00310003900000180042000390000016004200039000001400420003900000120042000390000010004200039000000e004200039000000e003100039000000c004200039000000a004200039000000000121001900000bff022001970000001f02300039000000000213001900001fb90000413d0000000006240019000000000512001900001fc00000613d000000000132043600001faf0000c13d00001fa30000c13d00001f970000c13d00001f8b0000c13d00001f7f0000c13d00001f730000c13d00001f670000c13d00001f5b0000c13d00001f4f0000c13d00001f430000c13d00001f370000c13d00001f2b0000c13d00001f1f0000c13d00001f130000c13d00001f070000c13d00001efb0000c13d00001eef0000c13d00001ee30000c13d00001ed70000c13d2e151fb40000040f0000002402400039000000040240003900000bd502000041002000000004001d0000001e0160035f00001eba0000613d00001ea90000c13d00001e9c0000c13d00001e8f0000c13d00001e820000c13d0000006001900210000000000163034f00001e780000613d00001e670000c13d00001e6b0000613d00000b880680019800000000090800190000001f0580018f00001e590000c13d000000120100003900001e3f0000c13d00001e330000c13d00001e270000c13d00001e1b0000c13d00001e0f0000c13d00001e030000c13d00001df70000c13d00001deb0000c13d00001ddf0000c13d00001dd30000c13d00001dc70000c13d00001dbb0000c13d00001daf0000c13d00001da30000c13d00001d970000c13d00001d8b0000c13d00001d7f0000c13d0000001101000039000015080000013d000015410000413d001f00000002001d0000002801000029002600010020003d0000001301000029001800600010003d0000002501000029001f00260000002d001900270000002d0000162d0000413d001d00010070003d0000001502400029000000000072004b000000000252001900000bd20220012a00000bd20550012a0000001d07000029000000000401043600000000055200d900001d290000613d00000000025400a9000000000152001900001f180000613d00001d0d0000613d00001cfc0000c13d00001d000000613d00001d120000613d0000001a0110002900001f900000613d00001cb30000613d00001ca20000c13d00001ca60000613d00001cb90000613d0000001a0400002900001cc60000013d00001c850000813d000000140020006b00001f600000613d00001c6a0000613d00001c590000c13d00001c5d0000613d001a0000000a001d00001c700000613d00001cc60000c13d0000001a0500002900001f0c0000613d00001c180000613d00001c070000c13d00001c0b0000613d00001c1f0000613d001900000006001d00000bdb02000041000000240250003900000bc60220019700000baa06200197001600000002001d0000001e02400029001500000004001d000000290200002900000017026000f900001bcd0000213d00170000006500ad00000000064200d900000bd10040009c00000000044200d900001bc00000613d00000bd1024000d100001f000000613d00001ba40000613d00001b930000c13d00001b970000613d000000170800002900001ba90000613d001700000005001d00000bda010000410000001c0110002900001f840000613d00001b4a0000613d00001b390000c13d00001b3d0000613d00001b500000613d00001b5d0000013d00001b1c0000813d000000150020006b00001f540000613d00001b010000613d00001af00000c13d00001af40000613d001c0000000a001d00001b070000613d00001b5d0000c13d0000001c0410002900001ef40000613d00001ab00000613d00001a9f0000c13d00001aa30000613d00001ab40000013d00001a890000c13d00000024014000390000002a02000029000000040140003900000bd80100004100000bc60110019700000baa0310019700001a320000013d00000000022400d900000000013400d900001a2a0000613d00000bd2043000d100001a2f0000613d0000001c0020006c00000000022300d90000001c032000b9000000140120002900001f780000613d00001a050000613d000019f40000c13d0000001408000029000019f80000613d000000140560002900001a090000013d000019de0000c13d00000bd70100004100001a5e0000613d0000001c0000006b00001a610000613d000000000114004b000019b40000013d000019b10000613d00001ee80000613d000019850000613d000019740000c13d000019780000613d000019890000013d0000195e0000c13d0000000401300039001c00000003001d00000bd60200004100000000022500d900000000023200d900000000014500d9000019130000613d00000bd2054000d1000019180000a13d000019080000a13d000000150050006c00000000055400d900000015045000b9000000100500002900000bd10030009c00000000033200d9000018f90000613d00000bd1023000d1000000110120002900001f6c0000613d000018e00000613d000018cf0000c13d0000001108000029000018d30000613d0000001105600029000018e40000013d000018b90000c13d00000bd001000041000019440000613d000000150000006b000019470000613d0010000000140053000018900000013d0000188d0000613d0000001501000029000000000251001900001edc0000613d000018600000613d0000184f0000c13d000018530000613d000018670000613d001200000004001d00000baa0420019700000bcc0400004100001ed00000613d0000180a0000613d000017f90000c13d000017fd0000613d0000180f0000613d00000bca01000041001800000001001d0000001d0010006c00001f480000613d000017ae0000613d0000179d0000c13d000017a10000613d000017b40000613d000000000445043600000bc90400004100001f3c0000613d000017510000613d000017400000c13d000017440000613d000017cc0000013d00001f300000613d000017100000613d000016ff0000c13d000017030000613d0000001805600029000000180a00002900180000000a001d000017160000613d00000000044a043600000bc70400004100001f240000613d000016b60000613d000016a50000c13d000016a90000613d000017550000013d0000172a0000c13d00000bc802000041000016ba0000013d0000168f0000c13d00000bc502000041000016750000613d0019000500200218000000200100003900001d510000613d0000161a0000413d00000bc20060009c000016270000613d001300000006001d000000050150021000001fa80000613d000015e80000613d000015d70000c13d000015db0000613d000015ee0000613d000000040550003900000baa0440019700000bc1040000410000001f0020006c00001f9c0000613d000015990000613d000015880000c13d0000158c0000613d0000159d0000013d000015730000c13d00000bc001000041002500000002001d00000bbf0010009c001f00000000001d000015170000013d000015340000413d000000000089004b00000001099000390000000000ba0435000000000aa2043600000baa0aa0019700000000ba0a0434000000000a070433000015170000613d000000800920003900000000005804350000006007700039000000400920003900000baa09900197000000000882043600000baa0880019700000000980704340000000004740436000000400770008a0000000007120049000002180000813d000000000036004b00000001066000390000151a0000013d000000190c00002900000080050000390000000002420019000015400000c13d002600000000003d000014f20000413d00000bbf0060009c0000006002000039000015030000613d000000000424043600000019040000290000000004460019002700000004001d0028001c0000002d000014da0000c13d000009b30000013d000014020000413d001d00010050003d001c001c0010002d0000001c0010002a000000190210002900000bd10110012a00000000044100d9000014b90000613d00000000014200a900001d840000613d000014a30000613d000014920000c13d000014960000613d000014af0000013d00000000011500190000147c0000c13d0000000004060433000000200040008c00000000060a001900001d780000613d000014510000613d000014400000c13d000014440000613d00200000000a001d000014550000013d000014290000c13d00000be60100004100000016054000290000000504200210001601a00010003d00150baa0020019b000013f80000c13d000013ec0000c13d000013e00000c13d000013d40000c13d000013c80000c13d000013bc0000c13d000012dc0000013d000013690000413d000000010aa000390000022005500039000002000b5000390000020006b00039000001e00c500039000001e006b00039000001c00c500039000001c006b00039000001a00c500039000001a006b00039000001800c5000390000018006b00039000001600c5000390000016006b00039000001400c5000390000014006b00039000001200c5000390000012006b00039000001000c5000390000010006b00039000000e00c500039000000e006b00039000000c00c500039000000c006b00039000000a00c500039000000a006b00039000000800c5000390000008006b00039000000600c5000390000006006b00039000000400c5000390000004006b000390000000000c60435000000000c0c0433000000000665043600000000c60b0434000000000b080433000012dc0000613d0000000005960436000000000908043300000180088000390000018005500039000001600b5000390000016006800039000001400b5000390000014006800039000001200b5000390000012006800039000001000b5000390000010006800039000013420000413d000013490000613d000000e00b500039000000e0098000390000132c0000413d000013330000613d000000c00b500039000000c009800039000013160000413d0000131d0000613d00000000ba0b0434000000a00b800039000000a00a5000390000000006a600190000001f06900039000000800b5000390000008006800039000000600b5000390000006006800039000000400b50003900000040068000390000000006a90019000012f00000413d00000000009e004b000000200ee0003900000000006f04350000000006ed0019000000000fae0019000012f70000613d000001c00a500039000001a00a50003900000000d9090434000000000b650436000001a00600003900000000c90804340000000008060433002000000006001d00000020062000290000000000840435000000400880008a0000000008150049000005500000813d000000000037004b00000001077000390000000004240019000012e00000013d000005450000013d0000002e0200002900000a980000413d000000020020006c0000000301d0002900000016010000290000001d0300002900000013030000290000001503000029000000120300002900000011030000290000010001200039000000100300002900000140012000390000018003200039000001a003200039000000000232001900001ea10000613d0000128d0000613d0000127c0000c13d000012800000613d000012970000613d00000bfb0100004100001e940000613d000012480000613d000012370000c13d0000123b0000613d000012520000613d00000bfa01000041001000000001001d00001e870000613d000012030000613d000011f20000c13d000011f60000613d0000120d0000613d00000bf901000041001100000001001d0000001a0120002900001e7a0000613d000011b80000613d000011a70000c13d000011ab0000613d000011bf0000013d0000000004014019000011900000c13d00000be5020000410000000001580019000011640000413d000000000374001900000000018400190000116b0000613d00000000017500190000000008510436000000010090019000000001090040390000000009000039001900000003001d000000000813001900000000750504340000000005580019000000000801043300000040015000390000000000a6043500000000018b00190000112e0000413d00000000008c004b00000000039c0019000011350000613d0000000001980019000000000b8a04360000000100c00190000000010c004039000000000c0000390000000000ab004b000000000b1a0019000000000971013f00000000085800190000000001b90019000010fb0000413d00000000009c004b0000000003ac0019000011020000613d000000800b2000390000000001a900190000000000960435000000000b61001900000000a9090434000000000a71013f00000bae074001970000000009570019000000008705043400000bc30020009c000000600060008c00000bad0060009c00000000065400490000001f043000290000000005030433000000000171016f001f00000008001d000000000343019f00000000033501cf000000000506043b000010b40000613d000010a30000c13d0000000006360436000000005305043c000000000501034f000010a70000613d00000000047801700000001f0900002900001e5e0000613d00000b8608300197001f00000009001d0000109e0000013d0000000008000031000010880000c13d00000b850000413d0000001701200029000000190110017f0000000c02000029000000100200002900001e380000613d000010080000613d00000ff70000c13d00000ffb0000613d000010100000613d00001e2c0000613d00000fc60000613d00000fb50000c13d00000fb90000613d00000fce0000613d000c00000002001d00001e200000613d00000f840000613d00000f730000c13d00000f770000613d00000f8c0000613d00001e140000613d00000f420000613d00000f310000c13d00000f350000613d00000f4a0000613d00001e080000613d00000f000000613d00000eef0000c13d00000ef30000613d00000f080000613d00001dfc0000613d00000ebe0000613d00000ead0000c13d00000eb10000613d00000ec60000613d00001df00000613d00000e780000613d00000e670000c13d00000e6b0000613d00000e800000613d001000000002001d00001de40000613d00000e320000613d00000e210000c13d00000e250000613d00000e3a0000613d00001dd80000613d00000df00000613d00000ddf0000c13d00000de30000613d00000df80000613d001200000002001d0000000002b1001900001dcc0000613d00000daf0000613d00000d9e0000c13d00000da20000613d0000001d0b000029001d0000000b001d00000db70000613d00000d260000a13d000000080050008c000000ff0520018f000000010250003900000000025201cf000014d30000613d00000d5d0000613d00000d4c0000c13d00000d500000613d001d0000000a001d00000d640000613d0000001f0120017f00000bf001000041000000000aa1001900001dc00000613d00000d100000613d00000cff0000c13d00000d030000613d00000d180000613d000000190220017f00001db40000613d00000ccc0000613d00000cbb0000c13d00000cbf0000613d00000cd20000613d00001da80000613d00000c810000613d00000c700000c13d00000c740000613d00000c870000013d00000c5a0000c13d0000001f0110017f00000000041a043600001d9c0000613d00000c340000613d00000c230000c13d00000c270000613d00000c3c0000613d0000000004a1001900000000050a001900001d900000613d00000bed0000613d00000bdc0000c13d00000be00000613d001e0000000a001d00000bf30000013d00000bc50000c13d0000000902300029000000050320021000000b590000413d0000001704200029000010770000613d001700000002001d0000000002320436001800000003001d000000000253001900000ba80520019700000b370000413d000000002302043400000b470000813d000900000004001d00000000046404360000000a060000290000000b040000290000000b0450002900000ba805400197000000000652013f00000bae0530019700000000014100190000001f0340002900000000040300190000000001030433000000000141019f000000000143034f00000af90000613d00000ae80000c13d0000000006160436000000005105043c000000000503034f00000aec0000613d0000001e0300035f00000bff048001980000001f0800002900001e510000613d001f0b860030019b0000000001094019001d00000009001d00000ae10000613d00000bbc02000041000600000001001d0000004001400039000400000004001d000000600320003900000080032000390000010003200039000001200320003900000140032000390000000001e204360000018001200039000001a0012000390000000101300029000300000003001d000000050310021000000008010000290005002d0000002d000800000002001d00000a750000413d0000000001d4001900000040035000390000006003500039000000800350003900000100035000390000012003500039000001400350003900000160035000390000000001e50436000000a001500039000000c0015000390000018001500039000001a00150003900000bea0050009c00000a6d0000c13d00000a610000c13d00000a550000c13d000006660000013d000000000169034f00000a460000c13d00000a4a0000613d0000052f0000a13d000200000001001d000009e60000413d0000008005a00039000000a0039000390000006005a0003900000080039000390000000000b304350000004003a0003900000baa00b0009c000000000b030433000000600390003900000baa00c0009c000000000c0304330000004003900039000000000bba04360000000003ec001900000a190000413d0000000000cf004b000000200ff0003900000000005304350000000005df00190000000003ef0019000000000f00001900000a200000613d00000000000c004b000000c00ea0003900000000002e004b000000000edc00190000004000e0043f00000ba700e0009c000000000ebe00190000003f0ee000390000001f0ec0003900000000dc0c043400000000000d004b000000000d0ec01900000bae00f0009c00000bae0d004041000000000d00001900000000004d004b000000000f4d013f00000bae0dd0019700000bae0e00804100000000002d004b0000001f0dc00039000000000ccd0019000000000d0c0433000000a00ba0003900000be200a0009c000000a000a0008c00000bad00a0009c000000000ac20049000000200c900039000000000919001900000000690604340000000108000029000009e00000c13d0000000002130049000009cc0000413d00000040033000390000000006630436000009d70000613d000013fd0000c13d0000000001150436001700000004001d0000004004500039000000600450003900000bc30040009c001400000004001d000009930000413d0000000008650019000000200870003900000bc20070009c000000400700043d000009a00000613d0000000005610436000000000515001900000ba8055001970000003f0540003900000005046002100000001d01200029000009d90000613d0000096f0000613d0000095e0000c13d000009620000613d0000001d05700029000001f40000013d000007800000413d000000190030006c0000001e030000290000001607000029000013f10000613d000009170000613d000009060000c13d0000090a0000613d001600000007001d0000091f0000613d00000bba020000410000002402a0003900000000070b0433000013e50000613d000008d40000613d000008c30000c13d000008c70000613d000000170b00002900170000000b001d001600000006001d000008dc0000613d00000bb50200004100000000060a0433000013d90000613d000008920000613d000008810000c13d000008850000613d000008990000613d001a00000002001d000013cd0000613d000008550000613d000008440000c13d000008480000613d0000001a0b000029001a0000000b001d0000085c0000613d001b00000002001d000013c10000613d000008150000613d000008040000c13d000008080000613d0000081c0000613d000013b50000613d000007d00000613d000007bf0000c13d000007c30000613d0000001c0b000029001c0000000b001d000007d50000013d000007a70000c13d001f00000005001d0000000401b00039001e00000003001d00200baa0030019b0000003d0000013d000006940000413d0000001d0030006c0000001f0300002900000a660000613d0000075a0000613d000007490000c13d0000074d0000613d000007610000613d00000a5a0000613d0000071b0000613d0000070a0000c13d0000070e0000613d000007220000613d00000000004a043500000a4e0000613d000006d90000613d000006c80000c13d000006cc0000613d000006de0000013d000006b00000c13d00000bed010000410000067d0000a13d0000077e0000813d0000014005400039000000a00510003900000bb30040009c0000065f0000c13d0000064a0000a13d000006930000813d000000200330003900000bfc0030009c000006420000c13d0000006001a00210000006390000613d000006280000c13d0000062c0000613d00000b8806a001980000061c0000c13d000006100000c13d000006760000a13d000006580000613d000005fa0000613d000005e90000c13d000000009a09043c0000012008000039000005ed0000613d000001200570003900000bde011001c7000001c50000013d000003400340003900000340011000390000032005100039000003200340003900000300051000390000030003400039000002e005100039000002e0034000390000000005570019000005b80000413d000000000a8600190000000009560019000005bf0000613d0000038005100039000000000065004b0000000005870019000000000073043500000bff059001970000000000a8004b000000000ba8013f0000000007780019000003600310003900000be20020009c000000a00030008c0000000003760049000002c007400039000002c006300039000002c00400043d000002c0021000390000057f0000a13d00000be10010009c00000000064601cf0000000304600210000005750000613d000005640000c13d000000000029004b000005680000613d000002c0024000390000063b0000613d00000be0011001c70000000002150049000012da0000c13d0000000005450019000000050530021000000a720000c13d00000000013104360000000203000029000000000415001900000be9054001970000003f042000390000000201000029000009e50000c13d000200000000001d000101400080003d00000140066000390000000000930435000000070aa0002900000ba80aa001970000003f0a700039000000050790021000000000090104330000012001600039000000000507c019000000000945013f00000bae0420019700000bae07008041000000000025004b0000013f05600039000001200600043d000001200180003900000ba90080009c00000bff082001970000001f02a00039001f0000000a001d000000000464019f00000000045401cf000000000454022f000000000441034f000004f80000613d000004e70000c13d000004eb0000613d00000bff04a00198000006210000613d00000b860a300197000004d00000c13d000014e00000013d00000ba806400197002800000001001d000004b90000413d0000000042040434000014df0000813d00000000071400190000001c070000290000001c076000290000003f061000390000000042010434000000000062004b000000000762013f00000bae065001970000001d011000290000001d053000290000001d04200029000000000159034f000004840000613d000004730000c13d0000001d08000029000004770000613d0000001d0450002900000b870210019700000a3f0000613d0000046d0000613d001d00000004001d00000bbe010000410029001e0000002d000004480000413d000000000075043500000baa0070009c00000000470404340000044f0000613d000000000056004b000000000646001900000000007104350000001e0810002900000ba8011001970000003f0160003900000005067002100000000007010433000000000106c01900000bae075001970000013f014000390000012005300039000000000454019f00000000044601cf000004160000613d000004050000c13d000004090000613d000006150000613d00000040023002100000000001310049000003e40000413d00000000016104360000000026020434000003ea0000613d00000040013000390000000005430436000003d50000413d00000000036304360000000003020019000003db0000613d0000000005540019000000000717001900000ba8077001970000003f0750003900000005056002100000012005400039000000000506c019000000000875013f00000bae073001970000013f054000390000012003300039000003a50000613d000003940000c13d000003980000613d0000012004500039000006090000613d00000bac011001c7000009730000013d000009470000c13d0000036f0000413d0000000015010434000003760000613d0000000004140019000001a0011000390000001f060000290000001f066000290000003f0640003900000005045002100000018004100039000000000405c01900000bae04004041000000000764013f00000bae0440019700000bae050080410000019f041000390000018002300039000001800100043d00000be40010009c0000033c0000613d0000032b0000c13d0000032f0000613d0000018004500039000004c90000613d00000be3011001c70000000001230049000002c50000413d000002200330003900000200073000390000020006600039000001e008300039000001e007600039000001c008300039000001c007600039000001a008300039000001a007600039000001800830003900000180076000390000016008300039000000010700c03900000000070000390000016007600039000001400830003900000140076000390000012008300039000001200760003900000100083000390000010007600039000000e008300039000000e007600039000000c008300039000000c007600039000000a008300039000000a00760003900000080083000390000006008300039000000400830003900000000077304360000000006010433000003100000613d2e152d610000040f0000012001000039000002b20000413d000000000505043b000000000513034f000002ba0000613d0000002401100039000001200660003900000ba90060009c0000003f062000390000000502500210000000000502043b0000002c0440008a002b00000000003d002c00000001001d00000bb1011001c72e151fc60000040f000004e10000013d000000000a000031000004d50000c13d000001200030043f00000be803000041002d00000002001d0000000402300370002e00200000003d0000000002000416000000240440008a002300200000003d002400000001001d0000055f0000013d000005520000c13d000002c40020043f000002c00010043f00000bdf01000041000002a00010043f000002800000043f000002600000043f000002400000043f000002200000043f000002000010043f000001e00010043f000001c00010043f000001a00000043f000001800000043f000001600000043f00000060022002100000000002120049000001fd0000413d000000c002200039000000a007200039000000a00660003900000080082000390000004008200039000000000772043600000120040000390000067a0000c13d000000190500002900000ba90040009c00000ba804100197001800240010003d000003110000013d2e15200c0000040f002000000003001d2e1520f70000040f0000012002000039000001a00020043f000001800040043f000000000443034f000001600040043f000001400040043f0000002002500039000001200020043f000001e0046000390000000000740435000000000797019f00000000078701cf000000000787022f0000010008800089000000000989022f00000000098901cf00000000090404330000000308900210000000000787034f000001ad0000613d0000019c0000c13d00000000004a004b000000000aca043600000000bc0b043c000000000b07034f000001e00a000039000001a00000613d000001e0048000390000001f0960018f00000bff08600198000000000743034f0000002004800039000000000047004b0000002407700039000001c00060043f000001c00aa0003900000bfe00a0009c0000001f0a600039000005790000813d00000bfd0060009c000000000683034f00000004087000390000002306700039000000000753034f0000000405600039000001c002000039000000a40020008c00000bad0020009c0000000002640049000000000602043b00000b8d01000041000001200010044300000003010000390000010000200443000001e000300443000001c000100443000001a000100443000001800020044300000160002004430000014000000443000000c00030043f000000020300003900000b8c0200004100000040012002102e152dd00000040f000000220440008a002100400000003d002200000001001d00000b920020009c000002920000613d00000b910020009c000003ff0000013d000003f30000c13d002a00200000002d00000b9d0020009c000002820000613d00000b9c0020009c00000bb0011001c72e1520e10000040f2e152b470000040f00000b970020009c0000026f0000613d00000b960020009c0000014e0000013d00000b8902000041000001540000c13d000003260000013d000003190000c13d000001800010043f000001600010043f000001200000043f00000ba20020009c0000025c0000613d00000ba10020009c0000038f0000013d000003820000c13d000001240030043f00000bab0100004100000b940020009c000002490000613d00000b930020009c000001330000213d00000b900020009c000005fe0000013d000005d80000c13d000001440030043f000001240010043f00000bdd040000410000004403300370000000640040008c00000b9f0020009c000002210000613d00000b9e0020009c000001160000213d00000b9b0020009c00000bb2011001c72e1520db0000040f2e15248d0000040f00000b990020009c000001ce0000613d00000b980020009c000000fb0000213d00000b950020009c000000bd0000213d00000b8f0020009c000001550000013d000000010300003900000b8b020000410000014c0000c13d000000f60000613d000000010200c039000000e00100043d000000400040008c000000000252019f00000000022301cf000000000323022f0000010002200089000000000525022f00000000052501cf0000000302200210000000000353034f0000006f0000613d0000005e0000c13d000000000016004b000000e006000039000000620000613d00000b88054001980000001f0240018f00000b8701100197000002180000013d000000460000413d000006470000c13d0000001d04000029000001200130003900000ba90030009c00000ba803100197001c00240010003d00000ba40020009c000001650000613d00000ba30020009c000000d90000213d00000ba00020009c0000009a0000213d00000b9a0020009c0000007f0000213d00000b8e0020009c000000e002200270000000000203043b000000000543034f000000510000c13d0001000000030355000200000043035500000b860410019700000060011002700000000001030019002e00000000000200030000000000020c4f0c4e04030c4d0c4c0c4b0c4a0c4900060c48040202a900e800160c470c460c450c440c430c420c410c400c3f0c3e0c3d0c3c003b01370016008d005d003b00b600400047000802a800e701e502a701e4017700e6005900080c3b00e502a602a500a8000804010c3a0c3900020c3800350c37040000b50c36011101e303ff005f00d5009502a403fe00c503fd03fc00b403fb006602a301e2017601e10c350c34008d005d003b00150c3302a200350c320c3103fa0c300c2f03f9013602a10c2e0c2d00940c2c0c2b0c2a03f80c290c2803f70c270c260c250c2400330c2300160c22005d005e0c21008c003b0046005d0c2000940c1f0c1e0c1d0c1c0c1b0c1a0c190c180c170c160c15003b01370016008d005d003b00b6004000b300080c14000701e00c1300c4002f002e001d0c1200b20c110c100c0f0c0e0c0d003b0c0c0016008d005d003b00b602a0008200080175004000b300080c0b03f7013500080c0a04000c090c08003f001e0c0700780001000a00090c060c050c040c030c020c01003b01340016008d005d003b00b602a000820008017503f6013500080c0001740bff0173001e01720bfe00780bfd0bfc0bfb0bfa003b01370016008d005d003b00b60040017100b3000803f502a90bf903f4029f0bf8029e0bf7017300e4001e01720bf600780bf500940bf400650bf30bf20bf10bf00bef003b01340016008d005d003b00b6004000b3000803f30177008200080bee000701e00bed00c4002f002e001d0bec00b20beb0bea0be9003b01340016008d005d003b00b60040017100b300080be80175004003f200b30008029e017401730072001e01720be700780be60be50be40be3003b008d005d003b01330be20be1029d029c029b0be0029a029902980bdf0007003e003700380bde03f100b200650bdd0033002f002e001d0023005c0bdc029702960bdb0bda0bd901110bd80bd702950bd60bd50bd40bd30bd20bd100b201340016008d005d003b00b6004000b3000803f30bd0013200080bcf0bce00080bcd00160bcc00360bcb0bca004900d4000802940bc903f001e50bc80bc700260bc60bc50bc401df03ef01df0bc300020bc200d30bc102940bc00bbf00080bbe0bbd0bbc0bbb0bba0bb90bb80bb70bb60bb50bb40bb301700bb20bb10bb00baf0bae0bad00490bac0bab0baa0ba90ba80ba7001f0ba60ba503ee01de029300080ba400c303ee01de029300080ba301dd0ba201de0ba101e201e401770ba00b9f0b9e011100810b9d02920b9c00e403ed0b9b01340016008d005d003b00b600400047000802a800e701e502a701e4017703ec005900080b9a01dc02a603eb00a80008017503f60135000804010b990b98000203ea00350b9703e900610b96011101e303ff005f00d5009502a40b9500c501db00b103e802910b94016f03e701da00660b93007c0290006603e6007c028f00660b92007c0b9100320b9000640b8f017601e10b8e0b8d003700380b8c002f002e001d005200b201340016008d005d003b00b60040017100b30008017502a00082000803e502a9029f017403f40b8b0b8a0b890b880b870b860b850b840b830b820b810b800b7f0b7e017300e4001e01720b7d00780b7c008d005d003b01330b7b0b7a029d029c029b0b79029a02990298005d00d2028e017403e400b20b780094003b0b77013700160b760177008200080b750b740b730173001e01720b720b710b7001370016008d005d003b00b6004000b30008028d000701e00b6f00c4002f002e001d0b6e00b2008d005d003b01330b6d0b6c029d029c029b0b6b029a02990298017403e400b201370016008d005d003b00b600400047000802a800e701e502a701e40b6a00d100020b690b68028c0b6700020b66028b03e90b65028a00e7000800610b6403fe0b630b6201d90008013100c2008c0b610b600b5f03e300070289028800e303e200b50b5e00c500c20b5d03e802910b5c016f03e701da00660b5b007c029000660b5a007c028f00660b59007c0b5800660b57007c0b5600660b55007c0b5400660b53007c0b5200660b51007c0b5000660b4f007c0b4e00660b4d007c0b4c006601d80b4b0b4a0b49007c0b4800660b47007c0b46006602910b45007c0b4400660b43007c0b4200660b41007c0b4000320b3f00640b3e0176016e0b3d0b3c002f002e01d700370038007b008000b200c100f9016d0b3b000b0011001000d00012000f00060b3a03f5028701d60b390b3800030136028603e10b37003a0b3603e0028500b100c000bf004000be00cf00ce00bd006d011000cd01d50b35000200a701d403f2003500f80008000100160b34004700080b330b32010f00c50b3103df0b300b2f01d300f70b2e03de0b2d00b5003b0b2c028400d100020b2b0b2a028c0b2901320002028b0b2800e20b270b26010f000800610b2500720b2401d9000800c3028300a80b23000703dd00e6003e003f00e4001e0b220001000a00090b2100c100f9016d0b20000b0011001000d00012000f00060b1f0402028701d60b1e0b1d00030136028603e10b1c003a0b1b03e0028500b100c000bf004000be00cf00ce00bd006d0110028203dc00020281003500f800080001001603db008b00080b1a0b1901e1013003da0b1803d90b1703d800c503d702800b160061003b0b15016c013200020b140b130b120b1100d40002016b027f03d60b1001e10008027e003a0b0f0b0e03fd03d500080b0d027d0b0c0081000a0b0b028800f60b0a00b50b0900c50b0800b40b070176016e0b060b05002f002e01d700c100f90b04008000b200c100f9016d03d4000b0011001000d00012000f00060b0301d2001303d30b0203d20003013602a1016a0b0100610b0003d1027c0169027b027a002601d103d00aff0afe00b002790110028203dc0002028101d5003500f800080001001603db008b00080afd0afc03cf013003da0afb01d003ce016800e101cf02800afa005d003b03ea0af900d400020af80af70af60af5010e0002027800a70af403d60af30af2000801d80af101ce0af00aef000802770aee01d30aed0aec0aeb012f0aea006d003d006c01670ae900e5002f002e001d0039003c01cd005200230072000b0011001000d000120279000f00060ae801100ae7028701d60ae60ae503cd0ae400f500f4000c0ae3003a0ae20ae1028500b100c000bf004000be00cf00ce00bd006d0ae0010f00d2010d0276008b0002010c0045007f003500f800080001001600e5001b004700080adf0ade03cc016600f7027503cb0add0adc0adb00a603ca03de03c90094003b0ada0059000203c80ad9028c0ad800d40002016b0ad703c70ad601cc000803c60ad5007f0ad40082000800c2003303c60ad3007f00e00ad20059000203c803c50ad10ad0001300140007000e00220003000d00050004000c0acf002500c100f9016d03d4000b0011001000d00ace000f00060acd0acc03c403d30acb03d20003013602a1016a0aca00610ac90ac800f3027400c000bf01de00be0ac70ac60ac500b0010b0ac40ac30ac20ac100020ac003c30035006c02730008006c00f200160abf01320008006c01cb0abe0abd01650abc0abb03d90aba016e00c503d702720ab90061003b0ab80ab7027100020ab60ab50ab40ab300df000200d302700ab20ab1029401ca00080ab001700aaf0aae0aad02a60aac0aab006501710aaa027d03c203c1008b000203c00045007100c40aa90aa803bf00950aa701110065003303be03bd0048007001c90aa60aa500950aa40aa303bc00c100f9016d0aa2000b0011001000d00012000f00060aa103e501d201d60aa00a9f0003013602860a9e0a9d003a0a9c026f0a9b02740a9a03d0004001d1026e026d00bd003e011000cd0a990a9800a500a4012e00a300a2005c0a97003600f80008000100160a96008b00080a950a940a9300f800080a9200160a9100020a9000af03bb010e00080a8f03ba03b901c8026c03b803b70a8e0a8d016403b603b503b40163003b03b300d4000203b203b103b00a8c03af00d1000201620a8b0a8a0a8900080a8801d80a8701300a860a8503ae03ad03ac03ab0a840a83012d005f0a820048013500080a8100cc0a800048013500080a7f00cc0a7e00480a7d00cc0a7c0a7b0048007500c40a7a002f002e00440a79000b0011001000120001000a0009005100570a780a770a7602790a7503aa00210a74003a0a730050004f001a004e004d0049004c004b004a001900170018000f00060a720015001c026b003500010016026a00820a7100e1005c001300140007000e00220003000d00050004000c0a700025001300140007000e00220003000d00050004000c0a6f002503c40a6e0007000e0a6d0003000d00050004000c0a6c00610a6b010a00f300b100c000bf004000be00cf00ce00bd006d0a6a0269001300140007000e00220003000d00050004000c0a6900250a68000200cb01c9007103a9001f006f01c7006d0a6701c60a66006500f10a6501c5001300140007000e00220003000d00050004000c0a64006103a8010a00f300b100c000bf004000be00cf00ce00bd006d010900370038007b0052005c0033001d03f100b20a63000200f703a701620a62012d03a6012d0268012d03a5012d03a4012d006f0a61016101db010f0a60006501c40a5f01c500cb0160015f012c02a503a303a201d90008006500f1000200d50036012b0031006f02670a5e0266003f009b03a10a5d00780001000a00090a5c0074026503a0007b002f002e0044008000230093039f000b039e0011001000120001000a00090030012a0a5b000301290005000400210a5a00240a59002d002c001a002b002a0026002900280027001900170018000f00060a5801c30015001c015e039d005e006b00df00020006004500d300010016007a00820008039c0a57003d001e0a56006300200079001d0039003c004300420023039b000b039a0011001000120001000a00090030006e0a55000300600005000400210a5400240a53002d002c001a002b002a0026002900280027001900170018000f00060a520015001c01c3015d00770002007300010016015c008200080264026303990262003d001e0a5100740020008a001d0039003c004300420058039f000b039e0011001000120001000a00090030012a0a50000301290005000400210a4f00240a4e002d002c001a002b002a0026002900280027001900170018000f00060a4d0015001c01c301c20047000200350001001600f10002007a010800af010700bc0106026a0a4c00f000410092027e003e039800ae0041015b0a4b0a4a00650a490a4800cb0a47015f00e603eb03a303a201d90008006501c40002015a003601590031012800310127003100d50031012b0031006f0267039702660a4600e40033003f009b0a450a4400780001000a00090a430074026503a0007b002f002e00440080005800930a42000b0a410011001000120001000a00090030012a0a40000301290005000400210a3f00240a3e002d002c001a002b002a0026002900280027001900170018000f00060a3d01260015001c015e039d005e006b00df00020006004500d300010016007a0158039600890157010500b0006a009b0a3c006300200079001d003700380069005200580093039b01c1039a0011001000120001000a00090030006e0a3b000300600005000400210a3a00240a39002d002c001a002b002a0026002900280027001900170018000f00060a380015001c0126015d00770002007300010016015c0a37039500a101c0010500b0006a009b0a3600740020008a001d0037003800690052005800930a3501c10a340011001000120001000a00090030012a0a33000301290005000400210a3200240a31002d002c001a002b002a0026002900280027001900170018000f00060a300015001c0126015e00df000200d300010016007a0a2f03940089006a009b0a2e006300200079001d0037003800690052002300930393000b03920011001000120001000a00090030006e0a2d000300600005000400210a2c00240a2b002d002c001a002b002a0026002900280027001900170018000f00060a2a0015001c0126015d007700020073000100160a2903d500080a2800a101c0010500b0006a03910a2700740020008a001d003700380069005200580a2603900a25000b0a240011001000120001000a00090030012a0a23000301290005000400210a2200240a21002d002c001a002b002a0026002900280027001900170018000f00060a200015001c012601bf015e00df000200d3000100160a1f0a1e02830a1d00890157010500b0006a03910a1c0a1b006300200079001d0037003800690052012503900393000b03920011001000120001000a00090030006e0a1a000300600005000400210a1900240a18002d002c001a002b002a0026002900280027001900170018000f00060a170015001c01260a1601560047000200350001001601c40002015c026100af01be00bc0128038f01270124005f00d50260005f012b0155005f0106026a0a1500f000410062027e003e039800ae0041015b0a140a1300650a12006200370038007b002f002e00440080002300e4000b0011001000120001000a0009005100570a110a100056038e0055005400530a0f003a0a0e0050004f001a004e004d0049004c004b004a001900170018000f00060a0d001500de0a0c008c005e006b0047000200060045003500010016006200340082000800bb00b1013200020a0b0a0a0a090a0800d1000201620a07003a0a0601300a050a040002038d02780a03038c01230a02007c03ac03f00a01012f0a0009ff0002038b09fe007109fd09fc006d00c409fb025f006f006c001b005d038a09fa025e007f006d0111006501e30389004801bd005f025d010800bc01bc003401bb010400e301ba010300e301be00b509f900c500c3027403fc00b409f8006602a309f70176016e09f609f503bc001300140007000e00220003000d00050004000c09f4002509f309f20271000809f109f009ef09ee000809ed001600ca09ec000209eb007309ea0388000809e909e809e7038709e609e509e409e309e209e109e009df09de003b09dd00ba000209dc038609db038609da09d9000209d8038509d709d6000809d509d409d309d209d109d000ad09cf09ce09cd09cc09cb005b09ca09c909c809c70008038509c609c509c4000809c309c209c1004809c000cc09bf004809be00cc03aa03ab09bd0384001b09bc004709bb01c5001300140007000e09ba03cd000d00f500f4000c09b9006103a809b809b7001300140007000e00220003000d00050004000c09b60025001300140007000e00220003000d00050004000c09b50025001300140007000e00220003000d00050004000c09b40025006800f7006700dd09b3000209b2003509b100ef03fa00ef09b000ef09af00ef09ae09ad005b09ac005b09ab005b09aa005b09a9005b09a8005b09a7005b006f09a6010601db010f09a500a60384001b09a4008c004100070383000209a309a209a109a0099f0288099e0035099d00ef038200ef038100ef038000ef099c037f005b099b005b099a005b0999005b0998005b0997005b01e20031006f099609950994001b01540993025c003d037e001e099201b9099100200990001d0039003c004300420023000b0011001000d0098f010b000f0006098e00670068038e098d098c01b8098b098a0989037d09880987016a0986037c0985098401b70103037b037a004000ee025b025a0983003e01b600cd03790259008800d2010d025800590002010c004501b50035006c02730008006c00f2001609820047000809810980097f03cc00f000f7027503cb097e097d016600a603ca037803c90094003b037701b400470002025701b303c5097c097b008b00020071097a09790978097703be0376000800e7097601b509750135000800c2007500e7097401b5001b01b400470002025701b301b2097300810972097100f00122025600590002025500450036012102540970096f0095096e00a6008102530002025200710251001f0250001f024f001f024e001f024d001f024c001f01c7001f024b001f024a001f0249001f01b1001f01b0001f01af001f01ae001f01ad001f0120001f005b096d007000c30088096c00cb01b5001b00ae0041037500650248000200dc096b096a0034037401ac00360373003103720031037100310247003102460031037000310245003101cb00310244003101ab0031015a003101590031012800310127003100d50031012b0031006f036f036e00ca036d01aa00ac036c003f001e036b096900780001000a0009096800630091011f0087002f002e0044008600230967000b00db0011001000120001000a00090030006e096600030060000500040021096500240964002d002c001a002b002a0026002900280027001900170018000f00060067006809630015001c096209610153005e006b036a008b000200060045009200360001001602430242024100db0089004600ab003d001e0960006300200079001d0039003c004300420023000b00db0011001000120001000a00090030006e095f00030060000500040021095e0024095d002d002c001a002b002a0026002900280027001900170018000f000600670068095c0015001c015601a90047000200e500350001001600a7001b01d500b30008036900a0095b00ac095a0157003e00ac0368003f001e02400959011e01a80009095800630091011f0087002f002e004400860058000b00a0001100100012011e01a800090152006e095700030060000500040021095600240955002d002c001a002b002a0026002900280027001900170018000f00060067006809540015011d0156011c00470002007f0035011e001600e500e0009400d2028e023f0088003b01dc001b025f036700ed01aa00ac036c003f001e000a095300630091011f0087002f002e004400860023000b00ed0011001000120001000a00090030006e095200030060000500040021095100240950002d002c001a002b002a0026002900280027001900170018000f000600670068094f0015001c00c900e6005900020062003600010016007e003403ec0082000801a700a000890046094e003d001e094d006300200079001d0039003c004300420023000b00a00011001000120001000a00090030006e094c00030060000500040021094b0024094a002d002c001a002b002a0026002900280027001900170018000f00060067006809490015001c0948036600df000200d30001001600e5001b036500080364036300c5094701aa03620046010609460157003e00ac0368003f001e000a0945036100630091011f0087002f002e0044008601250944000b00a00011001000120001000a00090030006e094300030060000500040021094200240941002d002c001a002b002a0026002900280027001900170018000f000600670068094001a60015001c015d0151005e006b0077000200060045007300010016015c00940102036000e7003b093f035f035e035d093e093d093c035c093b035b00a1004600ab003d001e093a00740020008a001d0039003c0043004200230939000b09380011001000120001000a00090030012a093700030129000500040021093600240935002d002c001a002b002a0026002900280027001900170018000f00060067006809340015001c093300e6005900020062003600010016007a0932035a00a00089004600ab003d001e0931006300200079001d0039003c004300420023000b00a00011001000120001000a00090030006e093000030060000500040021092f0024092e002d002c001a002b002a0026002900280027001900170018000f000600670068092d0015001c00c9015800590002007e003600010016006200340359035800ed0089004600ab003d001e092c006300200079001d0039003c004300420023000b00ed0011001000120001000a00090030006e092b00030060000500040021092a00240929002d002c001a002b002a0026002900280027001900170018000f00060067006809280015001c00c900e6005900020062003600010016007e00340927035700a00089004600ab023e009000460356003d001e0926006300200079001d0039003c004300420058000b00a00011001000120001000a00090030006e092500030060000500040021092400240923002d002c001a002b002a0026002900280027001900170018000f00060067006809220015001c00c9015800590002007e003600010016006200340355035400ed0089004600ab023e009000460356003d001e0921006300200079001d0039003c004300420058000b00ed0011001000120001000a00090030006e092000030060000500040021091f0024091e002d002c001a002b002a0026002900280027001900170018000f000600670068091d0015001c00c9012c005900020092003600010016007e00340158035300db0089004600ab003d001e091c006300200079001d0039003c004300420023000b00db0011001000120001000a00090030006e091b00030060000500040021091a00240919002d002c001a002b002a0026002900280027001900170018000f00060067006809180015001c00c900e6005900020062003600010016009200340352035100a00089004600ab003d001e0917006300200079001d0039003c004300420023000b00a00011001000120001000a00090030006e091600030060000500040021091500240914002d002c001a002b002a0026002900280027001900170018000f00060067006809130015001c00c9012c005900020092003600010016006200340350034f00db0089004600ab003d001e0912006300200079001d0039003c004300420023000b00db0011001000120001000a00090030006e09110003006000050004002109100024090f002d002c001a002b002a0026002900280027001900170018000f000600670068090e0015001c00c900e600590002006200360001001600920034090d034e00a00089004600ab003d001e090c006300200079001d0039003c004300420023000b00a00011001000120001000a00090030006e090b00030060000500040021090a00240909002d002c001a002b002a0026002900280027001900170018000f00060067006809080015001c00c9012c0059000200920036000100160062003400e601a700db0089004600ab003d001e0907006300200079001d0039003c004300420023000b00db0011001000120001000a00090030006e090600030060000500040021090500240904002d002c001a002b002a0026002900280027001900170018000f00060067006809030015001c0156034d0047000200350001001600920034034c0008029602970248000201ac0036004600ab0033005a00c201010033005a01a501a40033005a034b023d0033005a034a09020033005a023c03490033005a0348007e0033005a02a203470033005a034601a30033005a026b09010033005a034500620033005a034401a20033005a01d40343003300ac090001000342003e034101a101000340003e033f01a10100033e003e005a023b033d003301a0001b012400ae0041019f08ff0100003301a0001b00ae0041015b033c08fe023a001b0154033b025c00b9033a003e003f023900aa001e08fd023808fc033908fb01b908fa009102370087002f002e004400860058000b0011001000d008f9000f000608f803390067006808f708f601b808f508f4037d08f308f2016a08f1037c08f003d101b70103037b037a08ef00ee023608ee08ed005f010b08ec01b608eb0379025900880102015000590002014f00450036006c02730008006c00f2001608ea00d1000808e903af08e808e7000808e6001608e500020338028b08e400d4000808e3033700a800cb023501d008e208e1016800e101cf03360234005d003b08e002710002033700cd023300cd08df00770002007308de08dd00a8000808dc017008db014e033508da00480075011b08d908d808d7006f03fb016f010e000808d601b600a800cb023501d008d5016800e101cf02720234005d003b0334010e000201b600cd023300cd00ca08d408d308d208d10077000208d00045007308cf08ce00a80008016308cd014e033508cc00480075011b08cb08ca08c9006f08c808c708c6010e000808c5033300a800cb023501d003ce016800e101cf02800234005d003b08c400d10002033300cd023300cd008108c308c2033208c108c0010e000208bf0045027801dc08be08bd00a80008006108bc00f708bb08ba0048007501db027d08b908b8006f011a02320075014d019e033103300231019d001b025f014c001b032f014b001b0230014d019c023a001b008108b7037500bc006a00b901a9016708b6006c00f2000a08b508b400ec002f002e001d003700380069005200230062000b00110010001200010160000a00090030022f08b30003019b019a0199002108b2002408b101980197016c01960195019400ee01930192019100cc0190010b000f000608b000670068001500de08af008c01020150011c00470002014f0045007f0035006c00f2001600ec001b08ae00b3000808ad0155014a003d00e5016708ac00c10020022e001d0039003c01cd005200230062000b014900110010001200010160000a0009003000eb08ab0003019a0199002108aa002408a901980197016c01960195019400ee01930192019100cc0190010b000f000608a8001500de006700680155032e018f0047000200ec0035006c00f20016007f001b08a708a60124014a003d00e5016708a500c10020022e001d0039003c01cd005200230062000b019b00110010001200010160000a0009003000eb08a40003019a0199002108a3002408a201980197016c01960195019400ee01930192019100cc0190010b000f000608a1001500de006700680124032e011c00470002007f0035006c00f2001600ec001b018f08a00155014a003d00e50167089f00c10020022e001d0039003c01cd005200230062000b014900110010001200010160000a0009003000eb089e0003019a01990021089d0024089c01980197016c01960195019400ee01930192019100cc0190010b000f0006089b001500de006700680155089a005900020036006c00f2001603830002007f001b089900af0898014800e3037f014a089701240075028108960075089508940075038202320075038108930075038008920075019d08910075014c03890075011a08900075088f00b9032d014a018e003e00c4001b032c0041088e003300c4001b032c0041032b022d088d088c088b088a01650889088808870886088508840883088208810880087f087e087d087c087b087a032a08790170087803870877087600320875087408730872087100da022c00b400d90870003200b4086f00d9086e0032086d00d9086c0032086b00d9086a018d08690329086808670328032a0866022b018c0865014e022a022901470228011b02270864022600da0225018d0224086300ff0327086203260325022b018c0861014e022a022901470228011b02270860022600da0225018d0224085f00ff0327085e03260325022b018c085d014e022a022901470228011b0227085c022600da085b003200b4085a00d908590032085800d908570032085600d908550032085400d90225018d0224032908530852016f0324085108500170084f03230322084e084d00b4084c084b084a084900320848009a084700320846009a084500320844009a084300320842009a084100320840009a083f0032083e009a083d0032083c009a083b0032083a009a083900320838009a08370032003a032103200836009a083500320834009a0833003200b40832009a083100320830009a082f0032082e009a082d0032082c00d9082b082a031f08290828001300140007000e00220003000d00050004000c08270025001300140007000e00220003000d00050004000c08260025001300140007000e00220003000d00050004000c08250025001300140007000e00220003000d00050004000c08240025001300140007000e00220003000d00050004000c08230025001300140007000e00220003000d00050004000c08220025082100a70820031e038a006501d500f100020092011a0035022303bf006f006c001b0062008c0041081f0240081e022200b90221006d006c001b008c0041024300ca081d01aa003f00aa001e0220081c0001000a0009081b00630091011f0087002f002e004400860023081a000b031d0011001000120001000a00090030006e081900030060000500040021081800240817002d002c001a002b002a0026002900280027001900170018000f000608160015001c0815021f0146005e006b03a100d100020006004500e400360814001600720034014500dc00410813021e0034026401c300f6031c00aa0090003d0101001e08120811004700020035081000fe0020021d001d0039003c004300420058000b031d0011001000120001000a00090030006e080f00030060000500040021080e0024080d002d002c001a002b002a0026002900280027001900170018000f0006080c0015001c01560047000200350001001600c400e00148080b00b5021c080a0809010f00d80808009f003e018e001b00e001660041080700c3022100b0001b03cf00410119001b080600fd08050804006c001b031b08030802001300140007000e00220003000d00050004000c080100250800012f07ff024007fe01d303c203c1008b000203c00045007107fd07fc009407fb07fa00c5021b07f90002028f016b029003c701da0123031a012300da031900640277014607f807f7007f001b005d07f60065011101e302320048005f01c9015f07f5009502a407f4013007f307f207f107f007ef07ee07ed07ec011b031807eb07ea07e900ff07e80144038d016f07e7031707e6006603e607e507e403bb03170316016307e301c8018b07e207e107e007df032807de01e207dd07dc07db07da07d9006501a907d800020062019d0035021a029f021e006d011a0230006f014b019c006f003107d7007f001b0219004100bb0315007e031400c2018f001b00b9021c0161014d00a8004100ec00e0012f07d6018a006d003f00aa001e07d50001000a000907d4026000c100f90087002f002e004400860023000b0011001000120001000a00090030014307d30003011800050004002107d2002407d1002d002c001a002b002a0026002900280027001900170018000f000607d00015001c014200880102015000590002014f0045003600010016009f00340082000802180090007e003407cf004100dc003400dd07ce00f6010507cd021707cc00f6003d00aa001e07cb0119002f002e001d0039003c004300420058000b0011001000120001000a00090030014307ca0003011800050004002107c9002407c8002d002c001a002b002a0026002900280027001900170018000f000607c70015001c0142008800d2010d00590002010c00450036000100160119001b019f003e007f001b0219004100a703f800d1000207c601b20216021b031307c501d3005e006b008b00020006004500dc00340071025e0131006107c400c5021b07c3000201da016b031a012300da031900640277014607c200a7001b005d07c10374031e006501710215000200e4014c0035011a0230006f0223011c006f0065018f0215000200dc014c0035011a032f006f0223019c006f021400d70133021307c00212003f002f002e004402110210000b000601410040005d006207bf07be00a7001b008c00410117020f00c2019e001b008107bd0292020e00b903120311003e003f0072001e07bc007800c80104000907bb00a7001b008c00410117020f00c2019e001b008107ba0292020e00b903120311003e003f0072001e07b9007800c80104000907b8009f00370038007b002f002e0044008000580072000b00110010001200c8010400090152014307b70003011800050004002107b6002407b5002d002c001a002b002a0026002900280027001900170018000f000607b40015011d014200880102015000590002014f0045003600c80016009f003401890008014800fc0140031000ad01bf00e201a600f60105009000920034014500410101003400ca07b307b2018a00aa023e0090006a00bb00e807b1006300200079001d00370038006900520058007207b0000b00110010001200c801040009015207af07ae07ad0003006000050004002107ac002407ab002d002c001a002b002a0026002900280027001900170018000f000607aa0015011d020d00c9008800d2010d00590002010c0045003600c80016030f01880008009f0034030e00fc07a9009f00370038007b002f002e0044008000580072000b00110010001200c8010400090152014307a80003011800050004002107a7002407a6002d002c001a002b002a0026002900280027001900170018000f000607a50015011d014200880102015000590002014f0045003600c80016009f003401890008014800fc003900080140031000ad00fe000801bf00e201a600f60105009000920034014500410101003400dd07a407a3021e00aa0217031c0090006a00bb00e807a20119002f002e001d003700380069005200580072000b00110010001200c8010400090152014307a10003011800050004002107a00024079f002d002c001a002b002a0026002900280027001900170018000f0006079e0015011d0142008800d2010d00590002010c0045003600c800160119001b018800080121003400370008030d030e00fc00390008038b00f60218009000dc003e00a7001b079d00410117020f00c2079c00e000dd079b0161003f00aa001e000a030c079a00fe0091020c0087002f002e004400860023000b030b0011001000120001000a0009003000eb07990003000500040021079800240797002d002c001a002b002a0026002900280027001900170018000f00060796030a0015001c020b0153005e006b018a008b000200060045009f003600010016009f00ea000201010034014001870071013f00920034014500410121003400dd079500f607940309079300b0006a00bb00e8030c079200fe0020021d001d003700380069005200580072000b030b0011001000120001000a0009003000eb0791000300050004002107900024078f002d002c001a002b002a0026002900280027001900170018000f0006078e0015001c030a078d008800d2010d00590002010c0045003600010016078c001b019e021400d70133021302950212003f002f002e004402110210000b000601410040020a078b02090308020800d7003f078a020700d7003f002f002e004402060205000b00060141019f0103004000a8005e030700b50122020403060305007f001b0304078900fd0062078807870786000707850359003e003f01a4001e078400780001000a00090783023d00370038007b002f002e00440080002301a4000b0011001000120001000a000900300782078100030780000500040021077f0024077e002d002c001a002b002a0026002900280027001900170018000f0006077d001500de077c008c005e006b0047000200060045003500010016023d0303077b0095077a0779077800d80260004800950302077707760775077400d801c6077300fb00a6077201c500fb000203a40162006f077100b50770076f030100d8006500fb0002076e076d010700af0033000700ea000203bd004801dd00710300005f00810186000201200071005b0034001b02ff00fd008101860002028a02fe003500bc006500f10002010800af010702fd00e302fc007502fb02fa00c400330062007f02f9007500a7001b008c004101a0001b0081076c00bc037e076b076a02420033003f0072001e076900780001000a00090768007e00370038007b002f002e0044008000580072000b0011001000120001000a000900300185076700030149000500040021076600240765002d002c001a002b002a0026002900280027001900170018000f00060764001500de02a5008c005e006b0047000200060045003500010016007f001b011c021400d70133021302950212003f002f002e004402110210000b000601410040020a076302090308020800d7003f0762020700d7003f002f002e004402060205000b0006014101a20103004000a8005e030700b50122020403060305018e001b0304076100fd006207600330075f075e0007075d023f003e003f0101001e075c00780001000a0009075b01a200370038007b002f002e0044008000230101000b0011001000120001000a00090030075a075900030758000500040021075700240756002d002c001a002b002a0026002900280027001900170018000f00060755001500de0754008c005e006b004700020006004500350001001601a407530752075100d801a200340094075000fb000203a90071006f074f0095074e074d030100d8006500fb0002074c074b00fb00a60002010700af0033000700ea00020124004801dd00710300005f00810186000201200071005b0034001b02ff00fd008101860002028a02fe003500bc006500f10002010800af010702fd00e302fc007502fb02fa00ec00330062018e02f9007500a7001b008c00410065019c00fb000201a0001b074a00c4001b0218020300360749006d012f0748006d07470746036b00750276074501e000aa020e0033003f0072001e074400780001000a00090743007e00370038007b002f002e0044008001250072000b0011001000120001000a000900300185074200030149000500040021074100240740002d002c001a002b002a0026002900280027001900170018000f0006073f0015001c073e0153005e006b036a008b0002000600450092003600010016009200ea0002007e003401ce01870071013f00ca0094073d01bc0034024201840089006a00bb00e8073c006300200079001d003700380069005200230072073b000b0011001000120001000a0009003000ed0185073a00030060000500040021073900240738002d002c001a002b002a0026002900280027001900170018000f000607370015001c020d021f0146005e006b036100d1000200060045007e003600010016025d018900080736073500ed0734018402f80090006a00bb00e80733007f002f002e001d003700380069005200230072000b0011001000120001000a000900300185073200030149000500040021073100240730002d002c001a002b002a0026002900280027001900170018000f0006072f0015001c072e00470002003500010016007f001b018800080092003e00ca02f702f6000202f5014b0035003100a7001b01bc003402f400fd0007012c00ea0002022102030036006d00dd072d016102f301210033003f019f001e000a072c072b00fe0091020c0087002f002e004400860058000b072a0011001000120001000a0009003000eb07290003000500040021072800240727002d002c001a002b002a0026002900280027001900170018000f0006072602f20015001c020b0153005e006b0276008b000200060045007e00360001001601bc0103072500b507240723072200d8030d00fc00b5030201ce00ad07210720010f071f071e016600d8071d012c003401450041007e00ea0002011701dd071c071b071a0034071900dc003401a6018700710718013f00dd0717014800b00716013f0309071502f1006a00bb00e80220071400fe0020021d001d003700380069005201250072000b019b0011001000120001000a0009003000eb07130003000500040021071200240711002d002c001a002b002a0026002900280027001900170018000f000607100015001c070f020b0153005e006b018a008b000200060045009f003600010016009f00ea000200dc0034014001870071013f00ca0094070e007e0034023f01840089006a00bb00e8070d006300200079001d003700380069005200230072070c000b0011001000120001000a0009003002f0022f070b00030060000500040021070a00240709002d002c001a002b002a0026002900280027001900170018000f000607080015001c020d021f0146005e006b022000d100020006004500dc003600010016025d018900080707070602f00705018407040090006a00bb00e8070300ec002f002e001d003700380069005200230072000b0011001000120001000a00090030022f07020003019b000500040021070100240700002d002c001a002b002a0026002900280027001900170018000f000606ff0015001c06fe0047000200350001001600ec001b01880008009f003e00ca02f702f6000202f5014b003500310119001b007e003402f400fd0007015800ea000202f802030036006d00dd0397016102f301210033003f0117001e000a021706fd00fe0091020c0087002f002e004400860058000b01180011001000120001000a0009003000eb06fc000300050004002106fb002406fa002d002c001a002b002a0026002900280027001900170018000f000606f90140001500de06f8008c005e006b0047000200060045003500010016007e0103009f016906f7006106f606f5016e00d800f1000201c9007106f4001f01ce00ad06f303d8004102f206f206f101bf003200b4027f06f000900343003406ef0041025e06ee003e030f0168004106ed00a7001b031b06ec06eb06ea06e901a906e806e70121003e01dc001b0219004100bb03150117031400c2021c0106014d00a80041007206e6022d06e5011c001b06e4008806e306e200a500a4020200a300a2005c00a500a406e100a300a2005c001300140007000e00220003000d00050004000c06e00025001300140007000e00220003000d00050004000c06df0025001300140007000e00220003000d00050004000c06de0025001300140007000e00220003000d00050004000c06dd0025001300140007000e00220003000d00050004000c06dc0025001300140007000e00220003000d00050004000c06db0025001300140007000e00220003000d00050004000c06da0025001300140007000e00220003000d00050004000c06d90025001300140007000e00220003000d00050004000c06d80025001300140007000e00220003000d00050004000c06d70025001300140007000e00220003000d00050004000c06d60025001300140007000e00220003000d00050004000c06d50025001300140007000e00220003000d00050004000c06d40025001300140007000e00220003000d00050004000c06d30025001300140007000e00220003000d00050004000c06d20025001300140007000e00220003000d00050004000c06d10025001300140007000e00220003000d00050004000c06d00025018300a500a406cf00a300a2005c00a500a402ef00a300a2005c006c013e013d0007000e013c013b000d00f500f4000c06ce0182040306cd06cc06cb0007000e06ca03f9000d00f500f4000c06c9006106c806c701b7028402ee0236004000ee025b025a0181006d06c60269006c013e013d0007000e013c013b000d00f500f4000c06c50182006c013e013d0007000e013c013b000d00f500f4000c06c40182006c013e013d0007000e013c013b000d00f500f4000c06c30182006c013e013d0007000e013c013b000d00f500f4000c06c2006106c106c001b7028402ee0236004000ee025b025a0181006d006c01d70269012f06bf06be009006bd03e3005f06bc06bb00e403ed002f002e0037003801d7007b0080005c001300140007000e00220003000d00050004000c06ba0025001300140007000e00220003000d00050004000c06b90025001300140007000e00220003000d00050004000c06b80025001300140007000e00220003000d00050004000c06b70025001300140007000e00220003000d00050004000c06b60025001300140007000e00220003000d00050004000c06b50025001300140007000e00220003000d00050004000c06b40025001300140007000e00220003000d00050004000c06b30025001300140007000e00220003000d00050004000c06b20025001300140007000e00220003000d00050004000c06b10025001300140007000e00220003000d00050004000c06b00025001300140007000e00220003000d00050004000c06af0025001300140007000e00220003000d00050004000c06ae0025001300140007000e00220003000d00050004000c06ad0025001300140007000e00220003000d00050004000c06ac0025001300140007000e00220003000d00050004000c06ab0025001300140007000e00220003000d00050004000c06aa0025001300140007000e00220003000d00050004000c06a90025001300140007000e00220003000d00050004000c06a80025020106a7009506a600a606a506a40032001700c300f006a306a2003106a106a0069f0085020101bd028900fc00e30108004802ed007001bb0048021a007001ba004802ec007001be0048069e007002610048069d0070069c0048069b007002eb0048069a007002ea00480699007002e9004806980070020000480095012202040697007002e800480696007002e7004801bd02e600700695004802e5007006940048069300700692023b001b003e008506910690068f02e6068e007002e50095068d0164068c068b03ae03ad03220332068a0689012300ad02e400e203a500ad02e4068800e2026800ad033800e203a600ad068700e2068601ff01fe0685068402e3006600e20683013100610682016501fd01fc00ff0144018b01cc068101fb00da01fa01ff01fe03a700ad02e20680006402e101310061067f016501fd01fc00ff0144018b01cc067e01fb00da01fa01ff01fe067d00ad02e2067c006402e101310061067b016501fd01fc00ff0144018b01cc067a01fb00da0679003200b40678006406770032067600640675003206740064067300320672006401fa06710670066f066e01d400e000cc0303066d0095066c00f700c30169066b00b4066a006602a30669003206680064066700320666006406650032066400640663003202e30064066200320661006406600032065f0064065e0032065d0064065c0032065b0064065a00320659006406580032003a032103200657006406560032065500640654003200b406530064065200320651006406500032064f0064064e00ad064d00e2064c064b0376064a0085064900b90648064700330085020101bd028900fc00e30108004802ed007001bb0048021a007001ba004802ec00700316023c001b003e00850646018001f90065064506440247003602460643005f01ab005f015a005f0159005f06420200005b02e9005b02ea005b02eb005b01ba005b01bb005b01a5006f0031023a01a502e000e00154029e0641003f00aa001e064002380078063f01b9063e009102370087002f002e004400860023000b0011001000d00012000f0006063d063c01d2001301b8063b02df02de02dd02dc01ca063a00610639026f027c0169027b027a004001d1026e026d0181003e011000cd0259008800d2010d02db00590076010c011601f8003500f80099017f063806370047009902da0636063501c600f70275063406330632063100cb06300378062f0095017e062e062d062c00760254062b062a06290628008b007600710627062601310625062401c6009900ae062301f706220293009900c300b000ae062101f8001b01b400470076025701b301b2021600810620061f00f0012202560059007602550116003601a30254061e0095061d00a6008102530076025200710251001f0250001f024f001f024e001f024d001f024c001f01c7001f024b001f024a001f0249001f01b1001f01b0001f01af001f01ae001f01ad001f0120001f005b061c007000c30088061b00cb061a01f8001b00ae01f6015f02580619001b00b90618028d0617061601a3003400f001f60615003e0614001b00ae01f6015b033c061301f5001b0154033b025c00b9033a003e003f023100aa001e061202380078061101b90610009102370087002f002e004400860058000b0011001000d00012000f0006060f060e01d2001301b8060d02df02de02dd02dc01ca060c0061060b026f027c0169027b027a004001d1026e026d0181003e01100282060a008c005e006b0047007600060116003500f80099000101150609008b009902da060806070606009906050115021500760268016206040132009906030602016a01c8026c03b703df06010600032305ff03b505fe018c017e0334010e007605fd01df03ef01df05fc00df007600d305fb05fa05f9009905f8016305f702d902d805f6014702d702d605f505f405f3038c05f2006600d4009905f103ba02d501c8026c03b805f003b9016403b6033603b40163017e03b300d4007603b203b103b005ef015405ee031f05ed05ec00df007605eb011600d305ea05e905e8009901d805e702d902d805e6014702d702d605e505e402d40123032405e3006600d4009905e202d301ca016405e105e005df05de013005dd027205dc003a017e05db008b007602d302d205da02d200ca02d405d905d805d700d4007605d60116016b05d505d402d5009900b505d305d200a605d105d000ff014400c300e705cf05ce003100d502d1001b02d0022205cd02cf019d001b01f9014c001b03c3014b001b05cc014d01b401f500e001f403dd02ce003f05cb009b05ca05c90001000a000905c8009e026505c7007b002f002e004400800023009305c6000b05c50011001000120001000a000900510057009d05c40056009c00550054005305c3003a05c20050004f001a004e004d0049004c004b004a001900170018000f0006017d05c1017c0015001c00b80151005e006b007700760006011600730001011500d601800082009905c000a1006a009b05bf00740020008a001d00370038006900520023009302cd000b02cc0011001000120001000a000900510057009805be0056009700550054005305bd003a05bc0050004f001a004e004d0049004c004b004a001900170018000f0006017d05bb0015001c017c00c700ba007600c600010115007a01f305ba00e9006a009b05b9009e002000b7001d00370038006900520023009301f2000b01f10011001000120001000a000900510057009d05b80056009c00550054005305b7003a05b60050004f001a004e004d0049004c004b004a001900170018000f0006017d05b50015001c017c00b800770076007300010115022c05b400a1006a009b05b301f000740020008a001d00370038006900520023009301ef000b01ee0011001000120001000a000900510057009805b20056009700550054005305b1003a05b00050004f001a004e004d0049004c004b004a001900170018000f0006017d05af0015001c017c01ed01c20047007600350001011505ae0076007a02e700af02e805ad00e3020000bc024502f101cb02cb005f024405ac005f01ab02d1015a02ca005f015905ab005f012802c9005f01270270005f00d5028301f700aa010700bc02c80033008500a500a4020200a300a2005c00a500a4012e00a300a2005c00e1005c001300140007000e01140003000d00050004000c05aa013a001300140007000e01140003000d00050004000c05a9013a001300140007000e01140003000d00050004000c05a8013a001300140007000e01140003000d00050004000c05a7013a001300140007000e01140003000d00050004000c05a6013a001300140007000e01140003000d00050004000c05a5006105a4010a00f300b100c000bf004000be00cf00ce00bd006d010900370038007b0080005c05a3000705a205a103e200af032d005b0031024101f400e9006a02c7009b02c605a000780001000a0009059f009e002000b7001d00370038006900520023009302c5000b02c40011001000120001000a000900510057009d059e0056009c005500540053059d003a059c0050004f001a004e004d0049004c004b004a001900170018000f0006059b017b0015001c00b80151005e006b0077017a0006059a0073017f059900d6008202c3039c0263003d001e059800740020008a001d0039003c0043004200230597000b05960011001000120001000a00090051005700980595005600970055005400530594003a05930050004f001a004e004d0049004c004b004a001900170018000f000605920015001c017b00c700ba017a00c6000102c2007a008202c3026402c102c00262003d001e0591009e002000b7001d0039003c00430042005802c5000b02c40011001000120001000a000900510057009d05900056009c005500540053058f003a058e0050004f001a004e004d0049004c004b004a001900170018000f0006058d0015001c017b058c0047017a0035000102c200f1017a00d6010800af010700bc0106008500e1005c00a500a4012e00a300a2005c001300140007000e058b0003000d00050004000c058a00610589010a00f300b100c000bf004000be00cf00ce00bd006d010900370038007b0052005c001300140007000e02bf0003000d00050004000c05880587001300140007000e02bf0003000d00050004000c058600610585010a00f300b100c000bf004000be00cf00ce00bd006d010900370038007b0080005c058402be00650583058201ac00360373003103720031037100310247003102460031037000310245003101cb00310244003101ab0031015a003101590031012800310127003100d50031012b0031006f036f036e036d0267026600ac02bd003f001e0581058000780001000a0009057f0074009102bc0087002f002e004400860023057e000b057d0011001000120001000a0009005100570098057c00560097005500540053057b003a057a0050004f001a004e004d0049004c004b004a001900170018000f0006057900840015001c00c70578005e006b00ba007d000602bb00c6017f0577007a0576024100e9004600a9003d001e0575009e002000b7001d0039003c00430042002302ba000b02b90011001000120001000a000900510057009d05740056009c0055005400530573003a05720050004f001a004e004d0049004c004b004a001900170018000f000605710015001c008400b80077007d00730001008f0570056f00b301790369056e00ac056d01c0003e00ac02b8003f001e056c011e01a80009056b056a0074009102bc0087002f002e00440086005801ec000b01eb001100100012011e01a800090051056900980568005600970055005400530567003a05660050004f001a004e004d0049004c004b004a001900170018000f00060565008405640015011d00c700ba007d00c6011e008f007a009400d2028e02db008802b7033102d0036702ce00ac02bd003f001e0563000a0562009e009105610087002f002e0044008600230560000b055f0011001000120001000a000900510057009d055e0056009c005500540053055d003a055c0050004f001a004e004d0049004c004b004a001900170018000f0006055b00840015001c00b80077007d00730001008f00d602580082017901a700a10046055a003d001e055900740020008a001d0039003c00430042002301ec000b01eb0011001000120001000a00090051005700980558005600970055005400530557003a05560050004f001a004e004d0049004c004b004a001900170018000f000605550015001c0084015e036600df007d00d30001008f0554036501790364036302b602b50164055303620046055205510157003e00ac02b8003f001e0550054f054e00630091011f0087002f002e004400860125054d000b054c0011001000120001000a00090030006e054b00030060000500040021054a00240549002d002c001a002b002a0026002900280027001900170018000f00060548008402b602b505470015001c015d0151005e006b0077007d000602bb00730001008f015c00940102036000e702b70546035f035e035d054505440543035c0542035b00a1004600a9003d001e054100740020008a001d0039003c00430042002301ec000b01eb0011001000120001000a0009005100570098054000560097005500540053053f003a053e0050004f001a004e004d0049004c004b004a001900170018000f0006053d0015001c008400c700ba007d00c60001008f007a0352035a00e9004600a9003d001e053c009e002000b7001d0039003c004300420023053b000b053a0011001000120001000a000900510057009d05390056009c0055005400530538003a05370050004f001a004e004d0049004c004b004a001900170018000f000605360015001c008405350388007d05340001008f00d6035003580533004600a9003d001e0532053100200530001d0039003c004300420023052f000b052e0011001000120001000a000900510057052d052c0056052b005500540053052a003a05290050004f001a004e004d0049004c004b004a001900170018000f000605280015001c008405270077007d00730001008f05260525035700a1004600a903990090004602b4003d001e052400740020008a001d0039003c0043004200580523000b05220011001000120001000a00090051005700980521005600970055005400530520003a051f0050004f001a004e004d0049004c004b004a001900170018000f0006051e0015001c008400c700ba007d00c60001008f007a0180035400e9004600a902c00090004602b4003d001e051d009e002000b7001d0039003c00430042005802ba000b02b90011001000120001000a000900510057009d051c0056009c005500540053051b003a051a0050004f001a004e004d0049004c004b004a001900170018000f000605190015001c008400b80077007d00730001008f00d60355035300a1004600a9003d001e051800740020008a001d0039003c00430042002302cd000b02cc0011001000120001000a00090051005700980517005600970055005400530516003a05150050004f001a004e004d0049004c004b004a001900170018000f000605140015001c008400c700ba007d00c60001008f007a01f3035100e9004600a9003d001e0513009e002000b7001d0039003c0043004200230512000b05110011001000120001000a000900510057009d05100056009c005500540053050f003a050e0050004f001a004e004d0049004c004b004a001900170018000f0006050d0015001c008400b80077007d00730001008f00d602b3034f00a1004600a9003d001e050c00740020008a001d0039003c004300420023050b000b050a0011001000120001000a00090051005700980509005600970055005400530508003a05070050004f001a004e004d0049004c004b004a001900170018000f000605060015001c008400c700ba007d00c60001008f007a01ea034e00e9004600a9003d001e0505009e002000b7001d0039003c00430042002301f2000b01f10011001000120001000a000900510057009d05040056009c0055005400530503003a05020050004f001a004e004d0049004c004b004a001900170018000f000605010015001c008400b80077007d00730001008f022c01a700a1004600a9003d001e050001f000740020008a001d0039003c00430042002301ef000b01ee0011001000120001000a000900510057009804ff0056009700550054005304fe003a04fd0050004f001a004e004d0049004c004b004a001900170018000f000604fc0015001c008401ed01c2034d0047007d00350001008f007a034c0179029602970248007d01ac0036004600a90033005a00c202c80033005a01a503470033005a034b01a30033005a034a04fb0033005a023c02cf0033005a034803490033005a02a202390033005a034602310033005a026b04fa0033005a0345027f005a034401f70033005a01d4032b003300ac04f901000342003e034101a101000340003e033f01a10100033e003e005a023b033d0033005a008500e1005c00a500a4012e00a300a2005c001300140007000e00830003000d00050004000c04f8006104f7010a00f300b100c000bf004000be00cf00ce00bd006d010900370038007b0080005c001300140007000e00830003000d00050004000c04f6008e001300140007000e00830003000d00050004000c04f5008e001300140007000e00830003000d00050004000c04f4008e001300140007000e00830003000d00050004000c04f3008e001300140007000e00830003000d00050004000c04f2008e001300140007000e00830003000d00050004000c04f1008e001300140007000e00830003000d00050004000c04f0008e001300140007000e00830003000d00050004000c04ef008e001300140007000e00830003000d00050004000c04ee008e001300140007000e00830003000d00050004000c04ed008e001300140007000e00830003000d00050004000c04ec008e001300140007000e00830003000d00050004000c04eb008e001300140007000e00830003000d00050004000c04ea008e001300140007000e00830003000d00050004000c04e9008e001300140007000e00830003000d00050004000c04e8008e02b2008104e704e601b1007101b0001f01af001f01ae001f01ad001f0120001f005b04e501f404e404e302b102b0005f006a02c7009b04e204e100780001000a000904e0009e002000b7001d00370038006900520058009304df000b04de0011001000120001000a000900510057009d04dd0056009c00550054005304dc003a04db0050004f001a004e004d0049004c004b004a001900170018000f000604da01130015001c00b80151005e006b007700fa000604d90073017f04d800d601f3039600a101c0017800b0006a009b04d700740020008a001d00370038006900520058009304d601c104d50011001000120001000a000900510057009804d40056009700550054005304d3003a04d20050004f001a004e004d0049004c004b004a001900170018000f000604d10015001c011300c700ba00fa00c600010139007a02b3039500e902b1017800b0006a009b04d0009e002000b7001d00370038006900520058009304cf01c104ce0011001000120001000a000900510057009d04cd0056009c00550054005304cc003a04cb0050004f001a004e004d0049004c004b004a001900170018000f000604ca0015001c011300b8007700fa00730001013900d601ea039400a1006a009b04c900740020008a001d00370038006900520023009301ef000b01ee0011001000120001000a000900510057009804c80056009700550054005304c7003a04c60050004f001a004e004d0049004c004b004a001900170018000f000604c50015001c011300c700ba00fa00c600010139007a008204c404c302c104c2017802af003d001e04c1009e002000b7001d0039003c00430042005804c001f2000b01f10011001000120001000a000900510057009d04bf0056009c00550054005304be003a04bd0050004f001a004e004d0049004c004b004a001900170018000f000604bc0015001c011304bb00b8007700fa007300010139031804ba026204b9026304b8017802af003d001e04b704b600740020008a001d0039003c00430042012504b5000b04b40011001000120001000a000900510057009804b30056009700550054005304b2003a04b10050004f001a004e004d0049004c004b004a001900170018000f000604b00015001c011304af01c2004700fa00350001013901c400fa007a026100af01be00bc0128038f012702ca005f00d502c9005f012b02cb005f0106008500a500a4012e00a300a2005c00e1005c001300140007000e01120003000d00050004000c04ae0138001300140007000e01120003000d00050004000c04ad0138001300140007000e01120003000d00050004000c04ac0138001300140007000e01120003000d00050004000c04ab0138001300140007000e01120003000d00050004000c04aa0138001300140007000e01120003000d00050004000c04a9006104a8010a00f300b100c000bf004000be00cf00ce00bd006d010900370038007b0080005c02b201f9037701ea02e004a704a601f501b301b2021600dd04a5016601220256005902ae025504a40036023904a3009404a200a60081025302ae025200710251001f0250001f024f001f024e001f024d001f024c001f01c7001f024b001f024a001f0249001f01b1001f01b0001f01af001f01ae001f01ad001f0120001f005b0313007000c3008804a100cb02c601f004a0001b00ae01e9015f0180049f001b00b902b0028d027001ed017b024300f001e9049e003e022200ae01e9015b049d049c049b008500a500a4020200a300a2005c00a500a4012e00a300a2005c020a049a02090499020800d7003f0498020700d7003f002f002e004402060205000b0006049700400085018300a500a402ef00a300a2005c018302be049604950494049300a6049204910490048f048e022d00ae048d00c100f90109006a0037003800690052048c0093000b0006048b004000850183048a02ad008500a60085048902ad008500a60085048800b2005c00000000000001e80000000000000487000000000000048604850000000000000000000002ac00000000000000000484048300000000000004820000048100000000000000000480000000000000047f000000000000047e000000000000047d000000000000047c000000000000047b000000000000047a0000000000000479000000000000047800000000000004770000000000000476000000000000047500000000000004740000000000000473000000000000047200000000000004710000000000000470000000000000046f000000000000046e000000000000046d000000000000046c000000000000046b000000000000046a04690468046704660000000004650000000000000000009602ab0096009601e70000000000000464000001e8009600960463000000000000000000000462000002ab0096009600960461000000000000000000000460000000000000045f000000000000045e000000000000045d0000000000000000045c000000000000045b045a000000000000000000000459000004580000000000000457000000000000045600000000000004550000000000000000000002aa000004540000000000000000000004530000045200000000000000000000000004510450000000000000044f000000000000000000000000044e000000000000044d01e6000002aa0000044c00000000000001e8009600960096044b000000000000044a0000000000000449000000000000044800000000000000000000000004470446000000000000044504440443044201e6000002ac000004410440043f043e043d000000000000000000000000043c00000000043b043a04390438043700000436000000000000043500000000000004340000000000000433000000000000043200000000000004310000000000000430000000000000042f000000000000042e000000000000042d00000000000000000000042c0000042b00000000000000000000042a00000000000000000429000000000000042800000000042700000000000000000426042500000000000004240000000000000423000000000000042200000000000000000000042101e70000000000000420000000000000041f041e000000000000041d000000000000041c000000000000041b000000000000041a0000000000000419000000000000041800000000000004170000000000000416000000000000041500000000000004140000000000000413000000000000041200000000000004110000000000000410000000000000040f000000000000000000000000040e00000000040d0000000000000000040c00960096009601e7000000000000040b000000000000040a0000000000000409000000000000040801e600000000000000000000000000000407040604050404000000000000", - "logIndex": 21, - "blockHash": "0x00c8980923ce93732373f6e10773875b41b98308271c9d301738a75662fba4ed" + "data": "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000da420d1b0000000000000000000000200030008c000000000701034f0000000008980436000000007907043c000006870000213d0000000100200190000000400200043d0000002004000039000000000403401936b536b00000040f000000000048004b000000000462001900000000030100190000000008020019000200000001035500000060033002700000001f0530018f00000db00630019800000dae033001970000005b0000213d0000001f014000390000000000650435000000000003001f000000000686019f00000000080504330000005b0000413d000000600110018f00000dae0020009c00000dae020080410000004001100210000000000058004b0000064b0000613d0000001f074001900000064b0000013d00000db3011001c7000000000606043b00000000067601cf000000000676022f0000010007700089000000000878022f00000000087801cf0000000307700210000000000661034f00000020064001900000000001010433000000000112019f00000dae0100804100000dae0010009c00000dae010000410000000000320435000000c00220021000000000020004140000000006060433000000000004043500000000010004140000000002020433000000400010043f000000c00110021000000000000204350000268a0000a13d000000000006004b00000000000304350000005b0000c13d000000040020008c000000400020043f000000000205001900000000080a001900000000056a0019000006870000c13d000000000101043b000000040050008c00000dae00a0009c00000dd10010009c000000000067043500000dd10020009c00000000002104350000000000120435000000000707043b0000001c020000290000004002200210000000000059004b00000000066701cf000000000767022f0000010006600089000000000868022f00000000086801cf0000000306600210000000000771034f0000001f0640018f0000000009a90436000000008a08043c000000000801034f00000dd9011001c7000000200740019000000000020000390000000003030433000000000001004b00000dae00b0009c0000001d01000029000000600d0000390000000102004039000000000121019f000000400100043d000000000300003100000000010a401900000000020b04330000004000b0043f000000000002004b00000dd100b0009c00000000001404350000000000340435000036b70001043000000000002a043500000000010b4019000000000012004b000000000001043500000db10020009c00002d0d0000213d0000001a050000290000001b020000290000001805000029000000000005004b00000db10220019700000000002b0435000000400040043f0000000002000019000033720000213d0000001c0a00002900000dae0040009c0000001a070000290000001906000029000000400030043f0000000000230435000033830000613d0000000e05000029000000000031004b00000000020700190000004000a0043f000000000003004b0000000001000416000033830000013d000033700000413d000000170200002900000000020a0433000000040070008c0000002002200039000000000042004b00000000090b001900000000057b0019000000000001042d00000dae00c0009c000000000113019f00000dd100a0009c000000400300043d00000dd10040009c0000000003000019000000000707043300000db101100197ffffffffffffffff00000000090c001900000000057c001900002d130000213d000000110600002900000000006c0435000000190200002900000dae0400804100000000080b001900000000056b001900000dae0200004100000000005104350000001d02000029000000000004004b000000000041004b000000000021004b000000000bc1001900000000040004140000001d08000029000000000ab10019000000000010044300000e2501100197000000000042043500000db10660019700000dd10050009c00000040021000390000001a0100002900000000010c401900000000002404350000001d06000029000000180200002900000040033002100000004000c0043f000000c003400210000000000400003900000000060000190000000001000039000000000400001900000016020000290000000401300370000036b60001042e00000dd100c0009c000000000131019f0000001b0a0000290000001d0a00002900000000001a043500000dd901000041000000040010043f000000000010043f00000e13010000410000001c01000029000000400050043f0000000001000412000000040040008c000000000cb1001900000000020c043300000dde0010009c000000600030008c0000001d0010006c0000001c040000290000000002a10019000000000201043300000dae03000041000000000ba1001900000000003104350000000008000019000000000023004b00000dae0030019d00000db10010009c00000000010000190000000d0700002900000000002c0435000026900000c13d00000000006b04350000001701000029000000190100002900000100033000890000001708000029000000400400043d000000600210018f0000001b010000290000001a020000290000000001a10019001b00000002001d0000001709000029000000400030008c000000400a00043d000000200210003900000060021000390000008002100039000000000045043500000dea0030009c000000000161019f0000010005500089000000000656022f00000000065601cf0000000006040433000000400310003900000017056000290000000004040433001700000001001d0000000001020433000000010010019000000001010040390000000000d1043500000000040204330000001402000029001c00000002001d000000a002100039000000c00210003900000dfd0010009c00000000004304350000000000050435000026890000613d00000000015101cf000000000151022f00000dd10070009c000000000032004b000000000078043500000000050000190000360e0000213d00002d200000613d00002d130000413d00002d0d0000c13d00000dde0020009c000026900000413d00000e250660019700000001004001900000000104004039000000000014004b000000600400003900000000005204350000002003100039000000160300002900000ddd011001c7000000e00110018f00000000020a4019000000e002100039000000150200002900000020043000390000001d05000029000000000151019f00000020011000390000000000350435000080050200003900000df8011001c7000000040010044300000dcf010000410000001f0130003900000dd10080009c000000200010008c001d0000000a001d000000030550021000000dae0300804100000dae0030009c00000dd10060009c000000160100002900000001055000390000365d0000613d000000060500002900002d200000013d0000000008180436000000007107043c0000000c020000290000001102000029000000200cc00039001700000004001d0000001a0a000029000000000051004b0000001401000029001d00000009001d001a00000001001d00000000000704350000001c0500002900000ddf02000041000000000072043500000ddb02000041000000600640019000000040040000390000010002100039000001200210003900000140021000390000018002100039000001a0021000390000006001300210000000000161034f000000a002200039000000000068004b00000dd50010009c000000000141034f000000000053004b0000000501100270001c00000001035300000db10040009c000000000034004b00000020088000390000000003000039000000800010043f0000006001000039000000440040008c001d00000002001d000000800200043d000000240040008c000000007807043c0000365d0000013d000036140000413d00002a730000a13d0000000c010000290000000c0a000029000000000001042f000000120100002900000017041000290000001d0020006c000000000d0d04330000002002400039000000130200002900000020012000390000004001200039000000000c0000190000001804000029001900000001001d00000000030a401900000dd10030009c000000030350021000000000010504330000001803000029001800000002001d0000000001b10019000000400b00043d000000010330003900000000009204350000000402b000390000000402a00039000000010400c03900000000020b401900000000001b004b000001600210003900000040043000390000004101000039000000a0043000390000008003100039001c00000001001d000000000502043300000000050404330000000000a90435000000000a0a0433000000000008004b000000000900001900000000014101cf000000000141022f000001000440008900000e25043001980000000006050433000000240010044300000dd20550019700000deb0060009c0000000001000415000000000026004b0000002003000039001d00000001001d000000000009004b00000000050504330000000008080433000000000105034f00000db10030009c000000240130037000000db1033001970000002002000039000000000202043b0000000704000029000033700000213d00002e570000213d0000000b0500002900002d130000c13d0000001f0030008c000000000a87001900000000095800190000001c0700035f00000db10510019700000e1002000041000000130400002900000dde0030009c00000e000010009c001800000004001d00000e000020009c0000001a021000290000001a080000290000001a05600029000000190400002900000000070c0433000000400500043d000000000909043300000000000a004b00000000000604350000000501200210000000000027004b00000012020000290000001002000029000000600310018f000000000009001f000000000363019f00000000033701cf000000000737022f000000000708043b000000000636022f00000000063601cf0000000303700210000000000861034f0000000008380436000000007307043c0000000004094019000000200090008c00000dae09300197000000600120003900000deb03008041000000000535022f00000005010000290000001704000029001000000002001d00000005015002100000001f0180003900000000013101cf000000000131022f000000400900043d000000000071004b000000400c00043d00000060031000390000000001090433000000a00310003936b536ab0000040f0000001d04000029001900000002001d000000000054043500000005023002100000000f030000290000000b03000029000001c003100039000b00000002001d000c00000002001d000d00000002001d0000000f0b000029000f0000000b001d0000001b0400002900000004014000390000002401400039001c00000004001d0000000004a1001900000000001b0435001100000001001d0000000002090019000000040090008c000000000071043500000dd70200004100000060043000390000008004300039000000c00430003900000df10010009c0000000201000367000000800100043d000000000545022f00000000054501cf0000000304500210000000000045004b00000db10050009c0000000014010434000000000304c01900000deb03004041000000000653013f00000deb0330019700000deb0520019700000deb0400804100000000030204330000001b03000029000000000052004b000000800120003900000e25022001970000000006020433000000010100c0390000004002200039000000000404043b00000e250aa001970000000000560435000000400060043f0000000002210436001600000001001d000000000201043b000000000063043500000020044000390000001a04000029000000000223034f0000005b0000813d36b5368d0000040f00000dcf0200004100000005044002100000000004000415000000440300003900008005010000390200000200000000ffffffffffffffe000000000ffffffff0000000402c00039001100000006001d000000110b00002900110000000b001d00002e800000613d0000000205000029000000040300002900000003030000290000000503000029000000020b00002900020000000b001d000000020c00002900020000000c001d000500000002001d000000000b000019000600000002001d0000001f06600039000000000756001900000000056504360000000006350049000000000556001900000160031000390000000043010434000026ff0000613d00000db0061001980000001f0510018f00000000053501cf0000001101000029000000010300c0390000800b0200003900000e07011001c700000e060100004100000e0801000041000000020010008c000000010010008c000000000025043500000020045000390000000d0120002900000dfe0010009c000900000001001d000000040450003900000000020904330000000001020436000000a00710003900000000069600190000001f06a0003900000000069a00190000000000ac004b0000000000d60435000000000dcb001900000000069c00190000000009a604360000000007870436000000006806043c000000000601034f00000000011200190000000001a30019001300000001001d00000018010000290000003f01100039000000000103c01900000deb0100404100000deb0110019700000008030000290000000703000029000a00000002001d001100000002001d001a00000005001d000000200700008a000000050130021000000000040a0019000000000249001900000dae0090009c00000000002904350000006003200039000000000a0000190000003f0540003900000019090000290000001d090000290000000000dc04350000001903000029000000c00310003900000000004b043500000e1d0400004100000000001a004b001d00000005001d00000000010604330000001c0300002900000017030000290000000d030000290000000c03000029000001e004100039000000ff0330018f000000100300002900000200031000390000022003100039000000ff0020008c00000de70200004100000de60200004100000de50200004100000de402000041001700000002001d00000de30200004100000de20200004100000de101000041001b0000000a001d00000de0020000410000001c0b000029001d00000008001d0000002001000039000000000204043300000004024000390000002402400039000000ff0010008c001000000001001d00000000010a043300000dda010000410000000401a0003900000dd801000041001300000002001d000000e00430003900000100043000390000012004300039000001400430003900000160043000390000018004300039000001a004300039000001c004300039000001e0043000390000020004300039000002200430003900000dd50030009c000006870000013d000006590000013d0000006001100210000000400320003900000000033204360000002003300039000000800420003900000dd30010009c000000200660003900000deb0900804100000220021000390000000007000019000000190500002900000000098904360000001f0630018f00000040041000390000000201000029000000400080043f00000deb0200404100000deb02200197001b00000001001d000000400100003900000000030004140000002004200039000000000046004b0000000104400039000000010600c03900000000060000390000000000760435000000010030019000000001030040390000003f02100039000002390000613d00000dec0100004100000df6010000410000001901200029000000040210003900000023021000390000000006860436000000000703034f000000400090043f000000000301034f00000044000000007fffffffffffffff000000040000000000000001020000390000000000460435000300000002001d000400000002001d000000200900003900000ddc08000041000033700000c13d000000110c00002900110000000c001d000033720000c13d00000000001c004b00002e800000013d00000000004c043500002e550000413d00002e550000213d000000010c00002900010000000c001d00000020032000390000000603000029000000050b00002900050000000b001d000000060c00002900060000000c001d00000000020c401900000000001c0435000800000001001d0000000000a2043500000e25077001970000001f0740003900000000077a0019000000000028004b000000200bb00039000000000cab00190000000d0200002900000007060000290000000805000029000800000005001d000000000081004b000700000006001d00000df907000041000c0000000a001d00000040011000390000006009000039000400000001001d00000000760704340000000000680435000000c007100039000000800710003900000060071000390000004007100039000001a0031000390000018003100039000001400310003900000120031000390000010003100039000000600420003900000040042000390000005101000039000026ff0000013d0000001c0160035f000026b10000613d00000db00680019800000000090800190000001f0580018f000000320100003900000001022000390000000f010000290000000401200039000000000112004b00000e00011001970000271b0000813d00000e0c0020009c000000130300003900000e0b0400004100000020013000390000000002210019000000000021001a00000e000330019700000e0a0010009c0000270f0000613d0000000b02000029000000170000006b001100000004001d0000001301000029000000000401601900000000002301700000000102002039000027150000c13d000000170210002900000012040000290000000004450436000000130500002900000040055000390000000402300039001a00000003001d00000000022304360000001b021000290000001b080000290000001b056000290000001d030000290000000000130435001d00000000001d00000000008904350000000000980435000000000242001900000008010000290000000003230436001600000005001d000000150400002900000dae0050009c001700000005001d000000010660003900000000010b0433000000000091004b000000010990003900000df90800004100000000009a004b000000000095043500000000ba0904340000000000ab0435000000000a560049000000000b0b0433000000000956004900000000060c043300000000009a04350000003f03100039000000000063004b00000000004104350000000f02000029000000190a00002900000db102100197001200000001001d0000001f01500039000000009808043400000deb0090009c0000000001bc001900000deb00a0009c0000001f01900039000000600620003900000000030940190000000402000029000000040290003900000e20020000410000000a030000290000000903000029000700000002001d00000000020a0019001c0000000a001d001d00000006001d000000000662019f000f00000001001d001d00000004001d00000000060a001900000db105200197001200000003001d000000000223001900000dd2022001970000000001a20019001a0000000a001d0000000601100029001600000003001d00000000031400190000000003350436000000050430021000000000130104340000001f03100039000000000104043300000000029100190000000004090019000000000434022f00000000043401cf0000001f058001900000000006360436000000005305043c0000000006090019000000000501034f00000dae08300197000000040010008c000500000001001d00000040014000390000008003200039000001000320003900000120032000390000014003200039000001600320003900000001077000390000000000a1004b00000000006a004b000000010aa0003900000df90900004100000100081000390000001104000029001a00000000001d0000001205000029001200000004001d00000000000804350000004008700039000000400700043d000000000e0000190000001f02d000390000000002060019000000040060008c000000140a00002900140000000a001d00000dda0200004100000df40200004100000df3020000410000000401b0003900000df201000041001b00000003001d000000180a00002900180000000a001d00000e1b04000041000000180b00002900180000000b001d000000000501043b0000000101100367000000150300002900000000020604330000000e03000029000000120300002900000011030000290000000b0a000029000b0000000a001d000f00000002001d000000000a010019001c0000000b001d000000080020008c000000ff0220018f000000010240003900000000024201cf000000000104401900000ddc0100004100000000040b0019000000090010008c000000ff0110018f0000000101100039000000000882019f00000000021201cf00000dde0040009c00000ddc0200004100000000090b04330000001d0b000029001d0000000b001d001a00000007001d00000dd601000041000001c002100039000001e0021000390000020002100039001400000002001d001500000003001d001800000005001d000000000024004b000000200510003900000060051000390000002004100039000000a001100039000005460000613d0000000006010433000000000401043300000000005304350000008001100039000000000007004b00000000053500190000003f0990003900000e25099001970000001f097000390000000087070434000000000809c01900000deb00b0009c00000deb0800404100000deb0a60019700000deb088001970000001f08700039000000000807043300000e1b01000041000000160010006b00000000031300190000003f0530003900000005034002100000000004030433000000e003100039000000400070043f000000e0071000390000000305600210000000000151034f000000000049004b00000e2505300198000000000102001f000000000015004b000000050460021000020005001002180001000500100218000000000872001900000dd10090009c00000deb0080009c00000dea0010009c000000800600003900000080024000390000001f05a0018f00000df7011001c7000000c0013002100000000401000039000000800030043f00000220090000390000000001210049000000c00040043f000000000423034f0000003f0aa00039000000000767001900000dea0020009c0000020005500039000001e006500039000001c006500039000001a006500039000001800650003900000160072000390000016006500039000001400720003900000140065000390000012007200039000001200650003900000100072000390000010006500039000000e007200039000000e006500039000000c007200039000000c006500039000000a006500039000000800650003900000060065000390000004006500039000000000662043600000000760504340000001908000029001900000006001d0000000a02000029000000050140021000000dd20660019736b52e930000040f000000a007200039000000600820003900000db107700197000000800050043f000000800140003900000dd30040009c000000000301043b0000001501200029001600000002001d000000a00000043f000000e00900003900000024023003700000023a0000013d000000400370003900000080040000390000009f0000613d000000800040043f0000003f012000390000000502100210001a00000002001d000000000303043b0000000005010433000001000110003900000dd0011001c7000000800900003936d07081e6b4a2b623ea0355910672ddc6511fd4150dd11cfd266e967e3b2382ffffffffffffff40fffffffffffffde0ffffffffffffffc0fffffffffffffe60fffffffffffffedfdb5c65de000000004ada90af00000000e875544600000000a3aefa2c00000000fffffffffffffe5fd88ff1f400000000fc57d4df00000000bbcac557000000007dc0d1d000000000ffffffffffffff1f00000004000000e0ffffffffffffff5f00000024000002207aee632d000000000000004400000080266e0a7f000000004e487b7100000000552c09710000000095dd919300000000160c3a03000000006dfd08ca0000000074c4c1cc0000000008c379a00000000000000001000000006f7773000000000078206f766572666c6e657720696e6465b34b9f100000000000c097ce7bc907150de0b6b3a76400003c209e9336465bd123bf29dc2df74b6f266b0e7a08c0454b42cbb15ccdc3cad608cc6b5d955391325d622183e25ac5afcd93958e4c903827796b89b91644bc987c05a7c500000000aa5af0fd0000000092a18235000000002c427b570000000081814945000000008f693ec700000000ffffffffffffff9fffffffffffffffbf1627ee8900000000f7c618c10000000061252fd10000000022abdbf5000000000000000400000080b0772d0b00000000dd62ed3e000000003af9e6690000000017bfdfbc0000000070a0823100000000ffffffffffffff3ffffffffffffffebf00000040000000000000022000000000000000c000000000000000200000008080000000000000000000002400000080f36dba38000000003b1d21a2000000008f840ddd0000000047bd3718000000004a5844320000000002c3bcbb00000000173b990400000000f8f9da2800000000ae9d70b00000000018160ddd00000000ffffffffffffffdfe85a296000000000313ce567000000006f307dc30000000000000024000000008e8f294b000000005fe3b56700000000182df0f500000000fffffffffffffddf000000000000003fffffffffffffff7f0000002000000000ab882de59d99a32eff553aecb10793d015d089f94afb7896310ab089e4439a4c000000001f884fdf000000000d3ae318000000003e3e399c00000000345954dc00000000345954db0000000055dd95150000000047d86a81000000007a27db57000000006857249c000000006857249b0000000047d86a80000000007c84e3b3000000007c51b64200000000b312423900000000aa5dbd2300000000aa5dbd2200000000d26998e900000000c7ad089500000000e1d146fb00000000e0a67f1100000000d77ebf9600000000d77ebf9500000000c7ad0894000000007c51b64100000140000001000000000200000000ae0fcab3000000000000000001e1338009c8f7ec0000000000000000ffffffe000000001ffffffe0000036b500000432000036b300210423000036ae00210421000036aa0000613d00000e2a011001c7000036930000413d000000000161043a00000000060600310000000506600270000000000664001900000005062002100000369b0000413d000000050030008c00000000002004430000000005010019000036850000613d0000367b0000013d000036860000c13d000036780000613d0000366a0000613d000036590000c13d0000364d0000c13d000036410000c13d000036350000c13d000036290000c13d0000361d0000c13d0000000207000029000036520000613d000035ec0000613d000035db0000c13d000035df0000613d000000070b00002900070000000b001d000200000007001d000035f40000613d0000000406b0003900000df5040000410000002404b000390000000102000029000036460000613d000035a90000613d000035980000c13d0000359c0000613d000100000002001d000035b10000613d0000000406c0003900000df204000041000036140000213d0000363a0000613d000035670000613d000035560000c13d0000355a0000613d0000356e0000613d0000362e0000613d000035290000613d000035180000c13d0000351c0000613d000000030c00002900030000000c001d000035300000613d000036220000613d000034e80000613d000034d70000c13d000034db0000613d000000040b00002900040000000b001d000034ef0000613d000036140000a13d0000360e0000c13d000036160000613d000034a20000613d000034910000c13d000034950000613d000000050c00002900050000000c001d000034a70000013d000034780000c13d000600000005001d000700000003001d00000db10320019700000000003c043500000df2030000410000360e0000813d00000e290030009c0007000000000002000034510000c13d000034450000c13d000034390000c13d0000342d0000c13d000034210000c13d000034150000c13d000034090000c13d000033fd0000c13d000033f10000c13d000033e50000c13d000033d90000c13d000033cd0000c13d000033c10000c13d000033b50000c13d000033a90000c13d0000339d0000c13d000033900000613d0000337f0000c13d00000001070000290000343e0000613d0000332a0000613d000033190000c13d0000331d0000613d000100000007001d000033330000613d000034320000613d000032eb0000613d000032da0000c13d000032de0000613d000032f30000613d000034260000613d000032ac0000613d0000329b0000c13d0000329f0000613d000000030b00002900030000000b001d000032b40000613d0000341a0000613d0000326d0000613d0000325c0000c13d000032600000613d000000040c00002900040000000c001d000032750000613d0000340e0000613d0000322e0000613d0000321d0000c13d000032210000613d000032360000613d000034020000613d000031ef0000613d000031de0000c13d000031e20000613d000031f70000613d000033f60000613d000031ad0000613d0000319c0000c13d000031a00000613d000000060b00002900060000000b001d000031b60000613d000033ea0000613d0000316b0000613d0000315a0000c13d0000315e0000613d000000070c00002900070000000c001d000031740000613d000033de0000613d0000312b0000613d0000311a0000c13d0000311e0000613d000031320000013d000031010000c13d000030f90000013d000000000b0100190000344a0000613d000030e60000613d000030d50000c13d000030d90000613d000030ef0000613d000030f80000613d000033d20000613d000030a40000613d000030930000c13d000030970000613d000000100c00002900100000000c001d000030ad0000613d0000301c0000a13d000000000a0c00190000000800b0008c000000ff0b20018f0000000102b00039000000000626019f0000000002b201cf000000000ca10019000033780000613d000030500000613d0000303f0000c13d000030430000613d000000100a00002900100000000a001d0000305a0000613d00000000008a04350000000000b104350000002401a00039000033c60000613d000030060000613d00002ff50000c13d00002ff90000613d0000300e0000613d0000000c04000029000033ba0000613d00002fc40000613d00002fb30000c13d00002fb70000613d00002fca0000013d00002f9a0000c13d0000001006000029000033ae0000613d00002f7b0000613d00002f6a0000c13d00002f6e0000613d0000006007400190001000000006001d00002f820000013d00002f500000c13d000d00000007001d00000000061b043600000db10070009c000033a20000613d00002f340000613d00002f230000c13d00002f270000613d00002f3b0000613d000033700000a13d000033960000613d00002ef10000613d00002ee00000c13d00002ee40000613d00002ef60000013d00002ec70000c13d000e00000005001d00000dd602000041000000a003200039000000c003200039000000e0032000390000018003200039000001a003200039000001c003200039000001e00320003900000200032000390000022003200039000033720000813d00000e280020009c001100000000000200002e8d0000613d00002e7c0000c13d00002e700000c13d00002e640000c13d0000000001c1001900002e750000613d00002e3f0000613d00002e2e0000c13d00002e320000613d00002e460000613d0000000404c0003900002e690000613d00002dff0000613d00002dee0000c13d00002df20000613d000000010b00002900010000000b001d00002e060000613d00002e550000a13d00002e570000c13d00002e5d0000613d00002dbc0000613d00002dab0000c13d00002daf0000613d00002dc10000013d00002d920000c13d000200000005001d00002e570000813d00000e270020009c000200000000000200002d770000c13d00002d6b0000c13d00002d5f0000c13d00002d530000c13d00002d470000c13d00002d3b0000c13d00002d2d0000613d00002d1c0000c13d000000090200002900000000006204350000000d0400002900000e1f0010009c000000010600002900002d700000613d00002cd50000613d00002cc40000c13d00002cc80000613d000100000006001d00002cde0000613d00000e230200004100002d640000613d00002c960000613d00002c850000c13d00002c890000613d00002c9e0000613d00000e220200004100002d580000613d00002c570000613d00002c460000c13d00002c4a0000613d00002c5f0000613d00000e210200004100002d4c0000613d00002c110000613d00002c000000c13d00002c040000613d00002c170000013d00002be70000c13d000b00000005001d000a00000001001d000700000001001d0000000602000029000300000001001d000000000247001900002bbd0000413d000000000962001900002bc40000613d000000000864001900000000074a04360000000100800190000000010800403900000000080000390000000000a7004b0000003f077000390000000064040434000000000608c01900000deb06004041000000000067004b000000000967013f00000deb0770019700000deb080080410000000004470019000000400740003900002b890000413d00000000007b004b000000000d8b001900002b900000613d00000000002b004b000000000b870019000000000a7904360000000100b00190000000010b004039000000000b000039000000000aa9001900000e250a900197000000000a68013f000000000747001900000000055104360000000008a8001900002b560000413d00000000008b004b000000000d9b001900002b5d0000613d000000800a10003900000000002a004b000000000a9800190000000000850435000000000a5a00190000001f0a800039000000000a09c01900000deb0a004041000000000b6a013f00000deb062001970000001f0680003900000000084600190000000076040434000000600050008c00000dea0050009c0000000005420049000000000494001900000000029300190000000004090433000000000192001900000e250210019700002b140000613d00002b030000c13d000000000709001900002b070000613d0000000c0900002900002d400000613d000c00000009001d00002afd0000013d00002aea0000c13d00002abf0000413d0000000d010000290000000a02600029000b00000003001d000000090120002900002a910000413d00002ada0000613d0000000006520436000d00000003001d00002a0e0000213d00002a140000613d0000000a0800002900002d150000613d0000000d0900002900002a540000613d00002a430000c13d00002a470000613d000a00000008001d000d00000009001d00002a5d0000013d00002a290000c13d00000000007a04350000000909100029000000050180021000002a7a0000813d0000000108800039000000090110002900002a170000013d00002a790000613d00002a7c0000013d000000000506001900002a070000c13d0000000d0010006b00002d330000613d0000002400900443000029ea0000413d000029f10000813d000900000003001d0000000c050000290000000c055000290000000002a3001900002d130000a13d000029b30000613d000029a20000c13d00000000070a0019000029a60000613d00000000024a001900002d340000613d0000299c0000013d000029880000c13d0000000601000029000000000291043600002d0d0000813d00000e260010009c000d000000000002000000000203043300000000011204360000000031010434000028f00000413d00000220011000390000020006100039000001e007100039000001c007100039000001a0071000390000018007100039000001600710003900000140071000390000012007100039000001000710003900000000066104360000293b0000613d00000000013404360000018002200039000001a0011000390000000003340049000000000454001900000e25046001970000018008100039000001600810003900000140081000390000012008100039000028c90000413d000028d00000613d000028b30000413d000028ba0000613d000000e0081000390000289d0000413d000028a40000613d0000000076080434000000a0082000390000001f06400039000000800620003900000040062000390000000007540019000028760000413d0000287d0000613d000001e0051000390000000074040434000001c005100039000001a0050000390000000064020434000000000331043600000200011000390000020002200039000001e004200039000001e003100039000001c004200039000001a00420003900000180042000390000016004200039000001400420003900000120042000390000010004200039000000e004200039000000c004200039000000a00420003900000000012100190000001f023000390000000002130019000028170000413d000000000624001900000000051200190000281e0000613d00000000013204360000280d0000c13d000028010000c13d000027f50000c13d000027e90000c13d000027dd0000c13d000027d10000c13d000027c50000c13d000027b90000c13d000027ad0000c13d000027a10000c13d000027950000c13d000027890000c13d0000277d0000c13d000027710000c13d000027650000c13d000027590000c13d0000274d0000c13d000027410000c13d000027350000c13d36b528120000040f00000e0d0200004100000012010000390000270c0000613d000026fb0000c13d000026ee0000c13d000026e10000c13d000005450000013d000026c80000c13d000026cc0000613d00000db006900198000000000a0900190000001f0590018f0000006001900210000000000163034f000026be0000613d000026ad0000c13d000026b10000013d0000269f0000c13d000000110100003900001d3a0000013d00001e570000413d0000002601000029002700010020003d0016000000010035001400600010003d0000002401000029001d00270000002d00001f690000413d0000001d0010006b001d00010020003d0000000e02300029000000140300002900000db10550019700000e0a0220012a00000e0a0440012a0000001d0040006c000000000301043600000000044200d9000026430000613d00000000024300a9000027760000613d000026280000613d000026170000c13d0000261b0000613d00000019056000290000262c0000613d0000001201100029000027ee0000613d000025cc0000613d000025bb0000c13d0000001208000029000025bf0000613d0000001205600029000025d20000613d000025df0000013d0000259e0000813d000000110020006b000027be0000613d000025830000613d000025720000c13d000025760000613d000025890000613d000025e00000c13d0000276a0000613d000025320000613d000025210000c13d000025250000613d000025360000613d00000e120100004100000013015000f9000024eb0000213d00130000005400ad00000000052100d900000e090020009c00000000022100d9000024de0000613d00000e09012000d10000275e0000613d000024c30000613d000024b20000c13d000024b60000613d000024c70000613d00000e11010000410000001101100029000027e20000613d000024670000613d000024560000c13d00000011080000290000245a0000613d00000011056000290000246d0000613d0000247a0000013d000024390000813d000000100020006b000027b20000613d0000241e0000613d0000240d0000c13d000024110000613d000024240000613d0000247b0000c13d001900000004001d000027520000613d000023cd0000613d000023bc0000c13d000023c00000613d000023d10000013d000023a60000c13d00000e0f0100004100000db103100197000023530000013d00000000022400d900000000013400d90000234b0000613d00000e0a043000d1000023500000613d000000170020006c00000000022300d900000017032000b90000001001200029000027d60000613d000023260000613d000023150000c13d0000001008000029000023190000613d00000010056000290000232a0000013d000022ff0000c13d00000ddf010000410000237e0000613d000023810000613d000c000000140053001300000004001d000022d70000013d000022d40000613d0000001701200029000027460000613d000022a80000613d000022970000c13d0000229b0000613d000022ac0000013d000022810000c13d0000000401300039001700000003001d00000e0e0200004100000000022500d900000000023200d900000000014500d9000022370000613d00000e0a054000d10000223c0000a13d0000222c0000a13d000000170050006c00000000055400d900000017045000b90000000a0500002900000e090030009c00000000033200d90000221d0000613d00000e09023000d10000000b01200029000027ca0000613d000022040000613d000021f30000c13d0000000b08000029000021f70000613d0000000b05600029000022080000013d000021dd0000c13d00000de501000041000022670000613d0000226a0000613d000a000000140053000021b50000013d000021b20000613d0000273a0000613d000021860000613d000021750000c13d000021790000613d0000218c0000613d000c00000004001d000000040250003900000db10420019700000e05040000410000272e0000613d000021310000613d000021200000c13d000021240000613d000021350000613d00000e040100004100000010050000290000004004400039000027a60000613d000020d60000613d000020c50000c13d000020c90000613d000020dc0000613d00000e03040000410000279a0000613d000020790000613d000020680000c13d0000206c0000613d000020f40000013d0000278e0000613d000020370000613d000020260000c13d0000202a0000613d0000203d0000613d00000e0104000041000027820000613d00001fde0000613d00001fcd0000c13d00001fd10000613d0000207d0000013d000020520000c13d00000e020200004100001fe20000013d00001fb70000c13d00000dff0200004100001fa00000613d0014000500200218000000090000006b001c0db10020019b0000266e0000613d00001f440000413d0000000e0420002900000dfd0030009c00001f510000613d000e00000003001d000000000043004b000f00000004001d000000000334001900000dd203300197000d00000001001d00000000120104340000002b010000290000001a01200029000028060000613d00001f0d0000613d00001efc0000c13d00001f000000613d000000600330021000001f130000613d001500000005001d0000002d0550017f00000db1050000410000001804500029001b00000005001d00000dfc040000410000002c0220017f000027fa0000613d00001eb60000613d00001ea50000c13d00001ea90000613d000000000334019f000000600440021000001eba0000013d00001e8c0000c13d001800290000002d00000dfb0100004100000000030104330000002a01000029002400000002001d001500000001001d001400000003001d00001e510000c13d00001e450000c13d00001e390000c13d00001e2d0000c13d00001e210000c13d00001e150000c13d00001e090000c13d00001dfd0000c13d00001df10000c13d00001de50000c13d00001dd90000c13d00001dcd0000c13d00001dc10000c13d00001db50000c13d00001da90000c13d00001d9d0000c13d00001d910000c13d00001d850000c13d00001d790000c13d00001d490000013d00001d660000413d000000000089004b0000000000ba0435000000000aa2043600000db10aa0019700000000ba0a0434000000000a070433000000200770003900001d490000613d000000800920003900000000005804350000006007700039000000400920003900000db109900197000000000882043600000db10880019700000000980704340000000004740436000000400770008a0000000007120049000002390000813d000000000036004b00001d4c0000013d000000160c000029000000800500003900001e560000c13d002700000000003d000000160100002f00001d210000413d00000000052300190000002005400039000000400540003900000060054000390000008005400039000000600600003900001d320000613d00000000034500190008000500300218000000250330008a00000000030004150026001c0000002d00000f520000013d00001c3e0000413d0000001b0010006b001b00010050003d001a001a0010002d0000001a0010002a000000160210002900000e090110012a00000000044100d900001cf40000613d0000001b0500002900000000014200a900001e3e0000613d00001cdd0000613d00001ccc0000c13d00001cd00000613d0000000003054019000000c00140021000001cea0000013d000000000115001900001cb60000c13d001500000004001d00000000040604330000001b0020006c000000200040008c0000000005a1001900001e320000613d00001c8b0000613d00001c7a0000c13d00001c7e0000613d00001c900000013d00001c630000c13d00000e1c0100004100000000020504330000001605900029001600200010003d001800000001001d001b00000000001d00130db10020019b00001c360000c13d00001c2a0000c13d00001c1e0000c13d00001c120000c13d00001c060000c13d00001bfa0000c13d00001bee0000c13d00001be20000c13d00001bd60000c13d00001bca0000c13d00001bbe0000c13d00001bb20000c13d00001ba60000c13d00001b9a0000c13d00001b8e0000c13d00001b820000c13d00001b760000c13d00001b6a0000c13d00001b5e0000c13d00001b520000c13d00001b460000c13d00001b3a0000c13d00001b2e0000c13d00001b220000c13d00001b160000c13d00001b0a0000c13d00001a9c0000013d00000000017100190000000501600210000000000061004b00001a9c0000613d0000000001b20019000000170700002900001c230000613d0000001c0900002900001adc0000613d00001acb0000c13d00001acf0000613d0000001a0b000029001a0000000b001d00000000030b4019001c00000009001d00001ae60000013d00001ab10000c13d00000000008b0435000000000a7100190000000501900210000005e10000813d00001a9f0000013d001700000007001d000019bd0000013d00001a480000413d0000022005500039000002000b5000390000020006b00039000001e00c500039000001e006b00039000001c00c500039000001c006b00039000001a00c500039000001a006b00039000001800c5000390000018006b00039000001600c5000390000016006b00039000001400c5000390000014006b00039000001200c5000390000012006b00039000001000c5000390000010006b00039000000e00c500039000000e006b00039000000c00c500039000000c006b00039000000a00c500039000000a006b00039000000800c5000390000008006b00039000000600c5000390000006006b00039000000400c5000390000004006b000390000000000c60435000000000c0c0433000000000665043600000000c60b0434000000000b080433000019bd0000613d0000000005960436000000000908043300000180088000390000018005500039000001600b5000390000016006800039000001400b5000390000014006800039000001200b5000390000012006800039000001000b500039000001000680003900001a210000413d00001a280000613d000000e00b500039000000e00980003900001a0b0000413d00001a120000613d000000c00b500039000000c009800039000019f50000413d000019fc0000613d00000000ba0b0434000000a00b800039000000a00a5000390000000006a600190000001f06900039000000800b5000390000008006800039000000600b5000390000006006800039000000400b50003900000040068000390000000006a90019000019cf0000413d00000000009e004b000000200ee0003900000000006f04350000000006ed0019000000000fae0019000019d60000613d000001c00a50003900000000d9090434000001a00a500039000000000b650436000001a00600003900000000c908043400000000080204330000000004840436000000400880008a0000000008150049000003b80000813d000000000037004b000019c00000013d00001d100000013d00000dd2043001970008000500100218000000280110008a002600000001001d000019a80000413d000000003203043400001d0c0000813d000000000056004b000000000631001900000000002604350000001c060000290000001c0640002900000dd2044001970000003f041000390000000032010434000000000203c019000000000642013f00000deb045001970000001f021000390000001d011000290000001d053000290000001d02100029000019710000613d000019600000c13d0000001d07000029000019640000613d0000001d0240002900001b030000613d000019430000c13d000019370000c13d0000192b0000c13d000003ae0000013d000010260000413d000000000101003100000001010000290000000104500039003000010050003d000000300500002900000000020100310000006001400039000000a001400039000000c001400039000000e00140003900000100014000390000012001400039000001400140003900000160024000390000018002400039000001a00240003900000e1f0040009c0000000004a30019000026f30000613d000018d20000613d000018c10000c13d000018c50000613d000018db0000613d00000e2301000041000026e60000613d0000188f0000613d0000187e0000c13d000018820000613d000018980000613d00000e2201000041000026d90000613d0000184c0000613d0000183b0000c13d0000183f0000613d000018550000613d00000e2101000041000026c00000613d000018020000613d000017f10000c13d000017f50000613d000000c003300210000018090000013d0000000004014019000017da0000c13d00000e1b020000410000000302000029001400000001001d0000000001580019000017af0000413d000000000054004b00000000037400190000000001840019000017b60000613d00000000017500190000000008510436000000010090019000000001090040390000000009000039000000000038004b001800000003001d00000000081300190000000075050434000000000871013f0000000005580019000000000801043300000040015000390000000000a6043500000000018b0019000017790000413d00000000008c004b00000000039c0019000017800000613d0000000001980019000000000b8a04360000000100c00190000000010c004039000000000c0000390000000000ab004b000000000b1a0019000000000971013f00000000085800190000000001b90019000017460000413d00000000009c004b0000000003ac00190000174d0000613d000000800b2000390000000001a900190000000000960435000000000b61001900000000a9090434000000000a71013f00000deb074001970000000009570019000000008705043400000dfe0020009c000000600060008c00000dea0060009c00000000065400490000001d0430002900000000050304330000000003090019000000000171016f000000000343019f00000000033501cf000000000506043b000000000641034f000016ff0000613d000016ee0000c13d000016f20000613d0000000004780170000026a40000613d000016e90000013d0000000008000031000016d40000c13d000011980000413d0000001501000029000000130250002900001dde0000613d0000166c0000613d0000165b0000c13d0000165f0000613d000016750000613d00001dd20000613d0000162a0000613d000016190000c13d0000161d0000613d000016330000613d00001e1a0000613d000015e80000613d000015d70000c13d000015db0000613d000015f10000613d000800000002001d00001dc60000613d000015a60000613d000015950000c13d000015990000613d000015af0000613d000900000002001d00001e0e0000613d000015640000613d000015530000c13d000015570000613d0000156d0000613d00001dba0000613d000015220000613d000015110000c13d000015150000613d0000152b0000613d00001e020000613d000014de0000613d000014cd0000c13d000014d10000613d000014e70000613d00001dae0000613d0000149a0000613d000014890000c13d0000148d0000613d000014a30000613d00001df60000613d000014580000613d000014470000c13d0000144b0000613d0000145f0000613d000d00000000001d000014290000013d00001e260000613d000014130000613d000014020000c13d000014060000613d0000141c0000613d000014270000613d00001dea0000613d000013d10000613d000013c00000c13d000013c40000613d000013da0000613d0000134e0000a13d00001b630000613d000013810000613d0000136f0000c13d000013730000613d000013a20000013d000013340000413d000000000a2404360000134c0000c13d000e00000001001d00001da20000613d0000131c0000613d0000130b0000c13d0000130f0000613d000013240000613d00001d7e0000613d000012d80000613d000012c70000c13d000012cb0000613d000012de0000613d00001d960000613d0000128e0000613d0000127d0000c13d000012810000613d000012940000013d000012670000c13d00000000011a043600001d720000613d000012440000613d000012330000c13d000012370000613d0000124c0000613d00001d8a0000613d000011fe0000613d000011ed0000c13d000011f10000613d000012040000013d000011d50000c13d000000060230002900000005032002100000116c0000413d0000001304200029000016c40000613d00000000023204360000000501100210000011500000013d000010e70000413d000010e30000613d00001e4a0000613d000011250000613d000011140000c13d000011180000613d0000112a0000013d000010fd0000c13d00000df901000041000011500000813d000010e70000013d001b00000004001d0000114f0000613d000011520000013d0000000003040019000010dc0000c13d0000001a0010006b0000002400d00443000010be0000413d000010c50000813d000600000003001d00000014050000290000001405500029000000000141001900000000024300190000000003080019000000000141019f000010850000613d000010740000c13d000010780000613d00000e2504800198000026960000613d00000000010940190000106f0000613d0000001c0100035f00000df602000041000300000004001d0000000001d20436000000a001200039000000c001200039000000e0012000390000018001200039000001a001200039000400360000002d000000000151001900000e1f0020009c0000003505000029003000000000003d00000fff0000413d00000000016500190000006003700039000000800370003900000100037000390000012003700039000001400370003900000160037000390000000001d70436000000a001700039000000c001700039000000e0017000390000018001700039000001a00170003900000e1f0070009c00000ff80000c13d00000fec0000c13d00000f7f0000013d0000000001810019000000050170021000000f7f0000613d00000000010c04330000000001c20019000000180600002900001b570000613d00000fbe0000613d00000fad0000c13d00000000080c001900000fb10000613d00000000056c00190000001b0c000029001b0000000c001d00000000030c401900000fc90000013d00000f930000c13d00000000009c0435000000000b8100190000000501a002100000042e0000813d00000f820000013d001700000008001d001800000006001d0000009f0000013d00000f6b0000413d00000040033000390000000006630436000000007606043400001c3b0000c13d0000000001150436001400000004001d0000004004500039000000600450003900000dfe0040009c00000f330000413d0000000008650019000000200870003900000dfd0070009c00000f400000613d0000000005610436000000000515001900000000060904330000001d0120002900000ff10000613d00000f0f0000613d00000efe0000c13d00000f020000613d0000001d057000290000039b0000a13d003200000006001d000000310110008a000000320110008a003500000001001d00000e860000413d000000000087004b0000000000b904350000008003b00039000000a002a000390000006003b000390000008002a000390000004003b0003900000020099000390000006002a000390000000000c2043500000db100c0009c000000000c0304330000004003a000390000000002cb04360000000002fd001900000eb90000413d0000000000d2004b0000000006e200190000000003f2001900000ec00000613d00000000000d004b000000c00fb000390000000002ed00190000000002c200190000003f0220003900000dd100d0009c00000000ed0d043400000000020ec01900000deb00f0009c000000000f52013f00000deb0e008041000000000dd2001900000000020d0433000000a00cb0003900000e1800b0009c000000a00020008c0000000002d40049000000200da00039000000000a12001900000000720704340000001b090000290000017a0000013d00000cbe0000413d000000160030006c000000130700002900001b4b0000613d00000e550000613d00000e440000c13d00000e480000613d001300000007001d00000e5d0000613d00000df5020000410000002402a0003900000000070b0433000000130600002900001b3f0000613d00000e120000613d00000e010000c13d00000e050000613d000000140b00002900140000000b001d001300000006001d00000e1a0000613d00000df20200004100000db10060009c00000000060a043300001b330000613d00000dd00000613d00000dbf0000c13d00000dc30000613d00000dd70000613d00001b270000613d00000d930000613d00000d820000c13d00000d860000613d000000170b00002900170000000b001d00000d9a0000613d00001b1b0000613d00000d530000613d00000d420000c13d00000d460000613d00000d5a0000613d00001b0f0000613d00000d0e0000613d00000cfd0000c13d00000d010000613d000000190b00002900190000000b001d00000d130000013d00000ce50000c13d001c00000005001d001d0db10030019b000000870000013d00000bd20000413d0000001a0030006c0000193c0000613d00000c980000613d00000c870000c13d00000c8b0000613d00000c9f0000613d0000000404b00039000019300000613d00000c590000613d00000c480000c13d00000c4c0000613d00000c600000613d00000000004a0435000019240000613d00000c170000613d00000c060000c13d00000c0a0000613d00000c1c0000013d00000bee0000c13d00000dd701000041001c00000003001d000001e40000013d000006bb0000413d0000000a0030006c00000014025000290000001303000029000000000083043500001c170000613d000000090900002900000b7d0000613d00000b6c0000c13d00000b700000613d000000080a00002900080000000a001d000900000009001d00000b880000613d00001c0b0000613d00000b3d0000613d00000b2c0000c13d00000b300000613d000000090b00002900090000000b001d00000b470000613d00001bff0000613d00000afd0000613d00000aec0000c13d00000af00000613d00000b070000613d00001bf30000613d00000abd0000613d00000aac0000c13d00000ab00000613d0000000c0b000029000c0000000b001d00000ac70000613d00001be70000613d00000a7d0000613d00000a6c0000c13d00000a700000613d0000000d0a000029000d0000000a001d00000a870000613d000e00000002001d00001bdb0000613d00000a3d0000613d00000a2c0000c13d00000a300000613d0000000e0b000029000e0000000b001d00000a470000613d00001bcf0000613d000009fa0000613d000009e90000c13d000009ed0000613d0000000e0a000029000e0000000a001d00000a050000613d00001bc30000613d000009b70000613d000009a60000c13d000009aa0000613d000009c20000613d00001bb70000613d000009760000613d000009650000c13d000009690000613d0000097f0000613d001c00000000001d000009470000013d00001c2f0000613d000009310000613d000009200000c13d000009240000613d0000093c0000613d000009460000613d00001bab0000613d000008ef0000613d000008de0000c13d000008e20000613d000008fa0000613d0000086a0000a13d00000fe50000613d0000089c0000613d0000088b0000c13d0000088f0000613d000008c00000013d000008500000413d000000000b240436000008680000c13d00001b9f0000613d000008380000613d000008270000c13d0000082b0000613d000008420000613d000000160400002900001b930000613d000007f50000613d000007e40000c13d000007e80000613d000007fd0000613d0000000001080433001200000002001d0000001c0800002900001b870000613d000007ac0000613d0000079b0000c13d0000079f0000613d001c00000008001d000007b50000013d000007820000c13d001700000009001d00000000081a043600000db10090009c00001b7b0000613d000007640000613d000007530000c13d000007570000613d0000076d0000613d00001b6f0000613d000007200000613d0000070f0000c13d000007130000613d000007270000013d000006f70000c13d00000db10720019700000005022002100000068e0000413d0000000004520019000006720000a13d00000cbc0000813d0000000000150435000000a00540003900000040051000390000008005100039000000a005100039000000c00510003900000df00040009c000006610000a13d00000bd10000813d00000df10030009c000006580000613d000006470000c13d0000063b0000c13d000001d20000013d0000000004010019000000400600043d0000000001020019000006250000413d0000000004540436000000000505043b000000000513034f000000a00400003900000080011001bf000006400000613d000006130000613d000006020000c13d0000000008a80436000000009a09043c000000000901034f0000008008000039000006060000613d00000080057001bf00000e15011001c70000195a0000013d000019480000c13d002900040000003d00000dfa01000041002a00400000003d002b001d0000002d000000000061043500001a940000c13d000005e30000613d000005c20000413d000005c90000613d0000001d055000290000009f0310003900000080023000390000058f0000613d0000057e0000c13d000005820000613d000006340000613d000005670000c13d0000055b0000c13d0000054f0000c13d0000006001a00210000005350000c13d000005390000613d00000db006a0019800000000012300490000051e0000413d0000000003630436000005250000613d0000050e0000413d0000000025020434000005150000613d000000000424001900000000061600190000003f064000390000000504500210000000000405c01900000deb0070009c00000deb04004041000000000064004b000000000764013f00000deb0440019700000deb0630019700000deb050080410000009f042000390000008003300039000004df0000613d000004ce0000c13d000004d20000613d0000008004500039000005600000613d00000de9011001c7000002a20000013d000002a003400039000002a00110003900000280051000390000028003400039000002600510003900000260034000390000024005100039000002400340003900000000055700190000049c0000413d000000000076004b000000000a8600190000000009560019000004a30000613d000002e005100039000000000065004b0000000005870019000000000073043500000e25059001970000000000a8004b000000000ba8013f0000000007780019000002c00310003900000e180020009c000000a00030008c000000000376004900000220074000390000022006300039000002200400043d000000000646022f00000000064601cf00000003046002100000045f0000613d0000044e0000c13d000000000029004b000004520000613d0000022002400039000005540000613d00000e17011001c700000f130000013d00000ee70000c13d000000000075043500000f770000c13d0000042f0000613d001900000007001d0000040e0000413d000004150000613d00000000004704350000000005750019000000ff03100039000000e002300039000000e00100043d00000e1a0010009c000003dd0000613d000003cc0000c13d000003d00000613d000000e004500039000005480000613d00000e19011001c70000000002150049000019bb0000c13d00000000054500190000000505300210000000000431043600000ffd0000c13d0000000005620436000000010070019000000001070040390000000007000039000000000521001900000dd4011001970000003f01400039003400000000003d000000330110008a000000340110008a0035001b0000002d00000e850000c13d000000a00770003900000000009304350000001b0880002900000dd2088001970000003f08200039000000050290021000000000090104330000008001700039000000000206c019000000000852013f00000deb0540019700000deb060080410000009f027000390000008004100039000000800700043d00000dd30020009c0000001f02a00039000000000464019f00000000045401cf000000000454022f000000000441034f0000035d0000613d0000034c0000c13d000003500000613d00000e2504a001980000052e0000613d00000dae0a30019700000db6010000410000012000100443000001000030044300000220002004430000020000100443000001e000400443000001c000100443000001a000100443000001800030044300000160003004430000014000000443000000e00020043f000000a00010043f000000020400003900000db502000041000000230440008a002200200000003d002300000001001d000004c90000013d000004bc0000c13d000000840030043f00000de8010000410000002f0440008a002e00000000003d002f00000001001d000003460000013d000000000a0000310000033a0000c13d00000e1e03000041003600000002001d00000004023003700000000002000416000004490000013d0000043c0000c13d000002240020043f000002200010043f00000e1601000041000002000010043f000001e00000043f000001c00000043f000001a00000043f000001800000043f000001600010043f000001400010043f000001200010043f000001000000043f000000e00000043f000000c00000043f000005260000013d36b5286a0000040f000000000201001936b529580000040f0000008002000039000001000020043f000000e00040043f000000000443034f000000a00040043f0000002002500039000000800020043f00000140046000390000000000740435000000000797019f00000000078701cf000000000787022f0000010008800089000000000989022f00000000098901cf00000000090404330000000308900210000000000787034f0000028a0000613d000002790000c13d00000000004a004b000000000aca043600000000bc0b043c000000000b07034f000001400a0000390000027d0000613d00000140048000390000001f0960018f00000e2508600198000000000743034f0000002004800039000000000047004b0000002407700039000001200060043f000001200aa0003900000e2400a0009c0000001f0a600039000000000683034f00000004087000390000002306700039000000000753034f00000004056000390000012002000039000000a40020008c0000000002640049000000000602043b00000060022002100000000002120049000001ee0000413d00000220022000390000020006200039000001e007200039000001c007200039000001a0072000390000018007200039000000800720003900000060072000390000004007200039000000000508043300000000030604330000068d0000c13d0000000005260436000000000263001900000dd403200197000a00000004001d000006240000c13d00000000021200190000002401100039000000800660003900000dd30060009c0000003f062000390000000502500210000000000502043b00000dee011001c736b528240000040f000002390000013d000001830000413d000000000035004b000000c002200039000000a00660003900000080082000390000008007600039000000600760003900000040082000390000004007600039000000000087043500000000077204360000000087060434000000800300043d0000066f0000c13d000000160500002900000dd204100197001500240010003d0000031f0000013d00000db202000041000003250000c13d000000210440008a002000600000003d002100000001001d00000dbe0020009c0000030a0000613d00000dbd0020009c000005780000013d0000056c0000c13d002d00000002001d002c0db10000004500000dc70020009c000002e40000613d00000dc60020009c000003c70000013d000003ba0000c13d000000e00010043f000000c00010043f000000800000043f00000dcc0020009c000002d20000613d00000dcb0020009c00000ded011001c736b529420000040f36b534560000040f00000dc10020009c0000019f0000613d00000dc00020009c000003260000013d000000010400003900000db4030000410000031d0000c13d0000014f0000613d000001200300043d000006170000013d000005f10000c13d000000a40030043f000000840010043f00000e14040000410000004403300370000000640040008c00000dc90020009c000002aa0000613d00000dc80020009c0000011d0000213d00000dc50020009c00000def011001c736b5293c0000040f36b52d7c0000040f00000dc30020009c000001540000613d00000dc20020009c000000e50000213d00000dbf0020009c0000000002130049000000910000413d0000000006070019000000000025004b000000000608043300000060036000390000000000370435000000008303043400000000030404330000000007030019000000000601001900000000032104360000065e0000c13d000000800130003900000dd30030009c00000dd203100197001900240010003d00000dce0020009c000002420000613d00000dcd0020009c000001000000213d00000dca0020009c000000ba0000213d00000dc40020009c000000dd0000a13d000001400200043d000000010200c039000001000100043d000000600040008c000000000252019f00000000022301cf000000000323022f0000010002200089000000000525022f00000000052501cf0000000302200210000000000353034f000000500000613d0000003f0000c13d000000000016004b0000010006000039000000430000613d000001000150003900000db0054001980000001f0240018f00000daf01100197000000400120021036b536700000040f0000001f0440008a001e00400000003d001f00000001001d00000dbc0020009c000001b20000613d00000dbb0020009c000002f40000613d00000dba0020009c0000013a0000a13d00000db90020009c000000a10000a13d00000db80020009c0000005d0000a13d00000db70020009c000000e002200270000000000203043b000000000543034f000000320000c13d0001000000030355000200000043035500000dae0410019700000060011002700000000001030019003600000000000200030000000000020d1a0d1902dc0d180d170d160d150d1400060d13044c02db00d4001a0d120d110d100d0f0d0e0d0d0d0c0d0b0d0a0d090d080d070d060d05003f008c0061003f00d30d040d03022b022a02290d020228022702260d010007004d001c001d0d00044b00c7008c0061003f00150cff044a00390cfe0cfd0cfc0cfb0cfa02da016a02d90cf90cf8006c0cf70cf60cf504490cf40cf304480cf20cf10cf00cef004c0cee001a0ced0061005f0cec00ae003f0ceb00750cea00e400700ce90ce80ce70ce60ce50ce40ce3003f0169001a008c0061003f00c600460049001402d80093022502d7022401ab0447004b00140ce200b9044602d600ad001404450ce10ce000050cdf00390223044400ac0cde01aa0cdd016800850100006c0443044201160cdc0cdb02220cda0cd901a90cd80cd70cd602210441013c0cd50cd40cd30cd204400cd10cd00ccf0cce0ccd003f0169001a008c0061003f00c6004600e300140ccc000701670ccb00630030002f001e0cca00c70cc90cc80cc70cc60cc5003f0cc4001a008c0061003f00c602200075001401a8004600e300140cc3044801a700140cc204440cc10cc0003700400cbf00680001000800090cbe0cbd00610cbc008b0cbb0cba0cb90cb80cb70cb60cb5003f0166001a008c0061003f00c6004600e30014043f01ab007500140cb4000701670cb300630030002f001e0cb200c70cb10cb00caf003f0169001a008c0061003f00c60046021f00e30014043e02db0cae043d01650cad02d50cac003700c500400cab006801a60caa0ca90ca80ca7003f008c0061003f0166001a00c602200075001401a80046021f00e300140ca60ca502d50164003700c500400ca4006801a60ca30ca20ca10ca0003f008c0061003f00d30c9f0c9e022b022a02290c9d022802270226009e016402d400c7008b0c9c00670c9b0c9a0166001a008c0061003f00c600460049001402d80093022502d7022401ab043c004b00140c99013b0446043b00ad001401a8043a01a7001404450c9804390005043800390c970437007a0c9601aa021e0c95003200b8008b02d304420116022200ff0c9404360c9301a50c920c91009d0c9001150c8f009d043501150c8e009d0c8d01150c8c00350434004a0c8b013c0c8a0c890c880169001a008c0061003f00c6004600e300140433000701670c8700630030002f001e0c8600c70169001a008c0061003f00c600460049001402d80093022502d702240c8500b700050c840c8304320c8200050c81021d04370c800c7f00930014007a00c40c7e0c7d043102d20c7c0c7b0114016302d1004b000502d00045004104300c7a006c042f0c79006701aa021e0c78003200b8008b02d300c4042e01620c77042d00b6042c009d02cf042b00350c76004a042a00350c75004a042900350c74004a042800350434004a042700350426004a042500350424004a042300350422004a042100350420004a041f0035041e004a041d0035003d02ce02cd041c004a041b00350c73004a041a003500b60c72004a041900350c71004a041800350c70004a041701a40c6f021c0c6e02cc01610c6d0c6c001c001d0c6b0030002f001e002e00c70166001a008c0061003f00c6004600e30014043f0c6a013a00140c69041600140c68001a0c6700410c660c65004e0113001404150c6402cb02250c630c620024013a00050c61021b0414021b0c6000050c5f008a0c5e04150c5d0c5c00140c5b0c5a0c590c580c570c560c550c540c530c520c510c5001a30c4f0c4e0c4d0c4c0c4b0c4a004e0c490c480c470c460c450c4400360c430c420413021a016000140c4100920413021a01600014041202ca0c40021a0c3f0219022401ab0c3e0c3d0c3c0c3b006701a20c3a00ab04110c390166001a008c0061003f00c6004601a200e3001401a8022000750014041002db01650164043d0c380c370c360c350c340c330c320c310c300c2f0c2e0c2d0c2c0c2b003700ab00400c2a006801a60c290169001a0c28006c003f0c2701ab0c26007500140c25040f02c900400c240c2301a60c22008c0061003f00d30c210c20022b022a02290c1f022802270226016402d400c70166001a008c0061003f00c602200075001401a8043a01a700140c1e01640c1d02c900400c1c006801a60c1b008c0061003f00d30c1a0c19022b022a02290c18022802270226006100c30218016402d400c700670c17004c0030002f001e002300700c160c15040f04120c140c130c1201a10c110c1002c80c0f0c0e01650c0d0c0c0c0b040e0c0a0c0900c701390138040d040c000a000d001000e20c08000f00060c070c06040b040a0c0504090002016a02d901a00c04007a0c030c020137021700fe00fd021a00fc0c010c000bff00b5015f01360bfe02160bfd0005021502c7003900630408001400630135001a0bfc0113001400630bfb0bfa009300c20bf90bf802c60bf70214007e02c504070bf6006c003f0bf50bf4040600050bf30bf20bf10bf00134000502c402130bef0bee0405000b001401a30bed0bec019f0beb0404019f0bea04030be900c204020be80be700070be604010be50be400b700050be3004500d20be2003d0be102c3015e0400006701a10be00212006f02c20bdf0bde008b0bdd0bdc04400030002f003a0bdb000a000d001000e20013000f00060bda043e03ff02c10bd90bd80002016a02c003fe0bd7003d0bd603fd03fc00ff00fe00fd004600fc0112011100fb006e013300b401a20bd50005006303fb03fa00fa00140001001a0bd4004900140bd30bd200e100c402110210020f020e015d009c020d019e020c008b003f03f903f8009b000503f703f6019d0bd100b7000500d20bd0044a03f500e1001400ac0bcf0089020b01600014009200b500880bce0bcd013200b300d301310165019c00370030002f003a0130012f000a000601100046009e03f40bcc02bf019b003d02be0bcb0bca000703f30167004d003700c500400bc900680001000800090bc80030002f003a0bc7000a000d001000e20013000f00060bc60410019a02c10bc50bc40002016a02c00bc30bc2003d0bc1015c0bc002170bbf0bbe004601990198019700fb004d013300b4015b000502bd004100fa00140001001a0bbd009b00140bbc0bbb0bba00fa00140bb9001a0bb800050bb7008403f2013400140bb603f1015a019602bc03f003ef0bb50bb400e003ee03ed03ec0195003f03eb0113000503ea03e903e80bb303e700b7000500d20bb20bb10bb000140baf03e60bae00c20bad0bac0194019302bb0bab0baa0ba9010f00320ba8006001a700140ba7012e0ba6006001a700140ba5012e0ba400600ba3012e0ba20ba1006000df00630ba001390138040d0b9f000a000d001000e20013000f00060b9e044c03ff02c10b9d0b9c0002016a02c003fe0b9b003d0b9a03fd03fc00ff00fe00fd004600fc0112011100fb006e013300b402ba000503e5003900fa00140001001a0168004b00140b990b98016101160b970b960b950b940b9300c40b920b910b9000ac003f02b9019200b700050b8f0b8e04320b8d013a0005021d00aa01590b8c01610014007a0b8b000d0b8a020a001402b803e400930b89000701a102b703e3010e02b600ac0b880116012d03e200b60b87013c02090b860b850030002f02b5001c001d0050006600c7040b0b840007000c0b830002000e00040003000b0b82007a03e10158013700ff00fe00fd004600fc0112011100fb006e0b8102b4001100120007000c00200002000e00040003000b0b800022001100120007000c00200002000e00040003000b0b7f0022001100120007000c00200002000e00040003000b0b7e00220030002f003a040c000a000d001000e20013000f00060b7d019a0011040a0b7c04090002016a02d901a00b7b007a0b7a015c02080191020702060046019901980197012c004d013300b4019002ba000500d103e501a2003900fa00140001001a0205004900140b790b7800e100c402110210020f020e015d009c020d019e020c008b003f018f03f8009b000503f703f6019d0b7700b7000500d2012b00f903e003f500e1001400ac0b7600ab020b01600014009200b500880b75013200b300d301310165019c00370030002f003a0130012f000a000601100046009e03f40b7400630449007a00c20b7300630b720b710b700b6f00070167004d0b6e003700c500400b6d020400680b6c0030002f003a0b6b000a000d001000130001000800090059005e0b6a0b690b680b670b660b65001f0b64003d0b6300580057001900560055004e005400530052001800160017000f00060b620015001b0b6100390001001a016800750014004c001e044b00c70b600b5f0b5e020a00140b5d012d00ae0b5c01680b5b004b00050b5a0b590b58001100120007000c00200002000e00040003000b0b570022001100120007000c00200002000e00040003000b0b56007a0b550158013700ff00fe00fd004600fc0112011100fb006e0157001c001d0050002e00700b540005009c02c2007d03df00360074018e006e02b800e10b530067010d0b5202b30b51000500c40b5000d20b4f010f0b4e010f03de010f0b4d010f03dd010f00740b4c0b4b022203dc0b4a006702030b4900d000cf018d00ce00cd0070007e009a02b2000502b1007d02b0003602af003602ae003602ad003602ac003602ab003602aa003602a9003602a8003602a7003602020036018e00360201003602000036018c0036012a0036003e0b48006f009200730b47009c03db02050088003c03da0067015b000501290b4603d9015900380b4502bd004103d8003b03d7003b03d6003b0156003b0155003b018b003b0154003b0153003b0152003b0128003b010c003b010b003b00f8003b00f7003b00b8003b00f6003b007400f503d500cc0037009103d40b4400680001000800090b43004800a9012700500030002f003a0066002300890136000a00cb000d00100013000100080009002c00440b420002004300040003001f0b4100210b40002b002a0019002900280024002700260025001800160017000f00060b3f0083007900820015001b00de018a005f0065006d000500060045006b0001001a009002a601ff007c003400910b3e006200310072001e001c001d0033002e0023008903d3000a03d2000d00100013000100080009002c00a80b3d000200a700040003001f0b3c00210b3b002b002a0019002900280024002700260025001800160017000f00060b3a0015001b00830079008200b200990005008a0001001a03d10b39001402a50b3802a401fe003701fd0b370b3600f4015100090b350b34004800a9012700500030002f003a0066005d01fc0136000a00cb000d0010001300f401510009015000440b330002004300040003001f0b3200210b31002b002a0019002900280024002700260025001800160017000f000600f30b300083007900820b2f0015012600de006d0005006b00f4001a0090006c00c302180b2e0073003f0b2d01fb02a301fa0037009100080b2c006200a9018900500030002f003a00660023008903d3000a03d2000d00100013000100080009002c00a80b2b000200a700040003001f0b2a00210b29002b002a0019002900280024002700260025001800160017000f000600f30b280083007900820015001b00b200990005008a0001001a006a043c00750014014f007100340b2700d40b26004800310069001e001c001d0033002e002300c50136000a00cb000d00100013000100080009002c00440b250002004300040003001f0b2400210b23002b002a0019002900280024002700260025001800160017000f000600f30b220015001b00830079008201f9009b0005007d0001001a02a202a102a0001401fd0b2100e400e0029f004d03d00b20029e014e03cf0005006b029d006c00c101880093003f03ce03cd03cc03cb03ca03c90b1f029c0b1e007e00e001f8029b01f700f2004c03c8006e01f601fe0081003103c7001e0034001c001d0033002e012501fc000a0080000d00100013000100080009002c00440b1d0002004300040003001f0b1c00210b1b002b002a0019002900280024002700260025001800160017000f000600f30b1a0015001b00de018a005f0065006d00830079008200b1000500060045006b0001001a0090006c00c101880093003f01f503c603cd03c503c403c303c90b19014d007c00340091029b0b18006200310072001e001c001d0033002e0023008903c2000a029a000d00100013000100080009002c00a80b17000200a700040003001f0b1600210b15002b002a0019002900280024002700260025001800160017000f000600f30b140015001b00830079008200b100b200990005008a0001001a006a006c0b1302990071003400910b12004800310069001e001c001d0033002e002300890298000a00ca000d00100013000100080009002c00440b110002004300040003001f0b1000210b0f002b002a0019002900280024002700260025001800160017000f000600f30b0e0015001b00830079008200b100f10049000500390001001a0090010a03c10b0d0b0c029700cc0037009100080b0b004800a9012700500030002f003a0066002300890298000a00ca000d00100013000100080009002c00440b0a0002004300040003001f0b0900210b08002b002a0019002900280024002700260025001800160017000f000600f30b0700830079008200b10015001b00de006d0005006b0001001a009000f20296007c003400910b06006200310072001e001c001d0033002e0023008901f4000a01f3000d00100013000100080009002c00a80b05000200a700040003001f0b0400210b03002b002a0019002900280024002700260025001800160017000f000600f30b020015001b00830079008200b100b200990005008a0001001a006a03c0029500710187014e003401fd0b01004800310069001e001c001d0033002e005d01fc0b00000a0aff000d00100013000100080009002c00440afe0002004300040003001f0afd00210afc002b002a0019002900280024002700260025001800160017000f000600f30afb0015001b00830079008200b100de006d0005006b0001001a009002940293007c0186014e003401fd0afa006200310072001e001c001d0033002e005d01fc0af9000a0af8000d00100013000100080009002c00a80af7000200a700040003001f0af600210af5002b002a0019002900280024002700260025001800160017000f00060af40015001b00830079008200b100b200990005008a0001001a006a0af302920071003400910af2004800310069001e001c001d0033002e002300890af1000a0af0000d00100013000100080009002c00440aef0002004300040003001f0aee00210aed002b002a0019002900280024002700260025001800160017000f00060aec0015001b00830079008200b100de006d0005006b0001001a009001f20291007c003400910aeb006200310072001e001c001d0033002e002300890aea000a0ae9000d00100013000100080009002c00a80ae8000200a700040003001f0ae700210ae6002b002a0019002900280024002700260025001800160017000f00060ae50015001b00830079008200b100b200990005008a0001001a006a01f1014d0071003400910ae4004800310069001e001c001d0033002e0023008903bf000a03be000d00100013000100080009002c00440ae30002004300040003001f0ae200210ae1002b002a0019002900280024002700260025001800160017000f00060ae00015001b00830079008200b100de006d0005006b0001001a009001f00290007c003400910adf006200310072001e001c001d0033002e002300890ade000a0add000d00100013000100080009002c00a80adc000200a700040003001f0adb00210ada002b002a0019002900280024002700260025001800160017000f00060ad90015001b00830079008200b100b200990005008a0001001a03d1014f0071003400910ad80ad7004800310069001e001c001d0033002e002300890ad6000a0ad5000d00100013000100080009002c00440ad40002004300040003001f0ad300210ad2002b002a0019002900280024002700260025001800160017000f00060ad10ad00015001b00830079008200b100f10049000500390001001a0090028f0014015b0005028e0084028d0acf028c028b028a006f01ef0085015601240032015503bd0032018b03bc003201540185015301ee0032015202890032012802880032010c03bb0032010b0287003200f801ed003200f70213003200b80286003200f60ace003201fe03ba03b90114003c0acd004d02850088003c01840acc0acb0aca009c0ac901ec00f202d603b803b7020a00140067010d000500b8004100f6003b007401830ac801fa0037004702840ac700680001000800090ac6006200a9018900500030002f003a00660023004203b6000a03b5000d00100013000100080009002c00a80ac5000200a700040003001f0ac400210ac3002b002a0019002900280024002700260025001800160017000f00060ac2012b0015001b00b20283005f00650099000500060045008a0001001a006a0075001403b40ac100b000400ac0004800310069001e008100a600c00098002303b3000a03b2000d00100013000100080009002c00440abf0002004300040003001f0abe00210abd002b002a0019002900280024002700260025001800160017000f00060abc0015001b012b00de006d0005006b0001001a009000750014028202810abb01eb00b000400aba006200310072001e008100a600c00098005d03b6000a03b5000d00100013000100080009002c00a80ab9000200a700040003001f0ab800210ab7002b002a0019002900280024002700260025001800160017000f00060ab60015001b012b01820049000500390001001a010d0005006a010000840123008500aa016802860114003c00780159004d02050088003c01840ab50ab400670ab30ab2009c03b101ec0447043b03b803b7020a0014006702030005010c0041010b003b00f8003b00f7003b00b8003b00f6003b0074018303b001fa03af00ab004c003700470ab10ab000680001000800090aaf006200a9018900500030002f003a0066005d00420aae000a0aad000d00100013000100080009002c00a80aac000200a700040003001f0aab00210aaa002b002a0019002900280024002700260025001800160017000f00060aa9014c0015001b00b20283005f00650099000500060045008a0001001a006a01ea03ae0071018701e900b5003400470aa8004800310069001e001c001d0033002e005d004203b301e803b2000d00100013000100080009002c00440aa70002004300040003001f0aa600210aa5002b002a0019002900280024002700260025001800160017000f00060aa40015001b014c00de006d0005006b0001001a0090018103ad007c018601e900b5003400470aa3006200310072001e001c001d0033002e005d00420aa201e80aa1000d00100013000100080009002c00a80aa0000200a700040003001f0a9f00210a9e002b002a0019002900280024002700260025001800160017000f00060a9d0015001b014c00b200990005008a0001001a006a029403ac0071003400470a9c004800310069001e001c001d0033002e0023004203ab000a03aa000d00100013000100080009002c00440a9b0002004300040003001f0a9a00210a99002b002a0019002900280024002700260025001800160017000f00060a980015001b014c00de006d0005006b0001001a0a970a9600140a95007c018601e900b5003403a90a94006200310072001e001c001d0033002e005d0a9303a80a92000a0a91000d00100013000100080009002c00a80a90000200a700040003001f0a8f00210a8e002b002a0019002900280024002700260025001800160017000f00060a8d0015001b014c0a8c00b200990005008a0001001a0a8b0a8a01220a890071018701e900b5003403a90a880a87004800310069001e001c001d0033002e012503a803ab000a03aa000d00100013000100080009002c00440a860002004300040003001f0a8500210a84002b002a0019002900280024002700260025001800160017000f00060a830015001b014c0a8200f10049000500390001001a0203000500900280008401e7008500f8014e00f70287003200b80180003200f6027f003200aa016802130114003c00f00159004d02050088003c01840a810a8000670a7f0a7e0a7d004b00140a7c0a7b0a7a041600140a79001a01830a7800050a7700bf0a76004b00140a7503a7009303a60a7402c60a730214007e02c50a720a71006c003f0a700a6f000503a702160a6e02160a6d004b00050041027e0a6c009300140a6b0a6a0a69007e0a680a670035022100920a660a650a64003b0a630a620a610a6000140a5f0a5e0038007500140a5d0a5c00850a5b00380a5a00850a5900380a5800850a570a560a5500ef03e20a54019f0a530404019f0a5204030a51013a0a5002b300ab001c001d00500030002f003a0066002300c5000a000d001000130001000800090059005e0a4f0a4e005c027d005b005a00510a4d003d0a4c00580057001900560055004e005400530052001800160017000f00060a4b001500ee0a4a00ae005f00650049027c00050006004500390001001a00ab0038007500140a49013a00050402027b019d0a4800b7000500d20a47003d0a4600c203a50a45000503a402c40a4403a3014b0a43011502bb02cb0a4200ed03a20a41000503a10a40007d0a3f0a3e006e013b0a3d01fb007401e6006103a00a3c039f00b9006e01aa0067021e03bc006001a90032029d010000850109003801e50121010e018f0108010e01e700ac04430116009202170a3b00b60a3a009d02cf0a39013c02090a380a370063039e039d027a02be0a360a350a34039c039b0a33017f039a003c0a320a31006a01e40a300037007b00400a2f00680001000800090a2e03c2013603d4009700dd0a2d00be0030002f003a00c900230a2c000a0a2b000d00100013000100080009002c0a2a0a2900020a2800040003001f0a2700210a26002b002a0019002900280024002700260025001800160017000f000602bf039d00cb029a0a250a24008200ec001500ee0a2300ae005f0065004900050006004500390001001a0a2200610a21017f039a003c01e3003c0a200a1f006a007b004c03990a1e001100120007000c00200002000e00040003000b0a1d0022001100120007000c00200002000e00040003000b0a1c0022006400c203a50a1b00050a1a00390a1901070a1801070a1701070a1601070a150a14003e0a13003e0a12003e0a11003e0a10003e0a0f003e0441003e00740a0e01fe02bb02cb0a0d02c3015e04000a0c00c40a0b017f00ad003c00070a0a000504310a090a08012d03e30a0700390a0601070a0501070a0401070a0301070a020398003e0397003e0396003e0395003e0394003e0279003e0219003b00740a0103930392002d01e20a0002780034009e014a039109ff00b109fe02770149003109fd001e001c001d0033002e002300f0000a000d001000e20390000f000609fc0064027d09fb027609fa038f038e038d038c01a009f9038b09f8015c017e0108038a0389004600eb01e101e009f7004d09f601df00b403880387007300c3010603d9004b0005010500450148003900fa00140001001a03860049001409f509f4038500e100c40211020f0210020e015d009c020d019e020c008b003f0384017d00050383027b019d09f300b7000500d209f2038209f1038100e10014008809f00109020b01600014009200b5008809ef013200b300d3013109ee00370030002f003a0130012f000a00060110010901080046009e09ed09ec09eb006409ea00ac006409e90116009c09e809e7012b013c020909e60148002d0147003c038001de037f019000dc00f509e500cc0037007b0040028409e4006800010008000909e3004800dd017c00be0030002f003a00c90023037e000a0146000d00100013000100080009002c004409e20002004300040003001f09e1002109e0002b002a0019002900280024002700260025001800160017000f0006006409df001500ee0275037d00ae005f0065004900050006004500390001001a03860061012401f509de0148002d012b0147003c0088003c0274037f004f0038007b004c0184013c020909dd09dc009c014800df0380017d0005013b09db02d2037c009a037b03da0114016302d1004b000502d0004500410129012409da02a6008b027309d9007e009a02b2000502b1007d02b0003602af003602ae003602ad003602ac003602ab003602aa003602a9003602a8003602a7003602020036018e00360201003602000036018c0036012a0036003e09d8006f0092007309d700c40148002d00ad003c01450067015b0005008f09d6037a09d50038037902bd004103d8003b03d7003b03d6003b0156003b0155003b018b003b0154003b0153003b0152003b0128003b010c003b010b003b00f8003b00f7003b00b8003b00f6003b007400f503d500cc00370047027209d4006800010008000909d3004800a9012700500030002f003a0066002300420136000a00cb000d00100013000100080009002c004409d20002004300040003001f09d1002109d0002b002a0019002900280024002700260025001800160017000f0006006409cf00770015001b037801f90120005f00650377009b00050006004500ab00410001001a03ba027101ff00cb00710034004709ce004800310069001e001c001d0033002e00230042000a00cb000d00100013000100080009002c004409cd0002004300040003001f09cc002109cb002b002a0019002900280024002700260025001800160017000f0006006409ca0015001b007700f101900049000500d100390001001a0063002d017b00e3001402a5008009c902c702a400aa003700a5004009c800f40151000909c7004800dd017c00be0030002f003a00c9005d000a0080000d0010001300f4015100090150004409c60002004300040003001f09c5002109c4002b002a0019002900280024002700260025001800160017000f0006006409c300770015012600f101a2004900050063003900f4001a00d100dc006c00c3021801dd0073003f00ef002d037602a300cb00cc00370047000809c2004800a9012700500030002f003a006600230042000a00cb000d00100013000100080009002c004409c10002004300040003001f09c0002109bf002b002a0019002900280024002700260025001800160017000f0006006409be00770015001b00db010a004b0005004f00410001001a00ab0038018100750014014f008000710034017a00d409bd004800310069001e001c001d0033002e002300bd000a0080000d00100013000100080009002c004409bc0002004300040003001f09bb002109ba002b002a0019002900280024002700260025001800160017000f0006006409b90015001b007701f9009b0005007d0001001a00d1002d09b802a0001400ea039109b700e400c2029f004d03d009b6029e012203cf0005008a029d006c00c101880093003f03ce037503cc03cb03ca027509b5029c09b4007e00c201f8037401f700f2004c03c8006e01f600aa0081003103c7001e0034001c001d0033002e012500a5000a029a000d00100013000100080009002c00a809b3000200a700040003001f09b20021006409b1002b002a0019002900280024002700260025001800160017000f000609b00015001b00b20283005f00650099007700bc000500060045008a0001001a006a006c00c101880093003f01f503c6037503c503c403c3027509af014d007100340047037409ae004800310069001e001c001d0033002e002300420373000a0080000d00100013000100080009002c004409ad0002004300040003001f09ac002109ab002b002a0019002900280024002700260025001800160017000f0006006409aa0015001b007700bc00db010a004b0005004f00410001001a0090006c09a90299008000710034004709a8004800310069001e001c001d0033002e00230042000a0080000d00100013000100080009002c004409a70002004300040003001f09a6002109a5002b002a0019002900280024002700260025001800160017000f0006006409a40015001b007700bc00f10049000500390001001a004f003801f203c109a309a20080029700cc00370047000809a1004800a9012700500030002f003a0066002300420373000a0080000d00100013000100080009002c004409a00002004300040003001f099f0021099e002b002a0019002900280024002700260025001800160017000f00060064099d007700bc0015001b037201f901f8009b000500da007d0001001a003801f102960080007100340047099c004800310069001e001c001d0033002e00230042000a0080000d00100013000100080009002c0044099b0002004300040003001f099a00210999002b002a0019002900280024002700260025001800160017000f0006006409980015001b007700bc00db00f2004b0005007800410001001a004f003801f0029500ca00710187012200b000a500400997004800310069001e008100a600c00098005d000a00ca000d00100013000100080009002c004409960002004300040003001f099500210994002b002a0019002900280024002700260025001800160017000f0006006409930015001b007700bc00db010a004b0005004f00410001001a0078003802700293008000710187012200b000a500400992004800310069001e008100a600c00098005d000a0080000d00100013000100080009002c004409910002004300040003001f09900021098f002b002a0019002900280024002700260025001800160017000f00060064098e0015001b007700bc00db00f2004b0005007800410001001a004f003801ea029200ca007100340047098d004800310069001e001c001d0033002e00230042000a00ca000d00100013000100080009002c0044098c0002004300040003001f098b0021098a002b002a0019002900280024002700260025001800160017000f0006006409890015001b007700bc00db010a004b0005004f00410001001a007800380988029100800071003400470987004800310069001e001c001d0033002e00230042000a0080000d00100013000100080009002c004409860002004300040003001f098500210984002b002a0019002900280024002700260025001800160017000f0006006409830015001b007700bc00db00f2004b0005007800410001001a004f00380982014d00ca0071003400470981004800310069001e001c001d0033002e00230042000a00ca000d00100013000100080009002c004409800002004300040003001f097f0021097e002b002a0019002900280024002700260025001800160017000f00060064097d0015001b007700bc00db010a004b0005004f00410001001a00780038037102900080007100340047097c004800310069001e001c001d0033002e00230042000a0080000d00100013000100080009002c0044097b0002004300040003001f097a00210979002b002a0019002900280024002700260025001800160017000f0006006409780015001b007700bc00db00f2004b0005007800410001001a004f0038010a014f00ca0071003400470977004800310069001e001c001d0033002e00230042000a00ca000d00100013000100080009002c004409760002004300040003001f097500210974002b002a0019002900280024002700260025001800160017000f0006006409730015001b007700bc00f10049000500390001001a00780038028f0014015b0005028e0084028d022103bb028b028a006f01ef0085015601800032015501ed0032018b028c00320154028600320153026f00320152026e0032012803700032010c027f0032010b036f003200f801ee003200f70289003200b80288003200f603bd003200aa0129003801dc009302730124003c03a10972004d0971002d00ad003c02cc0161097001db002d01e2036e0278009e036d004d0037036c007b0040096f0204096e096d0277014900dd036b00be0030002f003a00c9005d000a000d001000e20390000f0006096c02730064027d096b0276096a038f038e038d038c01a00969038b09680967017e0108038a0389096600eb01da096509640032015f029b01df096309620387007300c1011f004b0005011e0045004100630408001400630135001a096100b70014096003e7095f095e0014095d001a095c0005036a021d095b01130014095a036900ad009c01d9026d0959095801e300e4026c0368026b0061003f095704060005036900b4026a00b40956006d0005006b0955095400ad0014095301a30952017903670951006000df01440950094f094e0074042c01a501340014094d01df00ad009c01d9026d094c01e300e4026c0366026b0061003f03650134000501df00b4026a00b400f5094b094a09490948006d000509470045006b0946094500ad001401950944017903670943006000df01440942094109400074093f093e093d01340014093c036400ad009c01d9026d093b01e300e4026c0407026b0061003f093a00b70005036400b4026a00b4009a09390938093709360935013400050934004502c402690933093200ad0014007a093100c40930092f006000df0222092e092d092c00740178018000df0104092b028501fb092a0215002d036301d8002d02680177002d021f0104010301db002d00f50929007102c903620040006300f209280135000809270926004800310069001e01390138092500980023037e000a0146000d001001d701d6000801d5002c004409240002004301d401d3001f09230021092201d201d1019b01d001cf01ce00eb01cd01cc01cb012e01ca015f000f0006006409210149001501c903720267008800c1011f014a00490005011e004500b9003900630135001a010402a100e300140920014600cc00b000780040091f004800310069001e008100a600c000980023000a0146000d001001d701d6000801d5002c0044091e0002004301d401d3001f091d0021091c01d201d1019b01d001cf01ce00eb01cd01cc01cb012e014901ca015f000f00060064091b001501c90267017b0049000500ea003900630135001a00b9002d0376091a036100cc00b0007800400919004800310069001e008100a600c000980023000a0361000d001001d701d6000801d5002c004409180002004301d401d3001f09170021091601d201d1019b01d001cf01ce00eb01cd01cc01cb012e014901ca015f000f000600640915001501c90267014a0049000500b9003900630135001a00ea002d017b0914014600cc00b0007800400913004800310069001e008100a600c000980023000a0146000d001001d701d6000801d5002c004409120002004301d401d3001f09110021091001d201d1019b01d001cf01ce00eb01cd01cc01cb012e014901ca015f000f00060064090f001501c9090e009b0005007d00630135001a090d000500b9002d090c0041090b03b90032090a004d090900a5004c09080360004c090701c8004c090600bd004c09050143004c09040109004c043801c7004c09030176004c03930078004c013b009e0175004d00e9006e02c3015e0902010409010147003c01de0266012d035f01040147003c090008ff08fe015e08fd012008fc08fb001100120007000c00200002000e00040003000b08fa0022001100120007000c00200002000e00040003000b08f90022001100120007000c00200002000e00040003000b08f8002200ab001c001d00500030002f003a0066002300c5000a000d001000e20013000f000608f7019a001108f608f5026508f40264026301c608f3007a08f2015c02080191020702060046019901980197012c004d013300b408f1007300c30106010a004b00050105004500d1003900fa00140001001a0063002d0049001408f008ef08ee0214009c01d902c608ed08ec0093007e02c5019e08eb006c003f08ea004b000501c508e908e808e7013a0005021d08e608e508e408e30014035e08e200d108e100750014012d004c035e08e000d100dc08df004b0005019f08de08dd01c5035d08dc08db02be08da039908d908d808d708d608d5009208d408d308d208d108d008cf035c08ce01a308cd03a608cc08cb003508ca08c908c808c708c601c4035b00b600e808c5003500b608c400e808c3003508c200e808c1003508c000e808bf011d08be035a08bd08bc0359035c08bb026201c308ba0179026102600174025f0144025e08b9025d01c4025c011d025b08b801c2035808b703570356026201c308b60179026102600174025f0144025e08b5025d01c4025c011d025b08b401c2035808b303570356026201c308b20179026102600174025f0144025e08b1025d01c408b0003500b608af00e808ae003508ad00e808ac003508ab00e808aa003508a900e8025c011d025b035a08a808a701a5035508a608a501a308a4027a016208a308a200b608a108a0089f089e0035089d00a4089c0035089b00a4089a0035089900a408980035089700a408960035089500a408940035089300a408920035089100a408900035088f00a4088e0035088d00a4088c0035003d02ce02cd088b00a4088a0035088900a40888003500b6088700a408860035088500a408840035088300a408820035088100e80880039c0354087f087e00d1025a0353019600c203db087d087c03520051087b0063002d0351003c087a08790090018308780037007b004008770068000100080009087602980875042f006200dd087400be0030002f003a00c900230873000a0872000d00100013000100080009002c00a80871000200a700040003001f08700021086f002b002a0019002900280024002700260025001800160017000f0006086e00ca086d00790083086c0353001500ee086b00ae005f0065004900050006004500390001001a03500061086a0063002d0351003c0869003c086808670090007b004c034f0866001100120007000c00200002000e00040003000b08650022001100120007000c00200002000e00040003000b08640022001100120007000c00200002000e00040003000b08630022001100120007000c00200002000e00040003000b08620022001100120007000c00200002000e00040003000b08610022001100120007000c00200002000e00040003000b08600022001100120007000c00200002000e00040003000b085f0022001100120007000c00200002000e00040003000b085e0022001100120007000c00200002000e00040003000b085d0022001100120007000c00200002000e00040003000b085c0022001100120007000c00200002000e00040003000b085b0022001100120007000c00200002000e00040003000b085a0022001100120007000c00200002000e00040003000b08590022001100120007000c00200002000e00040003000b08580022001100120007000c00200002000e00040003000b08570022001100120007000c00200002000e00040003000b08560022001100120007000c00200002000e00040003000b08550022001100120007000c00200002000e00040003000b08540022001100120007000c00200002000e00040003000b08530022001100120007000c00200002000e00040003000b08520022001100120007000c00200002000e00040003000b08510022001100120007000c00200002000e00040003000b08500022001100120007000c00200002000e00040003000b084f0022001100120007000c00200002000e00040003000b084e0022001100120007000c00200002000e00040003000b084d0022001100120007000c00200002000e00040003000b084c0022084b084a03a000670190010d0005004f0178003902590849007401e6007800ae003c01c508480847017f009e00da006e01e600ae003c084600f5084500cc0037007b0040034e08440001000800090843004800dd017c00be0030002f003a00c900230136000a00cb000d00100013000100080009002c004408420002004300040003001f084100210840002b002a0019002900280024002700260025001800160017000f0006027c083f0015001b0378083e0401005f0065028400b700050006004500ab0041083d001a0258083c008f003c083b083a00380282012b00f90257007b00bb00b001760040083908380049000500390837008100a60836034d00dd083500be0098005d000a00cb000d00100013000100080009002c004408340002004300040003001f083300210832002b002a0019002900280024002700260025001800160017000f0006027c08310015001b00f10049000500390001001a006300dc034c083000ac082f082e082d03dc00e7082c00bd004d0148002d00dc0214003c082b00da00b5002d0147003c0269002d082a011c0829082801e6082708260825082408230822082101c10820034b015d00c1011f017d0005011e004500840124034a006c081f007e081e00ed04390005081d00d2081c0016081b010f081a010f0036081900f90092007308180349015e0817081600d1002d00610815006701aa021e01240060003202c201ec0348008b02d3081400c208130812034f08110810080f080e080d014401c0080c080b080a01c20809034703a401a5080803460807009d04350806080503f203460159019508040196080308020801080007ff035907fe0219035207fd07fc07fb001100120007000c00200002000e00040003000b07fa0022001100120007000c00200002000e00040003000b07f90022001100120007000c00200002000e00040003000b07f80022001100120007000c00200002000e00040003000b07f70022001100120007000c00200002000e00040003000b07f60022001100120007000c00200002000e00040003000b07f50022001100120007000c00200002000e00040003000b07f40022001100120007000c00200002000e00040003000b07f30022001100120007000c00200002000e00040003000b07f20022001100120007000c00200002000e00040003000b07f10022001100120007000c00200002000e00040003000b07f00022001100120007000c00200002000e00040003000b07ef0022001100120007000c00200002000e00040003000b07ee0022001100120007000c00200002000e00040003000b07ed0022001100120007000c00200002000e00040003000b07ec0022001100120007000c00200002000e00040003000b07eb0022001100120007000c00200002000e00040003000b07ea0022001100120007000c00200002000e00040003000b07e90022001100120007000c00200002000e00040003000b07e8002203450067014a02ba000500f0021500390279016507e7034401780074017707e60074003b07e500d1002d00d9003c03430274004f0266012d017b002d009e0223006e01040088003c00ea00dc07e4010307e307e203b1034407e10037007b004007e0006800010008000907df02130139013800be017a008100a607de07dd0030002f003a0098000a000d00100013000100080009002c034207dc0002034100040003001f07db002107da002b002a0019002900280024002700260025001800160017000f000607d90015001b0340007300c1011f004b0005011e004500410001001a007800380075001407d8034c00bb004f00380173003c00a5003801dc019207d700f907d607d507d407d307d201eb00b0007b004007d100ef0030002f001e018002b80139013807d000c9008100a600c00098000a000d00100013000100080009002c034207cf0002034100040003001f07ce002107cd002b002a0019002900280024002700260025001800160017000f000607cc0015001b0340007300c30106004b00050105004500410001001a008f07cb00780038004c00d1002d00d9003c07ca02c707c907c8004b000501c5035d07c700ed07c607c507c400c1011f017d0005011e004501bf010201f8008401ed034a07c3006c07c2007e009a07c10005018c007d012a0036003e07c0006f0092007307bf013200b300d30131029c019c00370030002f003a0130012f000a0006011000780038006c07be004f07bd0046025603450067017b0255000500a501d80039017801fb00740259026800740067021f0255000500c501d80039017802a1007402590363007400ef002d07bc00ab07bb07ba00d9003c010902540103002d009a07b9033f0181009e033e033d004d0037004f004007b8006800d80121000907b700d9003c010902540103002d009a07b6033f0181009e033e033d004d0037004f004007b5006800d80121000907b400f0001c001d00500030002f003a0066005d004f000a000d0010001300d801210009015001be07b3000201bd00040003001f07b2002107b1002b002a0019002900280024002700260025001800160017000f000607b00015012601bc007300c1011f004b0005011e0045004100d8001a00f0003801bb0014017a01020077033c01a400a3021c033b00f901bf00bb007800380173003c008f003801c107af033a01ba007b0272025700bb003400da00d407ae00b90030002f001e001c001d0033002e005d004f000a000d0010001300d801210009015001be07ad000201bd00040003001f07ac002107ab002b002a0019002900280024002700260025001800160017000f000607aa0015012601bc007300c30106004b000501050045004100d8001a00b9002d01b9001400f00219010800bd003807a900f0001c001d00500030002f003a0066005d004f000a000d0010001300d801210009015001be07a8000201bd00040003001f07a7002107a6002b002a0019002900280024002700260025001800160017000f000607a50015012601bc007300c1011f004b0005011e0045004100d8001a00f0003801bb0014017a0102008100140077033c01a4034d001400a3021c033b00f901bf00bb007800380173003c008f003801c107a4033a01ba007b0272025700bb003400da00d407a300b90030002f001e001c001d0033002e005d004f000a000d0010001300d801210009015001be07a2000201bd00040003001f07a1002107a0002b002a0019002900280024002700260025001800160017000f0006079f0015012601bc007300c30106004b000501050045004100d8001a00b9002d01b9001400bd0038001c00140223079e010200810014079d00f9033900bb00c5004d00ef002d00d9003c01090254014a00dc00ed079c0145006e0037007b00400008079b02870139013800be0030002f003a00c90023000a000d00100013000100080009002c0101079a000200ec00040003001f079900210798002b002a0019002900280024002700260025001800160017000f000607970015001b01720120005f006501ba009b00050006004500bd00410001001a00bd011b0005008f003800790253007d0252007800380173003c00f0003801c1079600f90795034e0794079300b5003400da00d4079200e90030002f001e001c001d0033002e005d004f000a000d00100013000100080009002c01010791000200ec00040003001f07900021078f002b002a0019002900280024002700260025001800160017000f0006078e0015001b0338007300c30106004b00050105004500410001001a00e9002d0103013200b300d3013102c8019c00370030002f003a0130012f000a0006011000460251078d02500337024f00b30037078c024e00b300370030002f003a024d024c000a0006011001430108004600ad005f033600ac0163024b033503340333002d0332078b011c078a033107890007078801f0004d0037014200400787006800010008000907860330001c001d00500030002f003a006600230142000a000d00100013000100080009002c078507840002078300040003001f078200210781002b002a0019002900280024002700260025001800160017000f00060780001500ee077f00ae005f0065004900050006004500390001001a03300212077e008b077d077c077b00e701800060008b032f077a07790778077700e700e1077600d7007e077502b300d7000503dd00d20074077400ac07730772032e00e7006700d700050771077001230084004c0007011b0005027f006002ca007d032d0032009a01b80005012a007d003e0038002d032c011c009a01b80005032b032a003900850067010d00050100008401230329010e032800df0327032600ea004c03330143004c00ef002d00d9003c00b9002d009a076f00850362076e076d0271004c0037004f0040076c0068000100080009076b008f001c001d00500030002f003a0066005d004f000a000d00100013000100080009002c0101076a000200ec00040003001f076900210768002b002a0019002900280024002700260025001800160017000f00060767001500ee076600ae005f0065004900050006004500390001001a00e9002d0103013200b300d3013102c8019c00370030002f003a0130012f000a0006011000460251076502500337024f00b300370764024e00b300370030002f003a024d024c000a0006011001c80108004600ad005f033600ac0163024b033503340171002d07630762011c0761033107600007075f01dd004d003701430040075e0068000100080009075d01c8001c001d00500030002f003a006600230143000a000d00100013000100080009002c075c075b0002075a00040003001f075900210758002b002a0019002900280024002700260025001800160017000f00060757001500ee075600ae005f0065004900050006004500390001001a014207550754075300e701c80038006c075200d7000503df007d00740751008b0750074f032e00e7006700d70005074e074d00d7007e000501230084004c0007011b00050124006002ca007d032d0032009a01b80005012a007d003e0038002d032c011c009a01b80005032b032a003900850067010d00050100008401230329010e032800df03270326013b004c01710176004c00ef002d00d9003c0067026800d7000500b9002d074c00ea002d01b7017500410325006e00ed01f70129004c074b006e014501f6037a00df0037004f0040074a00680001000800090749008f001c001d00500030002f003a00660125004f000a000d00100013000100080009002c01010748000200ec00040003001f074700210746002b002a0019002900280024002700260025001800160017000f000607450015001b01720120005f00650744009b00050006004500a500410001001a00a5011b0005008f003802bf0253007d025200ed0145006c07430176003801dd01b601dc00bb003400da00d4074200e90030002f001e001c001d0033002e0023004f000a000d00100013000100080009002c01010741000200ec00040003001f07400021073f002b002a0019002900280024002700260025001800160017000f0006073e0015001b01720120005f00650332009b000500060045014300410001001a008f003801bb0014073d073c024a073b01b6039f00bb003400da00d4073a024a0030002f001e001c001d0033002e0023004f000a000d00100013000100080009002c073907380002073700040003001f073600210735002b002a0019002900280024002700260025001800160017000f000607340015001b07330049000500390001001a024a002d01b9001400a5004d0067010300e900d70005008f01770039003b00ea002d017600380324011c000702a6011b000501b701750041006e00070732004d029403230129004c003701c7004000080731008f001c001d00500030002f003a0066005d01c7000a000d00100013000100080009002c01010730000200ec00040003001f072f0021072e002b002a0019002900280024002700260025001800160017000f0006072d0015001b0338007300c3010601ea004b00050105004500ea00390001001a00e900dc072c006c072b072a072900e700bd0038006c032f01b701020728072700730726072500ad00e700ef002d00d9003c00ea00d7000500b9002d01b5013b002d01bf017500410325006e00ed01f70129004c0724006e014501f6034b00aa0037004f004000080723008f001c001d00500030002f003a00660125004f000a000d00100013000100080009002c01010722000200ec00040003001f072100210720002b002a0019002900280024002700260025001800160017000f0006071f0015001b01720120005f006501ba009b00050006004500bd00410001001a00bd011b0005008f003800790253007d025200ed0145006c071e00a50038027101b601dc00bb003400da00d4071d00e90030002f001e001c001d0033002e0023004f000a000d00100013000100080009002c0101071c000200ec00040003001f071b0021071a002b002a0019002900280024002700260025001800160017000f000607190015001b01720120005f006503a2009b00050006004501c700410001001a008f003801bb0014071807170171071601b6033900bb003400da00d4071501710030002f001e001c001d0033002e0023004f000a000d00100013000100080009002c071407130002071200040003001f071100210710002b002a0019002900280024002700260025001800160017000f0006070f0015001b070e0049000500390001001a0171002d01b9001400bd004d0067010300e900d70005008f01770039003b0269002d00a500380324011c00070181011b0005017a01750041006e000703b0004d01ea03230129004c003700c500400008070d00a5001c001d00500030002f003a0066005d00c5000a000d00100013000100080009002c070c070b0002042e00040003001f070a00210709002b002a0019002900280024002700260025001800160017000f00060708001500ee02d600ae005f0065004900050006004500390001001a00bd021200a50108070700ac07060705016100e7010d0005010000840704003e01f501020703003c01b707020701007701a4070000aa03480085036000380173003c06ff06fe004d0322002d00d9003c00ab06fd00ef002d06fc06fb06fa06f9014a06f80349015e06f703220109004d013b002d00d9003c0343027400c50266012d0223035f01040088003c00ab06f6032106f50190002d0167007306f406f3017000d000cf032000ce00cd007000d000cf06f200ce00cd007002dc031f031e031d0007000c031c02da000e01410140000b06f106f002dc031f031e031d0007000c031c02da000e01410140000b06ef007a06ee06ed017e0192024901da004600eb01e101e0012c006e06ec02b406eb06ea06e90007000c06e801b4000e01410140000b06e7007a03e1031b017e0192024901da004600eb01e101e0012c06e60063024802470007000c024601b4000e01410140000b06e5031a0063024802470007000c024601b4000e01410140000b06e4031a0063024802470007000c024601b4000e01410140000b06e3007a06e2031b017e0192024901da004600eb01e101e0012c006e006302b502b400d000cf06e100ce00cd007000d000cf031900ce00cd007000ed037706e000bb029e01a10032029f06df00ab04110030002f001c001d02b5005000660070001100120007000c00200002000e00040003000b06de0022001100120007000c00200002000e00040003000b06dd0022001100120007000c00200002000e00040003000b06dc0022001100120007000c00200002000e00040003000b06db0022001100120007000c00200002000e00040003000b06da0022001100120007000c00200002000e00040003000b06d90022001100120007000c00200002000e00040003000b06d80022001100120007000c00200002000e00040003000b06d70022001100120007000c00200002000e00040003000b06d60022001100120007000c00200002000e00040003000b06d50022001100120007000c00200002000e00040003000b06d40022001100120007000c00200002000e00040003000b06d30022001100120007000c00200002000e00040003000b06d20022001100120007000c00200002000e00040003000b06d10022001100120007000c00200002000e00040003000b06d00022001100120007000c00200002000e00040003000b06cf0022001100120007000c00200002000e00040003000b06ce0022001100120007000c00200002000e00040003000b06cd0022001100120007000c00200002000e00040003000b06cc0022024506cb008b06ca007e06c906c8003500160092011406c706c6003b06c5021606c40096024501a902b70102010e010000600318006f01e500600317006f018f006002b9006f01e7006006c3006f0280006006c2006f03f9006006c1006f0316006006c0006f0315006006bf006f0314006006be006f02440060008b0163024b06bd006f0313006006bc006f0312006001a906bb006f01ef006006ba006f06b9006006b8006f06b706b6002d004d009601a106b506b406b303e406b206b100f906b000ac06af00e001b301b2019401930162000b06ae06ad014b003500b60311004a06ac003500b60310004a036a0035030f004a06ab0035025a004a06aa011d02430242030e06a901a5004a06a80241003d06a700e001b301b2019401930162015a06a60240014b023f011d024302420426009d06a5030d030c0241003d06a400e001b301b2019401930162015a06a30240014b023f011d024302420424009d039e030d030c0241003d06a200e001b301b2019401930162015a06a10240014b0422009d043606a001150420009d069f0115041e009d069e0115041c009d069d0115023f069c069b069a06990698003800df02120697008b069600c400920191042d00b60695009d02cf042b00350311004a042a00350310004a04290035030f004a04280035025a004a04270035030e004a0425003503fb004a042300350694004a042100350693004a041f00350692004a041d0035003d02ce02cd0691004a041b00350690004a041a003500b6068f004a04190035068e004a04180035068d004a041701a4068c021c068b02cc0161068a00960689009e06880687004c0096024501a902b70102010e010000600318006f01e500600317006f018f006002b9006f015903e0002d004d00960686023e030b006706850684015600410155030a018501280185010c0185010b018506830244003e0314003e0315003e0316003e018f003e01e5003e03090074003b06820309039200dc00f502d500cc0037007b004001f206810204006806800048030800dd017c00be0030002f003a00c90023000a000d001000e20013000f0006067f030a016f019a0011067e067d0265067c0264026301c6067b007a067a015c02080191020702060046019901980197012c004d013300b400db007300c3010601f1004b00760105011a016e003900fa00a201b1067902a2004900a2067800f1038500e100c40211020f0210020e015d009c020d019e020c008b01b00384017d00760383027b019d067700b7007600d2067603820675038100e100a2008806740142020b016000a2009200b500880673013200b300d30131067200370030002f003a0130012f000a00060671014202170046009e0670066f066e066d003d066c030700e001160306066b01de066a0258007b004c013c0669015a0668016e002d0305016d06670666025800f506650037007b0040066400680001000800090663066206610304004800dd017c00be0030002f003a00c9002303bf000a03be000d00100013000100080009002c004406600002004300040003001f065f0021065e002b002a0019002900280024002700260025001800160017000f0006065d065c030303020307065b001500ee037d00ae005f0065004900760006011a00390001011902a20061065a016e002d0305016d0147065900d000cf032000ce00cd00700116016e00aa00b7007601de02d2037c009a037b06580114016302d1004b007602d0011a004103010657007a0656007e009a02b2007602b1007d02b0003602af003602ae003602ad003602ac003602ab003602aa003602a9003602a8003602a7003602020036018e00360201003602000036018c0036012a0036003e000c006f009200730655009c03040306016e002d0088016d01ec02700654002d009e0653043301ee03020303030100380114016d0652004d0651002d0088016d0184015d065001db002d01e2036e0278009e036d004d0037036c007b0040064f02040068064e0277064d00dd036b00be0030002f003a00c9005d000a000d001000e20013000f0006064c064b019a00110276064a026506490264026301c60648007a0647015c02080191020702060046019901980197012c004d01330646064500ae005f0065004900760006011a003900fa00a2000101190644009b00a2064306420641064000a2063f01190255007603de00d2063e013a00a2063d063c01a0019602bc03ef063b063a039b027a063903ed063801c301b00365013400760637021b0414021b063600990076008a06350634063300a2063201950631023d030006300174027e02ff062f062e062d03a3062c009d011300a2062b03f102fe019602bc03f0062a015a00e003ee036803ec019501b003eb0113007603ea03e903e8062901e20628035406270626009900760625011a008a06240623062200a203e60621023d030006200174027e02ff061f061e02fd014b0355061d009d011300a2061c02fc01c600e0061b061a0619061800c2061703660616003d01b00615009b007602fc02fb061402fb00f502fd061306120611011300760610011a03fa060f060e02fe00a200ac060d007e0405060c01c2034700920093060b060a003b00b802fa002d02f9017f060906080215002d030b01d8002d06070177002d02560104060601db00dc01e403f302f80037037900470308060506040001000800090603009700a902f700500030002f003a00660023004202f6000a02f5000d001000130001000800090059005e00a10602005c00a0005b005a00510601003d060000580057001900560055004e005400530052001800160017000f0006016f05ff01af0015001b00af018a005f0065006d00760006011a006b0001011900d6023e007500a205fe007c0034004705fd006200310072001e001c001d0033002e0023004202f4000a02f3000d001000130001000800090059005e009505fc005c0094005b005a005105fb003d05fa00580057001900560055004e005400530052001800160017000f0006016f05f90015001b01af00d500c8007600bf00010119006a023c05f800e60034004705f70097003100ba001e001c001d0033002e00230042023b000a023a000d001000130001000800090059005e00a105f6005c00a0005b005a005105f5003d05f400580057001900560055004e005400530052001800160017000f0006016f05f30015001b01af00af006d0076006b00010119035b05f2007c0034004705f105f0006200310072001e001c001d0033002e002300420239000a0238000d001000130001000800090059005e009505ef005c0094005b005a005105ee003d05ed00580057001900560055004e005400530052001800160017000f0006016f05ec0015001b01af05eb01820049007600390001011905ea0076006a03120084031305e9010e02440085015405e8015302370032015202f20032012802fa010c02360032010b026e003200f80235003200f7026f003200b8012205e7007b012300850430004c009600d000cf018d00ce00cd007000e40070001100120007000c01180002000e00040003000b05e6007a05e50158013700ff00fe00fd004600fc0112011100fb006e0157001c001d0050002e00700170001100120007000c01180002000e00040003000b05e4013f001100120007000c01180002000e00040003000b05e3013f001100120007000c01180002000e00040003000b05e2013f001100120007000c01180002000e00040003000b05e1013f001100120007000c01180002000e00040003000b05e0013f001100120007000c01180002000e00040003000b05df013f05de000705dd05dc02b6008402f1003e003b01ff01e400e6003401b5004705db05da006800010008000905d90097003100ba001e001c001d0033002e0023004202f0000a02ef000d001000130001000800090059005e00a105d8005c00a0005b005a005105d7003d05d600580057001900560055004e005400530052001800160017000f000605d502340015001b00af018a005f0065006d01ae000605d4006b01b105d300d6007502ee03b4028100b0004005d2006200310072001e008100a600c00098002305d1000a05d0000d001000130001000800090059005e009505cf005c0094005b005a005105ce003d05cd00580057001900560055004e005400530052001800160017000f000605cc0015001b023400d500c801ae00bf000102ed006a007502ee028202ec05cb01eb00b0004005ca0097003100ba001e008100a600c00098005d02f0000a02ef000d001000130001000800090059005e00a105c9005c00a0005b005a005105c8003d05c700580057001900560055004e005400530052001800160017000f000605c60015001b023405c5004901ae0039000102ed010d01ae00d6010000840123008500aa009600e4007000d000cf018d00ce00cd0070001100120007000c02330002000e00040003000b05c402eb001100120007000c02330002000e00040003000b05c302eb001100120007000c02330002000e00040003000b05c2007a05c10158013700ff00fe00fd004600fc0112011100fb006e0157001c001d0050002e007005c0000705bf05be05bd008405bc003e05bb003e05ba003e05b9003e05b8003e0398003e0397003e0396003e0395003e05b7003e05b6003e05b5003e0394003e0279003e02b6003e02f1003e003b05b40183007c003401b5004705b305b2006800010008000905b1006200310072001e001c001d0033002e002300420232000a0231000d001000130001000800090059005e009505b0005c0094005b005a005105af003d05ae00580057001900560055004e005400530052001800160017000f000605ad00870015001b00d502ea005f006500c8007f000602e900bf01b105ac006a01f001ff00e60034004705ab0097003100ba001e001c001d0033002e0023004202e8000a02e7000d001000130001000800090059005e00a105aa005c00a0005b005a005105a9003d05a800580057001900560055004e005400530052001800160017000f000605a70015001b008700af006d007f006b0001008e01c005a601ad02a505a503af00aa0037009105a405a300f40151000905a205a1006200a9018900500030002f003a0066005d00890232000a0231000d0010001300f401510009005905a00095059f005c0094005b005a0051059e003d059d00580057001900560055004e005400530052001800160017000f0006059c008700e5059b0015012600d500c8007f00bf00f4008e006a006c00c302180270007302e60285025602a302f800370047059a00080599009700a902f700500030002f003a00660023004202e8000a02e7000d001000130001000800090059005e00a10598005c00a0005b005a00510597003d059600580057001900560055004e005400530052001800160017000f00060595008700e50015001b00af006d007f006b0001008e00d601f1007501ad014f007c0034059400d40593006200310072001e001c001d0033002e002301420232000a0231000d001000130001000800090059005e00950592005c0094005b005a00510591003d059000580057001900560055004e005400530052001800160017000f0006058f0015001b008700e500b20099007f008a0001008e035002f902a001ad02e502e4023d00c2058e058d058c02a400aa003700910388058b01f40230004800a9012700500030002f003a006601250089058a000a0589000d00100013000100080009002c004405880002004300040003001f058700210586002b002a0019002900280024002700260025001800160017000f000602e401f30585008700a300e502e50015001b058402ea005f006500c8007f000602e900bf0001008e0090006c00c10188009302e60583058205810580057f057e057d014d00e600340047057c02300097003100ba001e001c001d0033002e00230042057b000a057a000d001000130001000800090059005e00a10579005c00a0005b005a00510578003d057700580057001900560055004e005400530052001800160017000f000605760015001b008700a300e500af006d007f006b0001008e00d6006c023005750299007c003400470574006200310072001e001c001d0033002e0023004201f4000a01f3000d001000130001000800090059005e00950573005c0094005b005a00510572003d057100580057001900560055004e005400530052001800160017000f000605700015001b008700a300e501820049007f00390001008e006a056f056e007e029701fa0037004701dd056d0008056c006200a9018900500030002f003a00660023004201f4000a01f3000d001000130001000800090059005e0095056b005c0094005b005a0051056a003d056900580057001900560055004e005400530052001800160017000f00060568008700a300e50015001b00d500c8007f00bf0001008e006a03c0029600e60034004705670097003100ba001e001c001d0033002e002300420566000a0565000d001000130001000800090059005e00a10564005c00a0005b005a00510563003d056200580057001900560055004e005400530052001800160017000f000605610015001b008700a300e500af006d007f006b0001008e00d603710295007c01860122003400910560006200310072001e001c001d0033002e005d0089055f000a055e000d001000130001000800090059005e0095055d005c0094005b005a0051055c003d055b00580057001900560055004e005400530052001800160017000f0006055a0015001b008700a300e500d500c8007f00bf0001008e006a01f2029300e6022f01220034009105590097003100ba001e001c001d0033002e005d008902f6000a02f5000d001000130001000800090059005e00a10558005c00a0005b005a00510557003d055600580057001900560055004e005400530052001800160017000f000605550015001b008700a300af006d007f006b0001008e00d6023e0292007c003400470554006200310072001e001c001d0033002e0023004202f4000a02f3000d001000130001000800090059005e00950553005c0094005b005a00510552003d055100580057001900560055004e005400530052001800160017000f000605500015001b008700a300d500c8007f00bf0001008e006a023c029100e600340047054f0097003100ba001e001c001d0033002e00230042054e000a054d000d001000130001000800090059005e00a1054c005c00a0005b005a0051054b003d054a00580057001900560055004e005400530052001800160017000f000605490015001b008700a300af006d007f006b0001008e00d602e3014d007c003400470548006200310072001e001c001d0033002e002300420547000a0546000d001000130001000800090059005e00950545005c0094005b005a00510544003d054300580057001900560055004e005400530052001800160017000f000605420015001b008700a300d500c8007f00bf0001008e006a02e2029000e60034004705410097003100ba001e001c001d0033002e00230042023b000a023a000d001000130001000800090059005e00a10540005c00a0005b005a0051053f003d053e00580057001900560055004e005400530052001800160017000f0006053d0015001b008700a300af006d007f006b0001008e01c0014f007c00340047053c053b006200310072001e001c001d0033002e002300420239000a0238000d001000130001000800090059005e0095053a005c0094005b005a00510539003d053800580057001900560055004e005400530052001800160017000f000605370015001b008700a3053601820049007f00390001008e006a028f01ad015b007f028e0084028d0221026e028b028a006f01ef0085015602890032015503700032018b036f00320154014e015302360032015202350032012802370032010c02f20032010b0288003200f8026f003200f701ed003200b8028c003200f601ee003200aa009600e4007000d000cf018d00ce00cd0070001100120007000c00860002000e00040003000b0535007a05340158013700ff00fe00fd004600fc0112011100fb006e0157001c001d0050002e0070001100120007000c00860002000e00040003000b0533008d001100120007000c00860002000e00040003000b0532008d001100120007000c00860002000e00040003000b0531008d001100120007000c00860002000e00040003000b0530008d001100120007000c00860002000e00040003000b052f008d001100120007000c00860002000e00040003000b052e008d001100120007000c00860002000e00040003000b052d008d001100120007000c00860002000e00040003000b052c008d001100120007000c00860002000e00040003000b052b008d001100120007000c00860002000e00040003000b052a008d001100120007000c00860002000e00040003000b0529008d001100120007000c00860002000e00040003000b0528008d001100120007000c00860002000e00040003000b0527008d001100120007000c00860002000e00040003000b0526008d001100120007000c00860002000e00040003000b0525008d001100120007000c00860002000e00040003000b0524008d0523009a052205210202007d018e00360201003602000036018c0036012a0036003e052001e4051f051e022f051d0032003401b50047051c051b0068000100080009051a0097003100ba001e001c001d0033002e005d00420519000a0518000d001000130001000800090059005e00a10517005c00a0005b005a00510516003d051500580057001900560055004e005400530052001800160017000f00060514013e0015001b00af018a005f0065006d011700060513006b01b1051200d6023c03ae007c018601ac00b5003400470511006200310072001e001c001d0033002e005d0042051001e8050f000d001000130001000800090059005e0095050e005c0094005b005a0051050d003d050c00580057001900560055004e005400530052001800160017000f0006050b0015001b013e00d500c8011700bf0001016c006a02e303ad00e6022f01ac00b500340047050a0097003100ba001e001c001d0033002e005d0042050901e80508000d001000130001000800090059005e00a10507005c00a0005b005a00510506003d050500580057001900560055004e005400530052001800160017000f000605040015001b013e00af006d0117006b0001016c00d602e203ac007c003400470503006200310072001e001c001d0033002e002300420239000a0238000d001000130001000800090059005e00950502005c0094005b005a00510501003d050000580057001900560055004e005400530052001800160017000f000604ff0015001b013e00d500c8011700bf0001016c006a007504fe04fd02ec04fc01ac02e100b0004004fb0097003100ba001e008100a600c00098005d04fa023b000a023a000d001000130001000800090059005e00a104f9005c00a0005b005a005104f8003d04f700580057001900560055004e005400530052001800160017000f000604f60015001b013e04f500af006d0117006b0001016c01c004f401eb04f3028104f201ac02e100b0004004f104f0006200310072001e008100a600c00098012504ef000a04ee000d001000130001000800090059005e009504ed005c0094005b005a005104ec003d04eb00580057001900560055004e005400530052001800160017000f000604ea0015001b013e04e901820049011700390001016c02030117006a0280008401e7008500f8014e00f70236003200b80235003200f60237003200aa009600d000cf018d00ce00cd007000e40070001100120007000c013d0002000e00040003000b04e8016b001100120007000c013d0002000e00040003000b04e7016b001100120007000c013d0002000e00040003000b04e6016b001100120007000c013d0002000e00040003000b04e5016b001100120007000c013d0002000e00040003000b04e4016b001100120007000c013d0002000e00040003000b04e3007a04e20158013700ff00fe00fd004600fc0112011100fb006e0157001c001d0050002e0070025104e1025004e0024f00b3003704df024e00b300370030002f003a024d024c000a000604de00460096017000d000cf031900ce00cd0070017004dd04dc04db04da040e007e04d904d804d704d604d50321008804d40139013801570034001c001d0033002e04d30042000a000604d200460096017004d102e00096007e009604d002e00096007e009604cf00c70070000000000000022e00000000000004ce00000000000004cd0000022e009f009f04cc0000000000000000000002df000000000000000004cb04ca00000000000004c9000004c8000000000000000004c700000000000004c600000000000004c500000000000004c400000000000004c300000000000004c200000000000004c100000000000004c000000000000004bf00000000000004be00000000000004bd00000000000004bc00000000000004bb00000000000004ba00000000000004b900000000000004b800000000000004b700000000000004b600000000000004b500000000000004b400000000000004b300000000000004b200000000000004b100000000000004b004af04ae04ad04ac0000000004ab0000000000000000009f02de009f009f022d00000000000004aa0000000004a9022d00000000000004a804a700000000000004a600000000000004a50000000000000000000004a4000004a300000000000004a200000000000004a10000000000000000000002dd000000000000000004a0049f000000000000049e000000000000049d000000000000049c000000000000049b000000000000049a0000000000000499000000000000049800000000000004970000000000000496000000000000000000000495000002de009f009f009f04940000000000000000000004930000000000000492000000000000049100000000000004900000000000000000048f000000000000048e048d000000000000048c000000000000048b000000000000048a00000000000004890000000000000000000004880000022c000002dd00000487000000000000048600000000000004850000000000000484000000000000000000000000048300000000000004820481000000000000022e009f009f009f0480000000000000047f000000000000047e000000000000047d000000000000047c000000000000047b047a04790478022c000002df00000477047604750474000000000000047300000000047204710470046f046e0000046d000000000000046c000000000000046b000000000000046a0000000000000469000000000000046800000000000004670000000000000466000000000000046500000000000000000000046400000463000000000000000000000462000000000000000004610000000004600000000000000000045f045e000000000000045d000000000000045c000000000000045b000000000000000000000000045a04590000000000000458000000000000045700000000000004560000000000000000000000000455009f009f009f022d0000000000000454000000000000045300000000000004520000000000000451022c00000000000000000000000000000450044f044e044d000000000000000000000000000000000000000000000000000000000000", + "logIndex": 2, + "blockHash": "0x15cb1c4093e40af087567a3e66834d93f6f5ea7ad9873a798693bdc29d641895" }, { - "transactionIndex": 4, - "blockNumber": 43551227, - "transactionHash": "0xfac1fd7b98aa5cfb77cd0d27e86ed268b5e7a61d733943cea154d8801e490f6e", + "transactionIndex": 0, + "blockNumber": 69333566, + "transactionHash": "0x34c60e6149487852ea51a994b1f6b49dfd33e3c7d64f6955014b95324f66b53b", "address": "0x0000000000000000000000000000000000008004", "topics": [ "0xc94722ff13eacf53547c4741dab5228353a05938ffcdd5d4a2d533ae0e618287", - "0x01000c07af31fb10c1815b79a3a8b1323e3f8223476b3f54e99930cbdab9ce14", + "0x01000e2dca2af8ea46588503a81cb7bc48163fa18d8a68c5ee46bc15ac0383cd", "0x0000000000000000000000000000000000000000000000000000000000000000" ], "data": "0x", - "logIndex": 22, - "blockHash": "0x00c8980923ce93732373f6e10773875b41b98308271c9d301738a75662fba4ed" + "logIndex": 3, + "blockHash": "0x15cb1c4093e40af087567a3e66834d93f6f5ea7ad9873a798693bdc29d641895" }, { - "transactionIndex": 4, - "blockNumber": 43551227, - "transactionHash": "0xfac1fd7b98aa5cfb77cd0d27e86ed268b5e7a61d733943cea154d8801e490f6e", + "transactionIndex": 0, + "blockNumber": 69333566, + "transactionHash": "0x34c60e6149487852ea51a994b1f6b49dfd33e3c7d64f6955014b95324f66b53b", "address": "0x0000000000000000000000000000000000008006", "topics": [ "0x290afdae231a3fc0bbae8b1af63698b0a1d79b21ad17df0342dfb952fe74f8e5", - "0x0000000000000000000000007f423e50147930e197daae9f637198e66746d597", - "0x01000c07af31fb10c1815b79a3a8b1323e3f8223476b3f54e99930cbdab9ce14", - "0x00000000000000000000000069fc4232959131b4992597b739cec97ee898aa68" + "0x000000000000000000000000f39495a0abcd780c367e6aba747db98dd54187bc", + "0x01000e2dca2af8ea46588503a81cb7bc48163fa18d8a68c5ee46bc15ac0383cd", + "0x000000000000000000000000437afd23d8929c382e0cbed30bf7a0a4310c8071" ], "data": "0x", - "logIndex": 23, - "blockHash": "0x00c8980923ce93732373f6e10773875b41b98308271c9d301738a75662fba4ed" + "logIndex": 4, + "blockHash": "0x15cb1c4093e40af087567a3e66834d93f6f5ea7ad9873a798693bdc29d641895" }, { - "transactionIndex": 4, - "blockNumber": 43551227, - "transactionHash": "0xfac1fd7b98aa5cfb77cd0d27e86ed268b5e7a61d733943cea154d8801e490f6e", + "transactionIndex": 0, + "blockNumber": 69333566, + "transactionHash": "0x34c60e6149487852ea51a994b1f6b49dfd33e3c7d64f6955014b95324f66b53b", "address": "0x000000000000000000000000000000000000800A", "topics": [ "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", "0x0000000000000000000000000000000000000000000000000000000000008001", - "0x0000000000000000000000007f423e50147930e197daae9f637198e66746d597" + "0x000000000000000000000000f39495a0abcd780c367e6aba747db98dd54187bc" ], - "data": "0x0000000000000000000000000000000000000000000000000002422457a35880", - "logIndex": 24, - "blockHash": "0x00c8980923ce93732373f6e10773875b41b98308271c9d301738a75662fba4ed" + "data": "0x00000000000000000000000000000000000000000000000000005ece02568ae0", + "logIndex": 5, + "blockHash": "0x15cb1c4093e40af087567a3e66834d93f6f5ea7ad9873a798693bdc29d641895" } ], - "blockNumber": 43551227, + "blockNumber": 69333566, "cumulativeGasUsed": "0", "status": 1, "byzantium": true }, - "args": [true, 0], - "numDeployments": 1, - "solcInputHash": "6cc413ed5bf9593899dec1514c1a16cf", + "args": [true, 0, "0xddE4D098D9995B659724ae6d5E3FB9681Ac941B1"], + "numDeployments": 2, + "solcInputHash": "10818118264cbc82e2eea514eb3f075b", "metadata": { "llvm_options": [], "optimizer_settings": { @@ -1280,12 +1298,12 @@ "level_middle_end_size": "Zero" }, "solc_version": "0.8.25", - "solc_zkvm_edition": "1.0.1", - "source_metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.47b979f3\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"timeBased_\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"blocksPerYear_\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidBlocksPerYear\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTimeBasedConfiguration\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"blocksOrSecondsPerYear\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"}],\"name\":\"getAllPools\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockNumberOrTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getPendingRewards\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"distributorAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"rewardTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalRewards\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.PendingReward[]\",\"name\":\"pendingRewards\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.RewardSummary[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getPoolBadDebt\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalBadDebtUsd\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"badDebtUsd\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.BadDebt[]\",\"name\":\"badDebts\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.BadDebtSummary\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolByComptroller\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolRegistryInterface.VenusPool\",\"name\":\"venusPool\",\"type\":\"tuple\"}],\"name\":\"getPoolDataFromVenusPool\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getPoolsSupportedByAsset\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getVTokenForAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isTimeBased\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"vTokenBalances\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalanceCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balanceOfUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenAllowance\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenBalances\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"vTokenBalancesAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalanceCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balanceOfUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenAllowance\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenBalances[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"vTokenMetadata\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"vTokenMetadataAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"vTokenUnderlyingPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"underlyingPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenUnderlyingPrice\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"vTokenUnderlyingPriceAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"underlyingPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenUnderlyingPrice[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"params\":{\"blocksPerYear_\":\"The number of blocks per year\",\"timeBased_\":\"A boolean indicating whether the contract is based on time or block.\"}},\"getAllPools(address)\":{\"details\":\"This function is not designed to be called in a transaction: it is too gas-intensive\",\"params\":{\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"Arrays of all Venus pools' data\"}},\"getBlockNumberOrTimestamp()\":{\"details\":\"Function to simply retrieve block number or block timestamp\",\"returns\":{\"_0\":\"Current block number or block timestamp\"}},\"getPendingRewards(address,address)\":{\"params\":{\"account\":\"The user account.\",\"comptrollerAddress\":\"address\"},\"returns\":{\"_0\":\"Pending rewards array\"}},\"getPoolBadDebt(address)\":{\"params\":{\"comptrollerAddress\":\"Address of the comptroller\"},\"returns\":{\"_0\":\"badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and a break down of bad debt by market\"}},\"getPoolByComptroller(address,address)\":{\"params\":{\"comptroller\":\"The Comptroller implementation address\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"PoolData structure containing the details of the pool\"}},\"getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))\":{\"params\":{\"poolRegistryAddress\":\"Address of the PoolRegistry\",\"venusPool\":\"The VenusPool Object from PoolRegistry\"},\"returns\":{\"_0\":\"Enriched PoolData\"}},\"getPoolsSupportedByAsset(address,address)\":{\"params\":{\"asset\":\"The underlying asset of vToken\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"A list of Comptroller contracts\"}},\"getVTokenForAsset(address,address,address)\":{\"params\":{\"asset\":\"The underlyingAsset of VToken\",\"comptroller\":\"The pool comptroller\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"Address of the vToken\"}},\"vTokenBalances(address,address)\":{\"params\":{\"account\":\"The user Account\",\"vToken\":\"vToken address\"},\"returns\":{\"_0\":\"A struct containing the balances data\"}},\"vTokenBalancesAll(address[],address)\":{\"params\":{\"account\":\"The user Account\",\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"A list of structs containing balances data\"}},\"vTokenMetadata(address)\":{\"params\":{\"vToken\":\"The address of vToken\"},\"returns\":{\"_0\":\"VTokenMetadata struct\"}},\"vTokenMetadataAll(address[])\":{\"params\":{\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"An array of VTokenMetadata structs\"}},\"vTokenUnderlyingPrice(address)\":{\"params\":{\"vToken\":\"vToken address\"},\"returns\":{\"_0\":\"The price data for each asset\"}},\"vTokenUnderlyingPriceAll(address[])\":{\"params\":{\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"An array containing the price data for each asset\"}}},\"title\":\"PoolLens\",\"version\":1},\"userdoc\":{\"errors\":{\"InvalidBlocksPerYear()\":[{\"notice\":\"Thrown when blocks per year is invalid\"}],\"InvalidTimeBasedConfiguration()\":[{\"notice\":\"Thrown when time based but blocks per year is provided\"}]},\"kind\":\"user\",\"methods\":{\"blocksOrSecondsPerYear()\":{\"notice\":\"Stores blocksPerYear if isTimeBased is true else secondsPerYear is stored\"},\"getAllPools(address)\":{\"notice\":\"Queries all pools with addtional details for each of them\"},\"getPendingRewards(address,address)\":{\"notice\":\"Returns the pending rewards for a user for a given pool.\"},\"getPoolBadDebt(address)\":{\"notice\":\"Returns a summary of a pool's bad debt broken down by market\"},\"getPoolByComptroller(address,address)\":{\"notice\":\"Queries the details of a pool identified by Comptroller address\"},\"getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))\":{\"notice\":\"Queries additional information for the pool\"},\"getPoolsSupportedByAsset(address,address)\":{\"notice\":\"Returns all pools that support the specified underlying asset\"},\"getVTokenForAsset(address,address,address)\":{\"notice\":\"Returns vToken holding the specified underlying asset in the specified pool\"},\"isTimeBased()\":{\"notice\":\"Acknowledges if a contract is time based or not\"},\"vTokenBalances(address,address)\":{\"notice\":\"Queries the user's supply/borrow balances in the specified vToken\"},\"vTokenBalancesAll(address[],address)\":{\"notice\":\"Queries the user's supply/borrow balances in vTokens\"},\"vTokenMetadata(address)\":{\"notice\":\"Returns the metadata of VToken\"},\"vTokenMetadataAll(address[])\":{\"notice\":\"Returns the metadata of all VTokens\"},\"vTokenUnderlyingPrice(address)\":{\"notice\":\"Returns the price data for the underlying asset of the specified vToken\"},\"vTokenUnderlyingPriceAll(address[])\":{\"notice\":\"Returns the price data for the underlying assets of the specified vTokens\"}},\"notice\":\"The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be looked up for specific pools and markets: - the vToken balance of a given user; - the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address; - the vToken address in a pool for a given asset; - a list of all pools that support an asset; - the underlying asset price of a vToken; - the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Lens/PoolLens.sol\":\"PoolLens\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"details\":{\"constantOptimizer\":false,\"cse\":false,\"deduplicate\":false,\"inliner\":false,\"jumpdestRemover\":false,\"orderLiterals\":false,\"peephole\":false,\"simpleCounterForLoopUncheckedIncrement\":true,\"yul\":true,\"yulDetails\":{\"optimizerSteps\":\"dhfoDgvulfnTUtnIf[xa[r]EscLMcCTUtTOntnfDIulLculVcul [j]Tpeulxa[rul]xa[r]cLgvifCTUca[r]LSsTFOtfDnca[r]Iulc]jmul[jul] VcTOcul jmul:fDnTOcmu\",\"stackAllocation\":true}},\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\":{\"keccak256\":\"0x9140dabc466abab21b48b72dbda26736b1183a310d0e677d3719d201df026510\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://75267b14b60dc216d01d596a4008189a6c44d3314e53eded0edb1e757d95be16\",\"dweb:/ipfs/QmQoMaxTRT6V7uQj9USfdQH9jh1crywB9auVjThzUSAbG2\"]},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"keccak256\":\"0x359a1ab89b46b9aba7bcad3fb651924baf4893d15153049b9976b0fc9be1358e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e89863421b4014b96a4b62be76eb3b9f0a8afe9684664a6f389124c0964bfe5c\",\"dweb:/ipfs/Qmbk7xr1irpDuU1WdxXgxELBXxs61rHhCgod7heVcvFx16\"]},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f103ee2e4aecd37aac6ceefe670709cdd7613dee25fa2d4d9feaf7fc0aaa155e\",\"dweb:/ipfs/QmRiNZLoJk5k3HPMYGPGjZFd2ke1ZxjhJZkM45Ec9GH9hv\"]},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c25f742ff154998d19a669e2508c3597b363e123ce9144cd0fcf6521229f401f\",\"dweb:/ipfs/QmQXRuFzStEWqeEPbhQU6cAg9PaSowxJVo4PDKyRod7dco\"]},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol\":{\"keccak256\":\"0x07e881de3b9f6d2c07909f193f24b96c7fe4ea60013260f3f25aecd8bab3c2f8\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://1fed09b97ccb0ff9ba9b6a94224f1d489026bf6b4b7279bfe64fb6e8749dee4d\",\"dweb:/ipfs/QmcRAzaSP1UnGr4vrGkfJmB2L9aiTYoXfV1Lg9gqrVRWn8\"]},\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\":{\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d03ebe5406134f0c4a017dee625ff615031194493bd1e88504e5c8fae55bc166\",\"dweb:/ipfs/QmUZV5bMbgk2PAkV3coouSeSainHN2jhqaQDJaA7hQRyu2\"]},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://310136ad60820af4177a11a61d77a3686faf5fca4942b600e08fc940db38396b\",\"dweb:/ipfs/QmbCzMNSTL7Zi7M4UCSqBrkHtp4jjxUnGbkneCZKdR1qeq\"]},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x75097e35253e7fb282ee4d7f27a80eaacfa759923185bf17302a89cbc059c5ef\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8b06267c5f80bad727af3e48b1382333d591dad51376399ef2f6b0ee6d58bf95\",\"dweb:/ipfs/QmdU5La1agcQvghnfMpWZGDPz2TUDTCxUwTLKmuMRXBpAx\"]},\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://bb2c137c343ef0c4c7ce7b18c1d108afdc9d315a04e48307288d2d05adcbde3a\",\"dweb:/ipfs/QmUxhrAQM3MM3FF5j7AtcXLXguWCJBHJ14BRdVtuoQc8Fh\"]},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://bd39944e8fc06be6dbe2dd1d8449b5336e23c6a7ba3e8e9ae5ae0f37f35283f5\",\"dweb:/ipfs/QmPV3FGYjVwvKSgAXKUN3r9T9GwniZz83CxBpM7vyj2G53\"]},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5a376d3dda2cb70536c0a45c208b29b34ac560c4cb4f513a42079f96ba47d2dd\",\"dweb:/ipfs/QmZQg6gn1sUpM8wHzwNvSnihumUCAhxD119MpXeKp8B9s8\"]},\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\":{\"keccak256\":\"0x0dcf283925f4dddc23ca0ee71d2cb96a9dd6e4cf08061b69fde1697ea39dc514\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://38db65a77297d8df3345797277a624d81706bde2e9ede230a140e8ca2a027040\",\"dweb:/ipfs/QmWKcmtyyvi3dhAJHkdAKGNrsKcMxKQ6c82ArtDqe8tncG\"]},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://8120bda3990193388d0cc5f551510ef1eab685387a58a88ab607b5149e51acde\",\"dweb:/ipfs/QmNSX9ai6GbN4wQukM29rFkcWDFhqStUTtKe6XtreTvRcN\"]},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"keccak256\":\"0x2432799b0d824fc701beb4c30146e912b9aeecf77b5c1635dde6c5fbe6bfc3a7\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://a0de4c46c1bb912ebf9eed630e210d17e2952b8076fcfd429672c7e6271ed665\",\"dweb:/ipfs/QmVuqSWTJSxpudZSJMpRC7pmw9iEjyZnnhm3n9RvmKXxTg\"]},\"@venusprotocol/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\":{\"keccak256\":\"0x5fddc5b63fdd850b3b5c83576cda50dcb27a205dbb1a23af17d9da0d9f04fa0a\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://8767ae7b2dd0ecd7a80ae3d083329a473949bd380535331acd6603ed56d60f00\",\"dweb:/ipfs/QmUyrJ9a1qjUHAxykwuDctAZxkDbvLMb5yGks8mUArCzj8\"]},\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\":{\"keccak256\":\"0x57a2bbb9b8e02b1c0a5c0e305fef1328a22db56c3d4b148c362010a6e767243c\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://01c6af010cbff93563f2175d48702f5d901beb59b0e3315ed2a5583dfa53ee21\",\"dweb:/ipfs/QmY7sfvoQ1kEQtLhPdSA3bQdV4u3hT563RSvuCtgSrQUmx\"]},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://6134b92b2bc5bad1c6e088d0d092736eede6dfe2cf7dadc573f1396a9d690274\",\"dweb:/ipfs/QmXwKV4SY7CdCaCaDqXudcLxVLB4vUfbwMiH9kH6HhWpiy\"]},\"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\":{\"keccak256\":\"0xd112f60183416ad796093b4a83a80ddc1b8b655965f02ae55ca82e2a0c68f97d\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://95b5d2eee4e994e248c66b95c1c23954e6aa81cce147b68705d0e9657de3871d\",\"dweb:/ipfs/Qmdf8sMZCm8f2j3rh2Jx7xzxqt1T5gyLKfMEeG6KtV4Fo7\"]},\"@venusprotocol/venus-protocol/contracts/Tokens/Prime/PrimeStorage.sol\":{\"keccak256\":\"0x5285c875114db2ea2be0b81b65722d5761806217022db733323c4e03365a95e7\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://f7381f89c82fcbacdb5f8d66dd944d09e102c23ad243d96cb46b480621bfb62c\",\"dweb:/ipfs/QmNgyd8zgXHB6akfj78MUrgLDvzjKn8d8u3KE3fhb2pPJh\"]},\"contracts/Comptroller.sol\":{\"keccak256\":\"0x7c6e1c6264e4681f82a9ac1bcd9155197a930033291ee5561ad97a56006f5e9c\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://9af5eb4fa4348f4bee0b0b4083c2eaf67dc6d05219882b298d82830316c6d40d\",\"dweb:/ipfs/QmR3iGJiWxQQSw8LQNVTMx4HNNixRsgVya2xCThE5FUv8T\"]},\"contracts/ComptrollerInterface.sol\":{\"keccak256\":\"0xcbf7f9977472650c61345b7cbde23e81f626e1f8863bab4c6ce3dacfc7604919\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://79472ca5fcc29e5a41f1209fb33701c45852141d231ff7ac584b2ece3bda76c4\",\"dweb:/ipfs/QmUB8e8obVXN898oCMwFjeP1SFmrpu99iSwjmtPUZXCkXm\"]},\"contracts/ComptrollerStorage.sol\":{\"keccak256\":\"0x4df44cb65ac152bac2be4b4545430e703005a74a55b72e144100b16421bd8bfd\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://a7b1f84e68406b41cadf240e111887ab79787fa385b87040c87d6cf25ff586ed\",\"dweb:/ipfs/QmV8JQog8CCz4HuiicsRShHfk4hfFKxUayT1NgpFvDRTdq\"]},\"contracts/ErrorReporter.sol\":{\"keccak256\":\"0x7a7ced1caaac2d9242659ebd50b99f308c725ce958ac9e11f7ada404b1d97a7b\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://6bc5b36130029c245d9c2c6e4e6e3a6ad5596518e98764a2315f247e817e7c6b\",\"dweb:/ipfs/QmWMtrqThCk1wqPxgkK9mMaf8E3fuRUg51awuGL6KmxwrU\"]},\"contracts/ExponentialNoError.sol\":{\"keccak256\":\"0x8afbe8a24fe3539c124e718681ed3dcebd24c40dd53095786c0155998213b9b0\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://64d6fe74721ef3112ecc641d868fe51738e3687d782b750fac63f139c0335900\",\"dweb:/ipfs/Qme9R3YKdc9WeLMymU4bW544usyXJU3PXDMBmyE7x7riV9\"]},\"contracts/InterestRateModel.sol\":{\"keccak256\":\"0xc4fda1ab75ebe4b187b707c4f10c58780f343cf343c537f641dc75d3cd28ab51\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://8cf703e1c44ebd4977200275e7c8c480081f1f6f54bedb6b0a070af04a8c733d\",\"dweb:/ipfs/QmUNCCcYZxftVaf4SdqXUpjeeyNe9Kqr45dbNguBGY5X1h\"]},\"contracts/Lens/PoolLens.sol\":{\"keccak256\":\"0xab04eb777ddc89a994e38e10ef0e776d165f1b7d98a4cf7715464366f931007a\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://9f498ab6c1ca91bd98dac8ff05d0dd7f6dbb485b210dba20c6308e721cfe98bf\",\"dweb:/ipfs/QmcDiKStyGEK2bDPEGvhokGkqs3pA4zoF7NPuTDkNDBSvD\"]},\"contracts/MaxLoopsLimitHelper.sol\":{\"keccak256\":\"0x4c25e30635485d162177effa384eee51768b0141a567a0da16ff6ad673274166\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://5d71ed301eb76292bce7b3500482452c397b766507222d00f3982b65520d156b\",\"dweb:/ipfs/QmcF3yPyr6hWQUA6wfEi6Hq1TEUtbxFP9MAcYQy4D2tFHC\"]},\"contracts/Pool/PoolRegistry.sol\":{\"keccak256\":\"0xafbb871f7b4db3ef439d846baa5f18a136192f9b43ea695c81262a77b06c4b25\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://ad9687d6df53a56c06a356dab0767bb710cc6f755d07afd1bd483f7c69886c08\",\"dweb:/ipfs/QmT3xsjq3ECawDtDhKi9ExNp8rA9A2AG9Jadi3XkRM4wG5\"]},\"contracts/Pool/PoolRegistryInterface.sol\":{\"keccak256\":\"0x7b39cda3b372a686501ce3c2aad288c6af410148110318249d75d4516729c92c\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://9d89bb6ea125321384ac9cb4cd041f98023caef20c30cf5fe443c3bec74114e0\",\"dweb:/ipfs/QmXECpsCgfj7vEMst4DL8Xos7V7XTDaVpPVTYEC34C4vee\"]},\"contracts/Rewards/RewardsDistributor.sol\":{\"keccak256\":\"0x3cc824e59c923cfe25c4f1a875959b7e9410cde8e73cd405de13f301298c697f\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://3cc9eaf325724c1a4906b2f91c4bd9ccb44fd721226e1d375832238d586b956b\",\"dweb:/ipfs/QmfTcWw1S3XonT8mc27RzD9aSWCu7qD7nqM9yD5wraCYZe\"]},\"contracts/Rewards/RewardsDistributorStorage.sol\":{\"keccak256\":\"0x70e5015a78a2acf95277949c8b4796e10b9ac194130be006d5e5217e158070c0\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://e2bb293581e076a38032cf087a5982967a2ffdc8f444550b019a4e52214da3fe\",\"dweb:/ipfs/QmV5QWm6hitgFyTcTXWQb9PyquuGfnLuMZumR9i6RUFT5g\"]},\"contracts/VToken.sol\":{\"keccak256\":\"0xa220ca317fe69b920b86e43f054c43b5f891f12160fd312c9a21668f969ee056\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://fbe57272638e7c9bad144320cb990fedd0c2a260fa508ff7eaa5c90aaf27cf73\",\"dweb:/ipfs/QmYoHbayLhZPr2avFLevtwkq77ZuvTPsZMH8bYP2SzQhcN\"]},\"contracts/VTokenInterfaces.sol\":{\"keccak256\":\"0x7c4cbb879e3a931cfee4fa7a9eb1978eddff18087a1c4f56decedb84c2479f1e\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://4e35b7a99b9e1050cbee00642bcfcddf81ea585836872a2c933ebac3ec5b8e2c\",\"dweb:/ipfs/QmWhKGVv361V92XcQHogaC2h1C6cNTK9BmEWjspxAjtg2t\"]},\"contracts/lib/constants.sol\":{\"keccak256\":\"0x54ab3a6f3bc87569ed12370f3470a1ec84cea9796d4d0ccf3d07dd4280c044aa\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://be1b725f8bf381f0a0e14b5fc676fcd38fbcbda868f6ec0b5163cfa4cb25e548\",\"dweb:/ipfs/QmdDLtw2sVdVy8RhHWeoNVaEzQJhykgbHdPrGeFRKRcPgw\"]},\"contracts/lib/validators.sol\":{\"keccak256\":\"0x93bdd5cfb100f0f9a1d446857e23c3633df6ab12c266333c978428edd96b1367\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://4b3a06c0cc5166270e920a1b7a7a2126ac01ed1198ce695c483f7c6ce0791056\",\"dweb:/ipfs/QmcK9nwALKisL6WnrxdWjf38n2vds1tUvBgz4ii7Aj6ZHR\"]}},\"version\":1}", + "solc_zkvm_edition": "1.0.2", + "source_metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.d94a798c\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"timeBased_\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"blocksPerYear_\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"corePoolComptroller_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidBlocksPerYear\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTimeBasedConfiguration\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"blocksOrSecondsPerYear\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"corePoolComptroller\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"}],\"name\":\"getAllPools\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockNumberOrTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getPendingRewards\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"distributorAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"rewardTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalRewards\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.PendingReward[]\",\"name\":\"pendingRewards\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.RewardSummary[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getPoolBadDebt\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"totalBadDebtUsd\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"badDebtUsd\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.BadDebt[]\",\"name\":\"badDebts\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.BadDebtSummary\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolByComptroller\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolRegistryInterface.VenusPool\",\"name\":\"venusPool\",\"type\":\"tuple\"}],\"name\":\"getPoolDataFromVenusPool\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"creator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockPosted\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestampPosted\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"category\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"logoURL\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"description\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"priceOracle\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"closeFactor\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentive\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minLiquidatableCollateral\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"vTokens\",\"type\":\"tuple[]\"}],\"internalType\":\"struct PoolLens.PoolData\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getPoolsSupportedByAsset\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistryAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"getVTokenForAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isTimeBased\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"vTokenBalances\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalanceCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balanceOfUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenAllowance\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenBalances\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"vTokenBalancesAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"balanceOf\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowBalanceCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balanceOfUnderlying\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenAllowance\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenBalances[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"vTokenMetadata\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"vTokenMetadataAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRateCurrent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowRatePerBlockOrTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reserveFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowCaps\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalBorrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalReserves\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"totalCash\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pausedActions\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenMetadata[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"vTokenUnderlyingPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"underlyingPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenUnderlyingPrice\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"vTokenUnderlyingPriceAll\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"underlyingPrice\",\"type\":\"uint256\"}],\"internalType\":\"struct PoolLens.VTokenUnderlyingPrice[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"params\":{\"blocksPerYear_\":\"The number of blocks per year\",\"corePoolComptroller_\":\"The address of the core pool comptroller\",\"timeBased_\":\"A boolean indicating whether the contract is based on time or block.\"}},\"getAllPools(address)\":{\"details\":\"This function is not designed to be called in a transaction: it is too gas-intensive\",\"params\":{\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"Arrays of all Venus pools' data\"}},\"getBlockNumberOrTimestamp()\":{\"details\":\"Function to simply retrieve block number or block timestamp\",\"returns\":{\"_0\":\"Current block number or block timestamp\"}},\"getPendingRewards(address,address)\":{\"params\":{\"account\":\"The user account.\",\"comptrollerAddress\":\"address\"},\"returns\":{\"_0\":\"Pending rewards array\"}},\"getPoolBadDebt(address)\":{\"params\":{\"comptrollerAddress\":\"Address of the comptroller\"},\"returns\":{\"_0\":\"badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and a break down of bad debt by market\"}},\"getPoolByComptroller(address,address)\":{\"params\":{\"comptroller\":\"The Comptroller implementation address\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"PoolData structure containing the details of the pool\"}},\"getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))\":{\"params\":{\"poolRegistryAddress\":\"Address of the PoolRegistry\",\"venusPool\":\"The VenusPool Object from PoolRegistry\"},\"returns\":{\"_0\":\"Enriched PoolData\"}},\"getPoolsSupportedByAsset(address,address)\":{\"params\":{\"asset\":\"The underlying asset of vToken\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"A list of Comptroller contracts\"}},\"getVTokenForAsset(address,address,address)\":{\"params\":{\"asset\":\"The underlyingAsset of VToken\",\"comptroller\":\"The pool comptroller\",\"poolRegistryAddress\":\"The address of the PoolRegistry contract\"},\"returns\":{\"_0\":\"Address of the vToken\"}},\"vTokenBalances(address,address)\":{\"params\":{\"account\":\"The user Account\",\"vToken\":\"vToken address\"},\"returns\":{\"_0\":\"A struct containing the balances data\"}},\"vTokenBalancesAll(address[],address)\":{\"params\":{\"account\":\"The user Account\",\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"A list of structs containing balances data\"}},\"vTokenMetadata(address)\":{\"params\":{\"vToken\":\"The address of vToken\"},\"returns\":{\"_0\":\"VTokenMetadata struct\"}},\"vTokenMetadataAll(address[])\":{\"params\":{\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"An array of VTokenMetadata structs\"}},\"vTokenUnderlyingPrice(address)\":{\"params\":{\"vToken\":\"vToken address\"},\"returns\":{\"_0\":\"The price data for each asset\"}},\"vTokenUnderlyingPriceAll(address[])\":{\"params\":{\"vTokens\":\"The list of vToken addresses\"},\"returns\":{\"_0\":\"An array containing the price data for each asset\"}}},\"title\":\"PoolLens\",\"version\":1},\"userdoc\":{\"errors\":{\"InvalidBlocksPerYear()\":[{\"notice\":\"Thrown when blocks per year is invalid\"}],\"InvalidTimeBasedConfiguration()\":[{\"notice\":\"Thrown when time based but blocks per year is provided\"}]},\"kind\":\"user\",\"methods\":{\"blocksOrSecondsPerYear()\":{\"notice\":\"Stores blocksPerYear if isTimeBased is true else secondsPerYear is stored\"},\"corePoolComptroller()\":{\"notice\":\"Address of the core pool comptroller (all markets are returned for this pool, including paused ones)\"},\"getAllPools(address)\":{\"notice\":\"Queries all pools with addtional details for each of them\"},\"getPendingRewards(address,address)\":{\"notice\":\"Returns the pending rewards for a user for a given pool.\"},\"getPoolBadDebt(address)\":{\"notice\":\"Returns a summary of a pool's bad debt broken down by market\"},\"getPoolByComptroller(address,address)\":{\"notice\":\"Queries the details of a pool identified by Comptroller address\"},\"getPoolDataFromVenusPool(address,(string,address,address,uint256,uint256))\":{\"notice\":\"Queries additional information for the pool\"},\"getPoolsSupportedByAsset(address,address)\":{\"notice\":\"Returns all pools that support the specified underlying asset\"},\"getVTokenForAsset(address,address,address)\":{\"notice\":\"Returns vToken holding the specified underlying asset in the specified pool\"},\"isTimeBased()\":{\"notice\":\"Acknowledges if a contract is time based or not\"},\"vTokenBalances(address,address)\":{\"notice\":\"Queries the user's supply/borrow balances in the specified vToken\"},\"vTokenBalancesAll(address[],address)\":{\"notice\":\"Queries the user's supply/borrow balances in vTokens\"},\"vTokenMetadata(address)\":{\"notice\":\"Returns the metadata of VToken\"},\"vTokenMetadataAll(address[])\":{\"notice\":\"Returns the metadata of all VTokens\"},\"vTokenUnderlyingPrice(address)\":{\"notice\":\"Returns the price data for the underlying asset of the specified vToken\"},\"vTokenUnderlyingPriceAll(address[])\":{\"notice\":\"Returns the price data for the underlying assets of the specified vTokens\"}},\"notice\":\"The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be looked up for specific pools and markets: - the vToken balance of a given user; - the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address; - the vToken address in a pool for a given asset; - a list of all pools that support an asset; - the underlying asset price of a vToken; - the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Lens/PoolLens.sol\":\"PoolLens\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"details\":{\"constantOptimizer\":false,\"cse\":false,\"deduplicate\":false,\"inliner\":false,\"jumpdestRemover\":false,\"orderLiterals\":false,\"peephole\":false,\"simpleCounterForLoopUncheckedIncrement\":true,\"yul\":true,\"yulDetails\":{\"optimizerSteps\":\"dhfoDgvulfnTUtnIf[xa[r]EscLMcCTUtTOntnfDIulLculVcul [j]Tpeulxa[rul]xa[r]cLgvifCTUca[r]LSsTFOtfDnca[r]Iulc]jmul[jul] VcTOcul jmul:fDnTOcmu\",\"stackAllocation\":true}},\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\":{\"keccak256\":\"0x9140dabc466abab21b48b72dbda26736b1183a310d0e677d3719d201df026510\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://75267b14b60dc216d01d596a4008189a6c44d3314e53eded0edb1e757d95be16\",\"dweb:/ipfs/QmQoMaxTRT6V7uQj9USfdQH9jh1crywB9auVjThzUSAbG2\"]},\"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\":{\"keccak256\":\"0x359a1ab89b46b9aba7bcad3fb651924baf4893d15153049b9976b0fc9be1358e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e89863421b4014b96a4b62be76eb3b9f0a8afe9684664a6f389124c0964bfe5c\",\"dweb:/ipfs/Qmbk7xr1irpDuU1WdxXgxELBXxs61rHhCgod7heVcvFx16\"]},\"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\":{\"keccak256\":\"0x89be10e757d242e9b18d5a32c9fbe2019f6d63052bbe46397a430a1d60d7f794\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://f103ee2e4aecd37aac6ceefe670709cdd7613dee25fa2d4d9feaf7fc0aaa155e\",\"dweb:/ipfs/QmRiNZLoJk5k3HPMYGPGjZFd2ke1ZxjhJZkM45Ec9GH9hv\"]},\"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\":{\"keccak256\":\"0x0e1f0f5f62f67a881cd1a9597acbc0a5e4071f3c2c10449a183b922ae7272e3f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c25f742ff154998d19a669e2508c3597b363e123ce9144cd0fcf6521229f401f\",\"dweb:/ipfs/QmQXRuFzStEWqeEPbhQU6cAg9PaSowxJVo4PDKyRod7dco\"]},\"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol\":{\"keccak256\":\"0x07e881de3b9f6d2c07909f193f24b96c7fe4ea60013260f3f25aecd8bab3c2f8\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://1fed09b97ccb0ff9ba9b6a94224f1d489026bf6b4b7279bfe64fb6e8749dee4d\",\"dweb:/ipfs/QmcRAzaSP1UnGr4vrGkfJmB2L9aiTYoXfV1Lg9gqrVRWn8\"]},\"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\":{\"keccak256\":\"0x23b997be73d3dd46885262704f0f8cfc7273fdadfe303d37969a9561373972b5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://d03ebe5406134f0c4a017dee625ff615031194493bd1e88504e5c8fae55bc166\",\"dweb:/ipfs/QmUZV5bMbgk2PAkV3coouSeSainHN2jhqaQDJaA7hQRyu2\"]},\"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\":{\"keccak256\":\"0x9c80f545915582e63fe206c6ce27cbe85a86fc10b9cd2a0e8c9488fb7c2ee422\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://310136ad60820af4177a11a61d77a3686faf5fca4942b600e08fc940db38396b\",\"dweb:/ipfs/QmbCzMNSTL7Zi7M4UCSqBrkHtp4jjxUnGbkneCZKdR1qeq\"]},\"@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol\":{\"keccak256\":\"0x75097e35253e7fb282ee4d7f27a80eaacfa759923185bf17302a89cbc059c5ef\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8b06267c5f80bad727af3e48b1382333d591dad51376399ef2f6b0ee6d58bf95\",\"dweb:/ipfs/QmdU5La1agcQvghnfMpWZGDPz2TUDTCxUwTLKmuMRXBpAx\"]},\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://bb2c137c343ef0c4c7ce7b18c1d108afdc9d315a04e48307288d2d05adcbde3a\",\"dweb:/ipfs/QmUxhrAQM3MM3FF5j7AtcXLXguWCJBHJ14BRdVtuoQc8Fh\"]},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://bd39944e8fc06be6dbe2dd1d8449b5336e23c6a7ba3e8e9ae5ae0f37f35283f5\",\"dweb:/ipfs/QmPV3FGYjVwvKSgAXKUN3r9T9GwniZz83CxBpM7vyj2G53\"]},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5a376d3dda2cb70536c0a45c208b29b34ac560c4cb4f513a42079f96ba47d2dd\",\"dweb:/ipfs/QmZQg6gn1sUpM8wHzwNvSnihumUCAhxD119MpXeKp8B9s8\"]},\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\":{\"keccak256\":\"0xfe0fd441c84ac907cabc88db69ef04f6d7532d770c7e6a1dfe6e7d6305debb49\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://2d94a5944cd90dd9fb985a3fd225b7b2065745e9a381ada6065c25fb43989e3a\",\"dweb:/ipfs/Qmb3WJHLiqq37EWEDmz1pGVq5fSnr65qC7nCxPsL9rKT5s\"]},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://8120bda3990193388d0cc5f551510ef1eab685387a58a88ab607b5149e51acde\",\"dweb:/ipfs/QmNSX9ai6GbN4wQukM29rFkcWDFhqStUTtKe6XtreTvRcN\"]},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"keccak256\":\"0xd3bbb7c9eef19e8f467342df6034ef95399a00964646fb8c82b438968ae3a8c0\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://e056fb5f1ce0c2b81641553d1f6415088bc91e6a8ceef1007bb0e149a806a9ea\",\"dweb:/ipfs/QmXg7TxRAtm5Rn8ZnyiZVG4szWze7q8c8hMH5saDn5Fhxp\"]},\"@venusprotocol/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\":{\"keccak256\":\"0x0f341bbef8f12885d79b7acaad7aaf11b84809e8f6b059ef4efc011c8f6c39a5\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://0c0f5e6f1df481791b626baf01e4190ad720e3921f167bb86f62c9ac7a39f821\",\"dweb:/ipfs/QmbswkkXdHd2JQ7ppLJMWYNxjYuZRoeYsJH3yzz3UxsijG\"]},\"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\":{\"keccak256\":\"0x57a2bbb9b8e02b1c0a5c0e305fef1328a22db56c3d4b148c362010a6e767243c\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://01c6af010cbff93563f2175d48702f5d901beb59b0e3315ed2a5583dfa53ee21\",\"dweb:/ipfs/QmY7sfvoQ1kEQtLhPdSA3bQdV4u3hT563RSvuCtgSrQUmx\"]},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://6134b92b2bc5bad1c6e088d0d092736eede6dfe2cf7dadc573f1396a9d690274\",\"dweb:/ipfs/QmXwKV4SY7CdCaCaDqXudcLxVLB4vUfbwMiH9kH6HhWpiy\"]},\"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\":{\"keccak256\":\"0xd112f60183416ad796093b4a83a80ddc1b8b655965f02ae55ca82e2a0c68f97d\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://95b5d2eee4e994e248c66b95c1c23954e6aa81cce147b68705d0e9657de3871d\",\"dweb:/ipfs/Qmdf8sMZCm8f2j3rh2Jx7xzxqt1T5gyLKfMEeG6KtV4Fo7\"]},\"@venusprotocol/venus-protocol/contracts/Tokens/Prime/PrimeStorage.sol\":{\"keccak256\":\"0x5285c875114db2ea2be0b81b65722d5761806217022db733323c4e03365a95e7\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://f7381f89c82fcbacdb5f8d66dd944d09e102c23ad243d96cb46b480621bfb62c\",\"dweb:/ipfs/QmNgyd8zgXHB6akfj78MUrgLDvzjKn8d8u3KE3fhb2pPJh\"]},\"contracts/Comptroller.sol\":{\"keccak256\":\"0x7c6e1c6264e4681f82a9ac1bcd9155197a930033291ee5561ad97a56006f5e9c\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://9af5eb4fa4348f4bee0b0b4083c2eaf67dc6d05219882b298d82830316c6d40d\",\"dweb:/ipfs/QmR3iGJiWxQQSw8LQNVTMx4HNNixRsgVya2xCThE5FUv8T\"]},\"contracts/ComptrollerInterface.sol\":{\"keccak256\":\"0xcbf7f9977472650c61345b7cbde23e81f626e1f8863bab4c6ce3dacfc7604919\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://79472ca5fcc29e5a41f1209fb33701c45852141d231ff7ac584b2ece3bda76c4\",\"dweb:/ipfs/QmUB8e8obVXN898oCMwFjeP1SFmrpu99iSwjmtPUZXCkXm\"]},\"contracts/ComptrollerStorage.sol\":{\"keccak256\":\"0x4df44cb65ac152bac2be4b4545430e703005a74a55b72e144100b16421bd8bfd\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://a7b1f84e68406b41cadf240e111887ab79787fa385b87040c87d6cf25ff586ed\",\"dweb:/ipfs/QmV8JQog8CCz4HuiicsRShHfk4hfFKxUayT1NgpFvDRTdq\"]},\"contracts/ErrorReporter.sol\":{\"keccak256\":\"0x7a7ced1caaac2d9242659ebd50b99f308c725ce958ac9e11f7ada404b1d97a7b\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://6bc5b36130029c245d9c2c6e4e6e3a6ad5596518e98764a2315f247e817e7c6b\",\"dweb:/ipfs/QmWMtrqThCk1wqPxgkK9mMaf8E3fuRUg51awuGL6KmxwrU\"]},\"contracts/ExponentialNoError.sol\":{\"keccak256\":\"0x8afbe8a24fe3539c124e718681ed3dcebd24c40dd53095786c0155998213b9b0\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://64d6fe74721ef3112ecc641d868fe51738e3687d782b750fac63f139c0335900\",\"dweb:/ipfs/Qme9R3YKdc9WeLMymU4bW544usyXJU3PXDMBmyE7x7riV9\"]},\"contracts/InterestRateModel.sol\":{\"keccak256\":\"0xc4fda1ab75ebe4b187b707c4f10c58780f343cf343c537f641dc75d3cd28ab51\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://8cf703e1c44ebd4977200275e7c8c480081f1f6f54bedb6b0a070af04a8c733d\",\"dweb:/ipfs/QmUNCCcYZxftVaf4SdqXUpjeeyNe9Kqr45dbNguBGY5X1h\"]},\"contracts/Lens/PoolLens.sol\":{\"keccak256\":\"0xfe3f00ebb7f0b5c98ee03cf1cfa1a013a56984cf6879373c70a74b3d9d0db399\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://4b3e8ccd9ce9b0498f8f90d1b52ee3e279950ae7c0dd66fde4d272f8736f8130\",\"dweb:/ipfs/Qmb9hFyPimgAApgi6hhLvPNC3vD46sP1HMdTi59aJQwuiw\"]},\"contracts/MaxLoopsLimitHelper.sol\":{\"keccak256\":\"0x4c25e30635485d162177effa384eee51768b0141a567a0da16ff6ad673274166\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://5d71ed301eb76292bce7b3500482452c397b766507222d00f3982b65520d156b\",\"dweb:/ipfs/QmcF3yPyr6hWQUA6wfEi6Hq1TEUtbxFP9MAcYQy4D2tFHC\"]},\"contracts/Pool/PoolRegistry.sol\":{\"keccak256\":\"0xafbb871f7b4db3ef439d846baa5f18a136192f9b43ea695c81262a77b06c4b25\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://ad9687d6df53a56c06a356dab0767bb710cc6f755d07afd1bd483f7c69886c08\",\"dweb:/ipfs/QmT3xsjq3ECawDtDhKi9ExNp8rA9A2AG9Jadi3XkRM4wG5\"]},\"contracts/Pool/PoolRegistryInterface.sol\":{\"keccak256\":\"0x7b39cda3b372a686501ce3c2aad288c6af410148110318249d75d4516729c92c\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://9d89bb6ea125321384ac9cb4cd041f98023caef20c30cf5fe443c3bec74114e0\",\"dweb:/ipfs/QmXECpsCgfj7vEMst4DL8Xos7V7XTDaVpPVTYEC34C4vee\"]},\"contracts/Rewards/RewardsDistributor.sol\":{\"keccak256\":\"0x3cc824e59c923cfe25c4f1a875959b7e9410cde8e73cd405de13f301298c697f\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://3cc9eaf325724c1a4906b2f91c4bd9ccb44fd721226e1d375832238d586b956b\",\"dweb:/ipfs/QmfTcWw1S3XonT8mc27RzD9aSWCu7qD7nqM9yD5wraCYZe\"]},\"contracts/Rewards/RewardsDistributorStorage.sol\":{\"keccak256\":\"0x70e5015a78a2acf95277949c8b4796e10b9ac194130be006d5e5217e158070c0\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://e2bb293581e076a38032cf087a5982967a2ffdc8f444550b019a4e52214da3fe\",\"dweb:/ipfs/QmV5QWm6hitgFyTcTXWQb9PyquuGfnLuMZumR9i6RUFT5g\"]},\"contracts/VToken.sol\":{\"keccak256\":\"0x7267f5337062ad01a5011f7725a86cc2ad0351cca0aaceadc167341f168cdef2\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://52fdb9fd04664f5b0b90f620c0b2f72b2a7c311d7193249b2083bc7391117884\",\"dweb:/ipfs/QmSmCAobThKhHXHS7mEqfGH5egVH1nBfGG6XnwApjZzcpo\"]},\"contracts/VTokenInterfaces.sol\":{\"keccak256\":\"0x155684e9cb12cdd8be63d2314c9452b68ee44ff98a00e0d65cd1fd7d0bdd4391\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://75da0c617e6eaba09484668c4b14d90a1063e087cd7f1a86c0955e620453f19d\",\"dweb:/ipfs/QmVTfEz6Mdd8R7C3PSBp49enYtqSY36WJDManvzCLHvstr\"]},\"contracts/lib/constants.sol\":{\"keccak256\":\"0x54ab3a6f3bc87569ed12370f3470a1ec84cea9796d4d0ccf3d07dd4280c044aa\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://be1b725f8bf381f0a0e14b5fc676fcd38fbcbda868f6ec0b5163cfa4cb25e548\",\"dweb:/ipfs/QmdDLtw2sVdVy8RhHWeoNVaEzQJhykgbHdPrGeFRKRcPgw\"]},\"contracts/lib/validators.sol\":{\"keccak256\":\"0x93bdd5cfb100f0f9a1d446857e23c3633df6ab12c266333c978428edd96b1367\",\"license\":\"BSD-3-Clause\",\"urls\":[\"bzz-raw://4b3a06c0cc5166270e920a1b7a7a2126ac01ed1198ce695c483f7c6ce0791056\",\"dweb:/ipfs/QmcK9nwALKisL6WnrxdWjf38n2vds1tUvBgz4ii7Aj6ZHR\"]}},\"version\":1}", "zk_version": "1.5.3" }, - "bytecode": "0x0003000000000002002e000000000002000000000301034f0000000001030019000000600110027000000b8604100197000200000043035500010000000303550000000100200190000000510000c13d0000012009000039000000400090043f000000040040008c000006070000413d000000000543034f000000000203043b000000e00220027000000b8e0020009c0000007f0000213d00000b9a0020009c0000009a0000213d00000ba00020009c000000d90000213d00000ba30020009c000001650000613d00000ba40020009c000006070000c13d000000240040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000101043b00000ba70010009c000006070000213d0000002302100039000000000042004b000006070000813d0000000402100039000000000223034f000000000202043b001d00000002001d00000ba70020009c000006070000213d001c00240010003d0000001d0100002900000005021002100000001c01200029000000000041004b000006070000213d0000003f0120003900000ba80310019700000ba90030009c000005790000213d0000012001300039000000400010043f0000001d04000029000001200040043f000000000004004b000006470000c13d00000020020000390000000002210436000001200300043d00000000003204350000004002100039000000000003004b000002180000613d000001400400003900000000050000190000000046040434000000007606043400000baa0660019700000000066204360000000007070433000000000076043500000040022000390000000105500039000000000035004b000000460000413d000002180000013d0000000001000416000000000001004b000006070000c13d0000001f0140003900000b8701100197000000e001100039000000400010043f0000001f0240018f00000b8805400198000000e001500039000000620000613d000000e006000039000000000703034f000000007807043c0000000006860436000000000016004b0000005e0000c13d000000000002004b0000006f0000613d000000000353034f0000000302200210000000000501043300000000052501cf000000000525022f000000000303043b0000010002200089000000000323022f00000000022301cf000000000252019f0000000000210435000000400040008c000006070000413d000000e00100043d000000000001004b0000000002000039000000010200c039000000000021004b000006070000c13d000001000200043d000000000001004b000000f60000613d000000000002004b0000014c0000c13d00000b8b020000410000000103000039000001550000013d00000b8f0020009c000000bd0000213d00000b950020009c000000fb0000213d00000b980020009c000001ce0000613d00000b990020009c000006070000c13d000000240040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000101043b00000baa0010009c000006070000213d2e15248d0000040f000000400200043d002000000002001d2e1520db0000040f000000200100002900000b860010009c00000b8601008041000000400110021000000bb2011001c700002e160001042e00000b9b0020009c000001160000213d00000b9e0020009c000002210000613d00000b9f0020009c000006070000c13d000000640040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000201043b00000baa0020009c000006070000213d0000002401300370000000000101043b00000baa0010009c000006070000213d0000004403300370000000000303043b00000baa0030009c000006070000213d00000bdd04000041000001200040043f000001240010043f000001440030043f0000000001000414000000040020008c000005d80000c13d0000000003000031000000200030008c00000020040000390000000004034019000005fe0000013d00000b900020009c000001330000213d00000b930020009c000002490000613d00000b940020009c000006070000c13d000000440040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000201043b00000baa0020009c000006070000213d0000002401300370000000000301043b00000baa0030009c000006070000213d00000bab01000041000001200010043f000001240030043f0000000003000414000000040020008c000000000105034f000003820000c13d00000000030000310000038f0000013d00000ba10020009c0000025c0000613d00000ba20020009c000006070000c13d000000240040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000101043b002000000001001d00000baa0010009c000006070000213d0000018009000039000000400090043f000001200000043f000001400000043f0000006001000039000001600010043f00000bbc01000041000001800010043f00000000030004140000002002000029000000040020008c000000000105034f000003190000c13d0000000003000031000003260000013d000000000002004b000001540000c13d000000400100043d00000b89020000410000014e0000013d00000b960020009c0000026f0000613d00000b970020009c000006070000c13d000000440040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000101043b00000baa0010009c000006070000213d0000002402300370000000000202043b00000baa0020009c000006070000213d2e152b470000040f000000400200043d002000000002001d2e1520e10000040f000000200100002900000b860010009c00000b8601008041000000400110021000000bb0011001c700002e160001042e00000b9c0020009c000002820000613d00000b9d0020009c000006070000c13d000000440040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000101043b002000000001001d00000baa0010009c000006070000213d002a00200000002d0000002401300370000000000101043b001f00000001001d00000baa0010009c000006070000213d00000bbc01000041000001200010043f00000000030004140000001f02000029000000040020008c000000000105034f000003f30000c13d0000000003000031000003ff0000013d00000b910020009c000002920000613d00000b920020009c000006070000c13d0000000001000416000000000001004b000006070000c13d0000000001000412002200000001001d002100400000003d000080050100003900000044030000390000000004000415000000220440008a000000050440021000000ba5020000412e152ded0000040f2e152dd00000040f000000400200043d000000000012043500000b860020009c00000b8602008041000000400120021000000ba6011001c700002e160001042e000000400100043d00000b8c02000041000000000021043500000b860010009c00000b8601008041000000400110021000000b8a011001c700002e17000104300000000203000039000000a00010043f000000800020043f000000c00030043f0000014000000443000001600020044300000020020000390000018000200443000001a0001004430000004001000039000001c000100443000001e00030044300000100002004430000000301000039000001200010044300000b8d0100004100002e160001042e000000440040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000101043b00000baa0010009c000006070000213d0000002402300370000000000602043b00000ba70060009c000006070000213d000000000264004900000bad0020009c000006070000213d000000a40020008c000006070000413d000001c002000039000000400020043f0000000405600039000000000753034f000000000707043b00000ba70070009c000006070000213d00000000076700190000002306700039000000000046004b000006070000813d0000000408700039000000000683034f000000000606043b00000bfd0060009c000005790000813d0000001f0a60003900000bff0aa001970000003f0aa0003900000bff0aa0019700000bfe00a0009c000005790000213d000001c00aa000390000004000a0043f000001c00060043f00000000076700190000002407700039000000000047004b000006070000213d0000002004800039000000000743034f00000bff086001980000001f0960018f000001e004800039000001a00000613d000001e00a000039000000000b07034f00000000bc0b043c000000000aca043600000000004a004b0000019c0000c13d000000000009004b000001ad0000613d000000000787034f0000000308900210000000000904043300000000098901cf000000000989022f000000000707043b0000010008800089000000000787022f00000000078701cf000000000797019f0000000000740435000001e0046000390000000000040435000001200020043f0000002002500039000000000423034f000000000404043b00000baa0040009c000006070000213d000001400040043f0000002002200039000000000423034f000000000404043b00000baa0040009c000006070000213d000001600040043f0000002004200039000000000443034f000000000404043b000001800040043f0000004002200039000000000223034f000000000202043b000001a00020043f00000120020000392e1520f70000040f0000002002000039000000400300043d002000000003001d00000000022304362e15200c0000040f00000020020000290000000001210049000003110000013d000000440040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000101043b00000ba70010009c000006070000213d0000002302100039000000000042004b000006070000813d0000000402100039000000000223034f000000000202043b001900000002001d00000ba70020009c000006070000213d001800240010003d000000190100002900000005021002100000001801200029000000000041004b000006070000213d0000002401300370000000000301043b00000baa0030009c000006070000213d0000003f0120003900000ba80410019700000ba90040009c000005790000213d0000012001400039000000400010043f0000001905000029000001200050043f000000000005004b0000067a0000c13d00000020020000390000000002210436000001200300043d00000000003204350000004002100039000000000003004b000002180000613d0000012004000039000000000500001900000020044000390000000006040433000000008706043400000baa07700197000000000772043600000000080804330000000000870435000000400760003900000000070704330000004008200039000000000078043500000060076000390000000007070433000000600820003900000000007804350000008007600039000000000707043300000080082000390000000000780435000000a0066000390000000006060433000000a0072000390000000000670435000000c0022000390000000105500039000000000035004b000001fd0000413d000000000212004900000b860020009c00000b8602008041000000600220021000000b860010009c00000b86010080410000004001100210000000000112019f00002e160001042e000000440040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000101043b002000000001001d00000baa0010009c000006070000213d0000002401300370000000000201043b00000baa0020009c000006070000213d000002c009000039000000400090043f0000006001000039000001200010043f000001400000043f000001600000043f000001800000043f000001a00000043f000001c00010043f000001e00010043f000002000010043f000002200000043f000002400000043f000002600000043f000002800000043f000002a00010043f00000bdf01000041000002c00010043f000002c40020043f00000000030004140000002002000029000000040020008c000000000105034f000005520000c13d00000000030000310000055f0000013d0000000001000416000000000001004b000006070000c13d0000000001000412002400000001001d002300200000003d000080050100003900000044030000390000000004000415000000240440008a000000050440021000000ba5020000412e152ded0000040f000000000001004b0000000001000039000000010100c039000001200010043f00000baf0100004100002e160001042e0000000002000416000000000002004b000006070000c13d002e00200000003d000000240040008c000006070000413d0000000402300370000000000202043b00000baa0020009c000006070000213d002d00000002001d00000be803000041000001200030043f0000000003000414000000040020008c000000000105034f000004d50000c13d000000000a000031000004e10000013d000000240040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000101043b00000baa0010009c000006070000213d2e1525b60000040f000000400200043d002000000002001d2e151fc60000040f000000200100002900000b860010009c00000b8601008041000000400110021000000bb1011001c700002e160001042e0000000001000416000000000001004b000006070000c13d0000000001000412002c00000001001d002b00000000003d0000800501000039000000440300003900000000040004150000002c0440008a000000050440021000000ba5020000412e152ded0000040f000001200010043f00000baf0100004100002e160001042e000000240040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000101043b00000ba70010009c000006070000213d0000002302100039000000000042004b000006070000813d0000000402100039000000000223034f000000000502043b00000ba70050009c000005790000213d00000005025002100000003f0620003900000ba80660019700000ba90060009c000005790000213d0000012006600039000000400060043f000001200050043f00000024011000390000000002210019000000000042004b000006070000213d000000000005004b000002ba0000613d0000014004000039000000000513034f000000000505043b00000baa0050009c000006070000213d00000000045404360000002001100039000000000021004b000002b20000413d00000120010000392e152d610000040f0000002003000039000000400200043d0000000003320436000000000401043300000000004304350000004003200039000000000004004b000003100000613d000000000500001900000020011000390000000006010433000000008706043400000baa07700197000000000773043600000000080804330000000000870435000000400760003900000000070704330000004008300039000000000078043500000060076000390000000007070433000000600830003900000000007804350000008007600039000000000707043300000080083000390000000000780435000000a0076000390000000007070433000000a0083000390000000000780435000000c0076000390000000007070433000000c0083000390000000000780435000000e0076000390000000007070433000000e008300039000000000078043500000100076000390000000007070433000001000830003900000000007804350000012007600039000000000707043300000120083000390000000000780435000001400760003900000000070704330000014008300039000000000078043500000160076000390000000007070433000000000007004b0000000007000039000000010700c039000001600830003900000000007804350000018007600039000000000707043300000180083000390000000000780435000001a007600039000000000707043300000baa07700197000001a0083000390000000000780435000001c0076000390000000007070433000001c0083000390000000000780435000001e0076000390000000007070433000001e0083000390000000000780435000002000660003900000000060604330000020007300039000000000067043500000220033000390000000105500039000000000045004b000002c50000413d000000000123004900000b860010009c00000b8601008041000000600110021000000b860020009c00000b86020080410000004002200210000000000121019f00002e160001042e00000b860030009c00000b8603008041000000c00130021000000be3011001c72e152e100000040f0000000003010019000000600330027000000b860030019d00000b860330019700020000000103550000000100200190000004c90000613d000001800900003900000bff053001980000001f0630018f00000180045000390000032f0000613d000000000701034f000000007807043c0000000009890436000000000049004b0000032b0000c13d000000000006004b0000033c0000613d000000000151034f0000000305600210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000001f0130003900000bff01100197001e00000001001d00000be40010009c000005790000213d0000001e010000290000018001100039001f00000001001d000000400010043f00000bad0030009c000006070000213d000000200030008c000006070000413d000001800100043d00000ba70010009c000006070000213d00000180023000390000019f04100039000000000024004b000000000500001900000bae0500804100000bae0620019700000bae04400197000000000764013f000000000064004b000000000400001900000bae0400404100000bae0070009c000000000405c019000000000004004b000006070000c13d0000018004100039000000000504043300000ba70050009c000005790000213d00000005045002100000003f0640003900000ba8066001970000001f0660002900000ba70060009c000005790000213d000000400060043f0000001f060000290000000000560435000001a0011000390000000004140019000000000024004b000006070000213d000000000005004b000003760000613d0000001f02000029000000001501043400000baa0050009c000006070000213d00000020022000390000000000520435000000000041004b0000036f0000413d000000400200043d00000be501000041001d00000002001d000000000012043500000000010004140000002002000029000000040020008c000009470000c13d000000200030008c00000020040000390000000004034019000009730000013d00000b860030009c00000b8603008041000000c00130021000000bac011001c72e152e100000040f0000000003010019000000600330027000000b860030019d00000b860330019700020000000103550000000100200190000006090000613d000001200900003900000bff053001980000001f0630018f0000012004500039000003980000613d000000000701034f000000007807043c0000000009890436000000000049004b000003940000c13d000000000006004b000003a50000613d000000000151034f0000000305600210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000001f0130003900000bff0210019700000ba90020009c000005790000213d0000012001200039000000400010043f00000bad0030009c000006070000213d000000200030008c000006070000413d000001200400043d00000ba70040009c000006070000213d00000120033000390000013f05400039000000000035004b000000000600001900000bae0600804100000bae0730019700000bae05500197000000000875013f000000000075004b000000000500001900000bae0500404100000bae0080009c000000000506c019000000000005004b000006070000c13d0000012005400039000000000605043300000ba70060009c000005790000213d00000005056002100000003f0750003900000ba807700197000000000717001900000ba70070009c000005790000213d000000400070043f000000000061043500000140044000390000000005540019000000000035004b000006070000213d0000014002200039000000000006004b000003db0000613d0000000003020019000000004604043400000baa0060009c000006070000213d0000000003630436000000000054004b000003d50000413d000000400300043d00000020040000390000000005430436000000000401043300000000004504350000004001300039000000000004004b000003ea0000613d0000000005000019000000002602043400000baa0660019700000000016104360000000105500039000000000045004b000003e40000413d000000000131004900000b860010009c00000b8601008041000000600110021000000b860030009c00000b86030080410000004002300210000000000121019f00002e160001042e00000b860030009c00000b8603008041000000c00130021000000bbd011001c72e152e100000040f0000000003010019000000600330027000000b860030019d00000b860330019700020000000103550000000100200190000006150000613d00000bff043001980000001f0530018f0000012002400039000004090000613d0000012006000039000000000701034f000000007807043c0000000006860436000000000026004b000004050000c13d000000000005004b000004160000613d000000000641034f0000000304500210000000000502043300000000054501cf000000000545022f000000000606043b0000010004400089000000000646022f00000000044601cf000000000454019f0000000000420435000000000901034f0000001f0130003900000bff0210019700000ba90020009c000005790000213d0000012001200039001e00000001001d000000400010043f00000bad0030009c000006070000213d000000200030008c000006070000413d000001200400043d00000ba70040009c000006070000213d00000120053000390000013f01400039000000000051004b000000000600001900000bae0600804100000bae0750019700000bae01100197000000000871013f000000000071004b000000000100001900000bae0100404100000bae0080009c000000000106c019000000000001004b000006070000c13d0000012001400039000000000701043300000ba70070009c000005790000213d00000005067002100000003f0160003900000ba8011001970000001e0810002900000ba70080009c000005790000213d000000400080043f0000001e01000029000000000071043500000140044000390000000006460019000000000056004b000006070000213d000000000007004b0000044f0000613d0000001e05000029000000004704043400000baa0070009c000006070000213d00000020055000390000000000750435000000000064004b000004480000413d0029001e0000002d00000bbe01000041000000400400043d001d00000004001d000000000014043500000000040004140000001f01000029000000040010008c0000046d0000613d0000001d0100002900000b860010009c00000b8601008041000000400110021000000b860040009c00000b8604008041000000c002400210000000000112019f00000b8a011001c70000001f020000292e152e100000040f0000000003010019000000600330027000000b860030019d00000b8603300197000000000901034f0002000000010355000000010020019000000a3f0000613d0000001f0130003900000b870210019700000bff053001980000001f0630018f0000001d04500029000004770000613d000000000709034f0000001d08000029000000007107043c0000000008180436000000000048004b000004730000c13d000000000006004b000004840000613d000000000159034f0000000305600210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000001d04200029000000000024004b00000000010000390000000101004039001c00000004001d00000ba70040009c000005790000213d0000000100100190000005790000c13d0000001c01000029000000400010043f00000bad0030009c000006070000213d000000200030008c000006070000413d0000001d01000029000000000101043300000ba70010009c000006070000213d0000001d053000290000001d011000290000001f02100039000000000052004b000000000400001900000bae0400804100000bae0220019700000bae06500197000000000762013f000000000062004b000000000200001900000bae0200404100000bae0070009c000000000204c019000000000002004b000006070000c13d000000004201043400000ba70020009c000005790000213d00000005012002100000003f0610003900000ba8066001970000001c0760002900000ba70070009c000005790000213d000000400070043f0000001c0700002900000000002704350000000007140019000000000057004b000006070000213d000000000074004b000014df0000813d0000001c01000029000000004204043400000baa0020009c000006070000213d00000020011000390000000000210435000000000074004b000004b90000413d0000001c010000290000000002010433002800000001001d00000ba70020009c000005790000213d00000005012002100000003f0410003900000ba806400197000014e00000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000004d00000c13d000006630000013d00000b860030009c00000b8603008041000000c00130021000000bbd011001c72e152e100000040f0000000003010019000000600330027000000b860030019d00000b860a30019700020000000103550000000100200190000006210000613d00000bff04a001980000001f05a0018f0000012002400039000004eb0000613d0000012006000039000000000701034f000000007807043c0000000006860436000000000026004b000004e70000c13d000000000005004b000004f80000613d000000000441034f0000000305500210000000000602043300000000065601cf000000000656022f000000000404043b0000010005500089000000000454022f00000000045401cf000000000464019f0000000000420435001e000000010353001f0000000a001d0000001f02a0003900000bff0820019700000ba90080009c000005790000213d0000012001800039000700000001001d000000400010043f0000001f0100002900000bad0010009c000006070000213d0000001f01000029000000200010008c000006070000413d000001200600043d00000ba70060009c000006070000213d0000001f0100002900000120021000390000013f05600039000000000025004b000000000700001900000bae0700804100000bae0420019700000bae05500197000000000945013f000000000045004b000000000500001900000bae0500404100000bae0090009c000000000507c019000000000005004b000006070000c13d0000012001600039000000000901043300000ba70090009c000005790000213d00000005079002100000003f0a70003900000ba80aa00197000000070aa0002900000ba700a0009c000005790000213d0000004000a0043f0000000703000029000000000093043500000140066000390000000007670019000000000027004b000006070000213d000101400080003d000000000009004b000200000000001d000009e50000c13d000000020100002900000005021002100000003f0420003900000be905400197000000400100043d002000000001001d0000000004150019000000000054004b0000000005000039000000010500403900000ba70040009c000005790000213d0000000100500190000005790000c13d000000400040043f000000200100002900000002030000290000000001310436001b00000001001d000000000003004b00000a720000c13d0000002002000039000000400100043d00000000002104350000000004210019000000200300002900000000030304330000000000340435000000400410003900000005053002100000000005450019000000000003004b000012da0000c13d0000000002150049000002190000013d00000b860030009c00000b8603008041000000c00130021000000be0011001c72e152e100000040f0000000003010019000000600330027000000b860030019d00000b8603300197000200000001035500000001002001900000063b0000613d000002c00900003900000bff043001980000001f0630018f000002c002400039000005680000613d000000000701034f000000007807043c0000000009890436000000000029004b000005640000c13d000000000006004b000005750000613d000000000141034f0000000304600210000000000602043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f00000000001204350000001f0130003900000bff0110019700000be10010009c0000057f0000a13d00000bdc01000041000000000010043f0000004101000039000000040010043f00000bb60100004100002e1700010430000002c002100039000000400020043f00000bad0030009c000006070000213d000000200030008c000006070000413d000002c00400043d00000ba70040009c000006070000213d000002c006300039000002c007400039000000000376004900000bad0030009c000006070000213d000000a00030008c000006070000413d00000be20020009c000005790000213d0000036003100039000000400030043f000000000807043300000ba70080009c000006070000213d00000000077800190000001f08700039000000000068004b000000000900001900000bae0900804100000bae0880019700000bae0a600197000000000ba8013f0000000000a8004b000000000800001900000bae0800404100000bae00b0009c000000000809c019000000000008004b000006070000c13d000000008707043400000ba70070009c000005790000213d0000001f0970003900000bff099001970000003f0990003900000bff05900197000000000535001900000ba70050009c000005790000213d000000400050043f00000000007304350000000005870019000000000065004b000006070000213d0000038005100039000000000007004b000005bf0000613d00000000060000190000000009560019000000000a860019000000000a0a04330000000000a904350000002006600039000000000076004b000005b80000413d000000000557001900000000000504350000000000320435000002e003400039000000000303043300000baa0030009c000006070000213d000002e00510003900000000003504350000030003400039000000000303043300000baa0030009c000006070000213d00000300051000390000000000350435000003200340003900000000030304330000032005100039000000000035043500000340011000390000034003400039000000000303043300000000003104350000002001000029000001c50000013d00000b860010009c00000b8601008041000000c00110021000000bde011001c72e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000012005700039000005ed0000613d0000012008000039000000000901034f000000009a09043c0000000008a80436000000000058004b000005e90000c13d000000000006004b000005fa0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000006580000613d0000001f01400039000000600110018f0000012001100039000000400010043f000000200030008c000006070000413d000001200200043d00000baa0020009c000006760000a13d000000000100001900002e17000104300000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000006100000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000061c0000c13d000006630000013d0000001f05a0018f00000b8806a00198000000400200043d00000000046200190000062c0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000006280000c13d000000000005004b000006390000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000006001a00210000006710000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000006420000c13d000006630000013d00000bfc0030009c000005790000213d00000000030000190000004004100039000000400040043f000000200410003900000000000404350000000000010435000001400430003900000000001404350000002003300039000000000023004b000006930000813d000000400100043d00000bc20010009c0000064a0000a13d000005790000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000065f0000c13d000000000005004b000006700000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000b860020009c00000b86020080410000004002200210000000000112019f00002e17000104300000000000210435000000400110021000000ba6011001c700002e160001042e00000bb30040009c000005790000213d0000000004000019000000c005100039000000400050043f000000a0051000390000000000050435000000800510003900000000000504350000006005100039000000000005043500000040051000390000000000050435000000200510003900000000000504350000000000010435000001400540003900000000001504350000002004400039000000000024004b0000077e0000813d000000400100043d00000bb40010009c0000067d0000a13d000005790000013d0000000003000019001f00000003001d0000000502300210001e00000002001d0000001c012000290000000101100367000000000501043b00000baa0050009c000006070000213d000000400100043d00000bc20010009c000005790000213d0000004002100039000000400020043f000000200210003900000000000204350000000000010435000000400b00043d00000bed0100004100000000001b04350000000001000414000000040050008c002000000005001d000006b00000c13d0000000003000031000000200030008c00000020040000390000000004034019000006de0000013d00000b8600b0009c00000b860200004100000000020b4019000000400220021000000b860010009c00000b8601008041000000c001100210000000000121019f00000b8a011001c70000000002050019001b0000000b001d2e152e100000040f0000001b0b0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056b0019000006cc0000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b000006c80000c13d0000001f07400190000006d90000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000000a4e0000613d00000020050000290000001f01400039000000600110018f000000000ab1001900000000001a004b0000000002000039000000010200403900000ba700a0009c000005790000213d0000000100200190000005790000c13d0000004000a0043f000000200030008c000006070000413d00000000020b043300000baa0020009c000006070000213d00000be50400004100000000004a04350000000004000414000000040020008c000007220000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c7001b0000000a001d2e152e100000040f0000001b0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000070e0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b0000070a0000c13d0000001f074001900000071b0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000000a5a0000613d0000001f01400039000000600110018f0000002005000029000000000ba1001900000ba700b0009c000005790000213d0000004000b0043f000000200030008c000006070000413d00000000020a043300000baa0020009c000006070000213d00000be70400004100000000004b04350000000404b0003900000000005404350000000004000414000000040020008c000007610000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000bb6011001c7001b0000000b001d2e152e100000040f0000001b0b0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056b00190000074d0000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b000007490000c13d0000001f074001900000075a0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000000a660000613d0000001f01400039000000600110018f00000020050000290000000001b1001900000ba70010009c000005790000213d000000400010043f000000200030008c000006070000413d00000bc20010009c000005790000213d00000000020b04330000004003100039000000400030043f000000200310003900000000002304350000000000510435000001200200043d0000001f03000029000000000032004b00001d6c0000a13d0000001e0200002900000140022000390000000000120435000001200100043d000000000031004b00001d6c0000a13d00000001033000390000001d0030006c000006940000413d000000400100043d0000003d0000013d00200baa0030019b0000000003000019001e00000003001d0000000502300210001d00000002001d00000018012000290000000101100367000000000501043b00000baa0050009c000006070000213d000000400100043d00000bb40010009c000005790000213d000000c002100039000000400020043f000000a0021000390000000000020435000000800210003900000000000204350000006002100039000000000002043500000040021000390000000000020435000000200210003900000000000204350000000000010435000000400b00043d00000bb50100004100000000001b04350000000401b00039000000200200002900000000002104350000000001000414000000040050008c001f00000005001d000007a70000c13d0000000003000031000000200030008c00000020040000390000000004034019000007d50000013d00000b8600b0009c00000b860200004100000000020b4019000000400220021000000b860010009c00000b8601008041000000c001100210000000000121019f00000bb6011001c70000000002050019001c0000000b001d2e152e100000040f0000001c0b0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056b0019000007c30000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b000007bf0000c13d0000001f07400190000007d00000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000013b50000613d0000001f050000290000001f01400039000000600110018f000000000ab1001900000000001a004b0000000002000039000000010200403900000ba700a0009c000005790000213d0000000100200190000005790000c13d0000004000a0043f000000200030008c000006070000413d00000000020b0433001c00000002001d00000bb70200004100000000002a04350000000402a00039000000200400002900000000004204350000000002000414000000040050008c0000081c0000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bb6011001c70000000002050019001b0000000a001d2e152e0b0000040f0000001b0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000008080000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000008040000c13d0000001f07400190000008150000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000013c10000613d0000001f01400039000000600110018f0000001f05000029000000000ba1001900000ba700b0009c000005790000213d0000004000b0043f000000200030008c000006070000413d00000000020a0433001b00000002001d00000bb80200004100000000002b04350000000402b00039000000200400002900000000004204350000000002000414000000040050008c0000085c0000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bb6011001c70000000002050019001a0000000b001d2e152e0b0000040f0000001a0b0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056b0019000008480000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b000008440000c13d0000001f07400190000008550000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000013cd0000613d0000001f01400039000000600110018f0000001f05000029000000000ab1001900000ba700a0009c000005790000213d0000004000a0043f000000200030008c000006070000413d00000000020b0433001a00000002001d00000bb90200004100000000002a04350000000002000414000000040050008c000008990000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c7000000000205001900170000000a001d2e152e100000040f000000170a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000008850000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000008810000c13d0000001f07400190000008920000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000013d90000613d0000001f01400039000000600110018f0000001f05000029000000000ba1001900000ba700b0009c000005790000213d0000004000b0043f000000200030008c000006070000413d00000000060a043300000baa0060009c000006070000213d00000bb50200004100000000002b04350000000402b00039000000200400002900000000004204350000000002000414000000040060008c000008dc0000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bb6011001c7001600000006001d000000000206001900170000000b001d2e152e100000040f000000170b0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056b0019000008c70000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b000008c30000c13d0000001f07400190000008d40000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000013e50000613d0000001f01400039000000600110018f0000001f050000290000001606000029000000000ab1001900000ba700a0009c000005790000213d0000004000a0043f000000200030008c000006070000413d00000000070b04330000002402a00039000000000052043500000bba0200004100000000002a04350000000402a00039000000200400002900000000004204350000000002000414000000040060008c0000091f0000613d001600000007001d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bbb011001c7000000000206001900170000000a001d2e152e100000040f000000170a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000090a0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000009060000c13d0000001f07400190000009170000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000013f10000613d0000001f01400039000000600110018f0000001f0500002900000016070000290000000001a1001900000ba70010009c000005790000213d000000400010043f000000200030008c000006070000413d00000bb40010009c000005790000213d00000000020a0433000000c003100039000000400030043f000000a00310003900000000002304350000008002100039000000000072043500000060021000390000001a03000029000000000032043500000040021000390000001b03000029000000000032043500000020021000390000001c0300002900000000003204350000000000510435000001200200043d0000001e03000029000000000032004b00001d6c0000a13d0000001d0200002900000140022000390000000000120435000001200100043d000000000031004b00001d6c0000a13d0000000103300039000000190030006c000007800000413d000000400100043d000001f40000013d0000001d0200002900000b860020009c00000b8602008041000000400220021000000b860010009c00000b8601008041000000c001100210000000000121019f00000b8a011001c700000020020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000001d05700029000009620000613d000000000801034f0000001d09000029000000008a08043c0000000009a90436000000000059004b0000095e0000c13d000000000006004b0000096f0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000009d90000613d0000001f01400039000000600210018f0000001d01200029000000000021004b0000000002000039000000010200403900000ba70010009c000005790000213d0000000100200190000005790000c13d000000400010043f000000200030008c000006070000413d0000001d02000029000000000202043300000baa0020009c000006070000213d0000001f04000029000000000604043300000ba70060009c000005790000213d00000005046002100000003f0540003900000ba805500197000000000515001900000ba70050009c000005790000213d000000400050043f0000000005610436000000000006004b000009a00000613d0000000006000019000000400700043d00000bc20070009c000005790000213d0000004008700039000000400080043f000000200870003900000000000804350000000000070435000000000865001900000000007804350000002006600039000000000046004b000009930000413d000000400400043d001400000004001d00000bc30040009c000005790000213d00000014050000290000006004500039000000400040043f0000004004500039001700000004001d000000000014043500000020010000290000000001150436001300000001001d00000000000104350000001f010000290000000001010433000000000001004b001c00000000001d000013fd0000c13d00000013040000290000001c0100002900000000001404350000002002000039000000400100043d00000000022104360000001403000029000000000303043300000baa03300197000000000032043500000000020404330000004003100039000000000023043500000017020000290000000002020433000000600310003900000060040000390000000000430435000000800310003900000000040204330000000000430435000000a003100039000000000004004b000009d70000613d000000000500001900000020022000390000000006020433000000007606043400000baa0660019700000000066304360000000007070433000000000076043500000040033000390000000105500039000000000045004b000009cc0000413d0000000002130049000002190000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000009e00000c13d000006630000013d0000000108000029000000006906043400000ba70090009c000006070000213d0000000009190019000000200c900039000000000ac2004900000bad00a0009c000006070000213d000000a000a0008c000006070000413d000000400a00043d00000be200a0009c000005790000213d000000a00ba000390000004000b0043f000000000d0c043300000ba700d0009c000006070000213d000000000ccd00190000001f0dc0003900000000002d004b000000000e00001900000bae0e00804100000bae0dd00197000000000f4d013f00000000004d004b000000000d00001900000bae0d00404100000bae00f0009c000000000d0ec01900000000000d004b000006070000c13d00000000dc0c043400000ba700c0009c000005790000213d0000001f0ec0003900000bff0ee001970000003f0ee0003900000bff0ee00197000000000ebe001900000ba700e0009c000005790000213d0000004000e0043f0000000000cb0435000000000edc001900000000002e004b000006070000213d000000c00ea0003900000000000c004b00000a200000613d000000000f0000190000000003ef00190000000005df001900000000050504330000000000530435000000200ff000390000000000cf004b00000a190000413d0000000003ec00190000000000030435000000000bba04360000004003900039000000000c03043300000baa00c0009c000006070000213d0000000000cb04350000006003900039000000000b03043300000baa00b0009c000006070000213d0000004003a000390000000000b30435000000800390003900000000030304330000006005a000390000000000350435000000a00390003900000000030304330000008005a0003900000000003504350000000008a80436000000000076004b000009e60000413d00000007010000290000000001010433000200000001001d00000ba70010009c0000052f0000a13d000005790000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900000a4a0000613d000000000709034f0000000008020019000000007107043c0000000008180436000000000048004b00000a460000c13d000000000005004b000006700000613d000000000169034f000006660000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000a550000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000a610000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000a6d0000c13d000006630000013d000000600e00003900000000040000190000001b0d000029000000400500043d00000bea0050009c000005790000213d000001a001500039000000400010043f00000180015000390000000000e10435000000e0015000390000000000e10435000000c0015000390000000000e10435000000a0015000390000000000e104350000000001e504360000016003500039000000000003043500000140035000390000000000030435000001200350003900000000000304350000010003500039000000000003043500000080035000390000000000030435000000600350003900000000000304350000004003500039000000000003043500000000000104350000000001d4001900000000005104350000002004400039000000000024004b00000a750000413d000000000200001900000007010000290000000001010433000800000002001d000000000021004b00001d6c0000a13d000000400200043d00000bea0020009c000005790000213d0005002d0000002d00000008010000290000000503100210000300000003001d00000001013000290000000004010433000001a001200039000000400010043f00000180012000390000000000e10435000000e0012000390000000000e10435000000c0012000390000000000e10435000000a0012000390000000000e104350000000001e20436000001600320003900000000000304350000014003200039000000000003043500000120032000390000000000030435000001000320003900000000000304350000008003200039000000000003043500000060032000390000000000030435000000400220003900000000000204350000000000010435000400000004001d0000004001400039000600000001001d0000000001010433000000400900043d00000bbc020000410000000000290435000000000400041400000baa02100197000000040020008c00000ae10000613d00000b860090009c001d00000009001d00000b86010000410000000001094019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c72e152e100000040f0000000003010019000000600330027000000b860030019d001f0b860030019b001e0000000103530002000000010355000000010020019000001e510000613d0000001b0d000029000000600e0000390000001d090000290000001f0800002900000bff0480019800000000024900190000001e0300035f00000aec0000613d000000000503034f0000000006090019000000005105043c0000000006160436000000000026004b00000ae80000c13d0000001f0580019000000af90000613d000000000143034f0000000303500210000000000402043300000000043401cf000000000434022f000000000101043b0000010003300089000000000131022f00000000013101cf000000000141019f00000000001204350000001f0180003900000bff0110019700000000030900190000000002910019000000000012004b00000000010000390000000101004039000b00000002001d00000ba70020009c000005790000213d0000000100100190000005790000c13d0000000b01000029000000400010043f0000001f0100002900000bad0010009c000006070000213d0000001f01000029000000200010008c000006070000413d000000000103043300000ba70010009c000006070000213d00000000040300190000001f0340002900000000014100190000001f02100039000000000032004b000000000400001900000bae0400804100000bae0220019700000bae05300197000000000652013f000000000052004b000000000200001900000bae0200404100000bae0060009c000000000204c019000000000002004b000006070000c13d0000000021010434000a00000001001d00000ba70010009c000005790000213d0000000a0100002900000005011002100000003f0410003900000ba8054001970000000b0450002900000ba70040009c000005790000213d000000400040043f0000000b040000290000000a060000290000000004640436000900000004001d0000000004210019000000000034004b000006070000213d000000000042004b00000b470000813d0000000b01000029000000002302043400000baa0030009c000006070000213d00000020011000390000000000310435000000000042004b00000b370000413d0000000b010000290000000001010433000a00000001001d00000ba70010009c000005790000213d0000000a0100002900000005011002100000003f0210003900000ba805200197000000400300043d0000000002530019001800000003001d000000000032004b0000000003000039000000010300403900000ba70020009c000005790000213d0000000100300190000005790000c13d000000400020043f00000018020000290000000a030000290000000002320436001700000002001d000000000003004b000010770000613d0000000002000019000000400300043d00000beb0030009c000005790000213d0000022004300039000000400040043f00000200043000390000000000040435000001e0043000390000000000040435000001c0043000390000000000040435000001a00430003900000000000404350000018004300039000000000004043500000160043000390000000000040435000001400430003900000000000404350000012004300039000000000004043500000100043000390000000000040435000000e0043000390000000000040435000000c0043000390000000000040435000000a0043000390000000000040435000000800430003900000000000404350000006004300039000000000004043500000040043000390000000000040435000000200430003900000000000404350000000000030435000000170420002900000000003404350000002002200039000000000012004b00000b590000413d00000000030000190000000b010000290000000001010433000000000031004b00001d6c0000a13d001a00000003001d000000400100043d00000beb0010009c000005790000213d0000001a02000029000000050320021000000009023000290000000002020433001f0baa0020019b0000022002100039000000400020043f00000200021000390000000000020435000001e0021000390000000000020435000001c0021000390000000000020435000001a00210003900000000000204350000018002100039000000000002043500000160021000390000000000020435000001400210003900000000000204350000012002100039000000000002043500000100021000390000000000020435000000e0021000390000000000020435000000c0021000390000000000020435000000a002100039000000000002043500000080021000390000000000020435000000600210003900000000000204350000004002100039000000000002043500000020021000390000000000020435000000000001043500000baa01000041000001000010043f000000400a00043d00000bec0100004100000000001a0435000001000100043d0000001f0210017f0000000001000414000000040020008c001600000003001d00000bc50000c13d0000000003000031000000200030008c0000002004000039000000000403401900000bf30000013d00000b8600a0009c00000b860300004100000000030a4019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000b8a011001c7001e0000000a001d2e152e100000040f0000001e0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000be00000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000bdc0000c13d0000001f0740019000000bed0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001d900000613d0000001f01400039000000600110018f00000000050a00190000000004a10019000000000014004b00000000020000390000000102004039001e00000004001d00000ba70040009c000005790000213d0000000100200190000005790000c13d0000001e02000029000000400020043f000000200030008c000006070000413d0000000002050433001500000002001d00000bed020000410000001e0a00002900000000002a0435000001000200043d0000001f0220017f0000000004000414000000040020008c00000c3c0000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c72e152e100000040f0000001e0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000c270000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000c230000c13d0000001f0740019000000c340000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001d9c0000613d0000001f01400039000000600110018f0000000001a10019001d00000001001d00000ba70010009c000005790000213d0000001d01000029000000400010043f000000200030008c000006070000413d0000001e010000290000000001010433001e00000001001d00000baa0010009c000006070000213d00000bee010000410000001d0a00002900000000041a0436000001000100043d0000001f0110017f0000000402a000390000000000120435000001000100043d0000001e0210017f0000000001000414000000040020008c001900000004001d00000c5a0000c13d000000400030008c0000004004000039000000000403401900000c870000013d00000b8600a0009c00000b860300004100000000030a4019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000bb6011001c72e152e100000040f0000001d0a0000290000000003010019000000600330027000000b8603300197000000400030008c00000040040000390000000004034019000000600640019000000000056a001900000c740000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000c700000c13d0000001f0740019000000c810000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001da80000613d0000001f01400039000000e00110018f0000000001a10019001c00000001001d00000ba70010009c000005790000213d0000001c01000029000000400010043f000000400030008c000006070000413d0000001d010000290000000002010433000000000002004b0000000001000039000000010100c039001400000002001d000000000012004b000006070000c13d00000019010000290000000001010433001300000001001d00000bb9010000410000001c0a00002900000000001a0435000001000100043d0000001f0210017f0000000001000414000000040020008c000000200400003900000cd20000613d00000b8600a0009c00000b860300004100000000030a4019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000b8a011001c72e152e100000040f0000001c0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000cbf0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000cbb0000c13d0000001f0740019000000ccc0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001db40000613d0000001f01400039000000600110018f0000000002a10019001d00000002001d00000ba70020009c000005790000213d0000001d02000029000000400020043f000000200030008c000006070000413d0000001c020000290000000002020433001900000002001d00000baa0020009c000006070000213d00000bef020000410000001d0a00002900000000002a0435000001000200043d000000190220017f0000000004000414000000040020008c00000d180000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c72e152e100000040f0000001d0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000d030000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000cff0000c13d0000001f0740019000000d100000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001dc00000613d0000001f01400039000000600110018f000000000aa10019000000c00000043f00000ba700a0009c000005790000213d0000004000a0043f000000200030008c000006070000413d0000001d010000290000000001010433000000ff0010008c000006070000213d000000c00010043f000000e00000043f000000000500001900000bf00100004100000000001a04350000002401a00039000001000200043d00000000005104350000001f0120017f0000000402a000390000000000120435000001000100043d0000001e0210017f0000000001000414000000040020008c000000200400003900000d640000613d001c00000005001d00000b8600a0009c00000b860300004100000000030a4019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000bbb011001c7001d0000000a001d2e152e100000040f0000001d0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000d500000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000d4c0000c13d0000001f0740019000000d5d0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e000039000014d30000613d0000001c050000290000001f01400039000000600110018f000000000ba1001900000000001b004b0000000002000039000000010200403900000ba700b0009c000005790000213d0000000100200190000005790000c13d0000004000b0043f000000200030008c000006070000413d00000000020a0433000000000002004b0000000004000039000000010400c039000000000042004b000006070000c13d00000000025201cf000000e00400043d000000000224019f000000e00020043f0000000102500039000000ff0520018f000000080050008c000000000a0b001900000d260000a13d00000bf10200004100000000002b0435000001000200043d0000001f0220017f0000000004000414000000040020008c00000db70000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c7001d0000000b001d2e152e100000040f0000001d0b0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056b001900000da20000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b00000d9e0000c13d0000001f0740019000000daf0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001dcc0000613d0000001f01400039000000600110018f0000000002b10019001d00000002001d00000ba70020009c000005790000213d0000001d02000029000000400020043f000000200030008c000006070000413d00000000020b0433001200000002001d00000bf2020000410000001d0a00002900000000002a0435000001000200043d0000001f0220017f0000000004000414000000040020008c00000df80000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c72e152e100000040f0000001d0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000de30000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000ddf0000c13d0000001f0740019000000df00000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001dd80000613d0000001f01400039000000600110018f0000000002a10019001c00000002001d00000ba70020009c000005790000213d0000001c02000029000000400020043f000000200030008c000006070000413d0000001d020000290000000002020433001100000002001d00000bf3020000410000001c0a00002900000000002a0435000001000200043d0000001f0220017f0000000004000414000000040020008c00000e3a0000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c72e152e100000040f0000001c0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000e250000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000e210000c13d0000001f0740019000000e320000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001de40000613d0000001f01400039000000600110018f0000000002a10019001d00000002001d00000ba70020009c000005790000213d0000001d02000029000000400020043f000000200030008c000006070000413d0000001c020000290000000002020433001000000002001d00000bf4020000410000001d0a00002900000000002a0435000001000200043d0000001f0220017f0000000404a000390000000000240435000001000200043d0000001e0220017f0000000004000414000000040020008c00000e800000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000bb6011001c72e152e100000040f0000001d0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000e6b0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000e670000c13d0000001f0740019000000e780000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001df00000613d0000001f01400039000000600110018f0000000002a10019001c00000002001d00000ba70020009c000005790000213d0000001c02000029000000400020043f000000200030008c000006070000413d0000001d020000290000000002020433000f00000002001d00000bf5020000410000001c0a00002900000000002a0435000001000200043d0000001f0220017f0000000404a000390000000000240435000001000200043d0000001e0220017f0000000004000414000000040020008c00000ec60000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000bb6011001c72e152e100000040f0000001c0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000eb10000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000ead0000c13d0000001f0740019000000ebe0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001dfc0000613d0000001f01400039000000600110018f0000000002a10019001e00000002001d00000ba70020009c000005790000213d0000001e02000029000000400020043f000000200030008c000006070000413d0000001c020000290000000002020433001c00000002001d00000bd0020000410000001e0a00002900000000002a0435000001000200043d0000001f0220017f0000000004000414000000040020008c00000f080000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c72e152e100000040f0000001e0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000ef30000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000eef0000c13d0000001f0740019000000f000000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001e080000613d0000001f01400039000000600110018f0000000002a10019001d00000002001d00000ba70020009c000005790000213d0000001d02000029000000400020043f000000200030008c000006070000413d0000001e020000290000000002020433000e00000002001d00000bf6020000410000001d0a00002900000000002a0435000001000200043d0000001f0220017f0000000004000414000000040020008c00000f4a0000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c72e152e100000040f0000001d0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000f350000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000f310000c13d0000001f0740019000000f420000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001e140000613d0000001f01400039000000600110018f0000000002a10019001e00000002001d00000ba70020009c000005790000213d0000001e02000029000000400020043f000000200030008c000006070000413d0000001d020000290000000002020433000d00000002001d00000bd7020000410000001e0a00002900000000002a0435000001000200043d0000001f0220017f0000000004000414000000040020008c00000f8c0000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c72e152e100000040f0000001e0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000f770000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000f730000c13d0000001f0740019000000f840000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001e200000613d0000001f01400039000000600110018f0000000002a10019001d00000002001d00000ba70020009c000005790000213d0000001d02000029000000400020043f000000200030008c000006070000413d0000001e020000290000000002020433000c00000002001d00000bf7020000410000001d0a00002900000000002a0435000001000200043d0000001f0220017f0000000004000414000000040020008c00000fce0000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c72e152e100000040f0000001d0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000fb90000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000fb50000c13d0000001f0740019000000fc60000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001e2c0000613d0000001f01400039000000600110018f0000000002a10019001e00000002001d00000ba70020009c000005790000213d0000001e02000029000000400020043f000000200030008c000006070000413d0000001d020000290000000002020433001d00000002001d00000bef020000410000001e0a00002900000000002a0435000001000200043d0000001f0220017f0000000004000414000000040020008c000010100000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c72e152e100000040f0000001e0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000ffb0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000ff70000c13d0000001f07400190000010080000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001e380000613d0000001f01400039000000600110018f0000000001a10019000000800000043f00000ba70010009c000005790000213d000000400010043f000000200030008c000006070000413d0000001e020000290000000002020433000000ff0020008c000006070000213d000000800020043f000000a00010043f00000beb0010009c000005790000213d0000022002100039000000400020043f000001000200043d0000001f0220017f0000000000210435000000a00100043d000000200110003900000015020000290000000000210435000000a00100043d000000400110003900000012020000290000000000210435000000a00100043d000000600110003900000011020000290000000000210435000000a00100043d000000800110003900000010020000290000000000210435000000a00100043d000000a0011000390000000f020000290000000000210435000000a00100043d000000c0011000390000001c020000290000000000210435000000a00100043d000000e0011000390000000e020000290000000000210435000000a00100043d00000100011000390000000d020000290000000000210435000000a00100043d00000120011000390000000c020000290000000000210435000000a00100043d00000140011000390000001d020000290000000000210435000000a00100043d000001600110003900000014020000290000000000210435000000a00100043d000001800110003900000013020000290000000000210435000001000100043d000000190110017f000000a00200043d000001a0022000390000000000120435000000800100043d000000ff0110018f000000a00200043d000001c0022000390000000000120435000000c00100043d000000ff0110018f000000a00200043d000001e0022000390000000000120435000000a00100043d0000020001100039000000e00200043d0000000000210435000000180100002900000000010104330000001a03000029000000000031004b00001d6c0000a13d00000016020000290000001701200029000000a00200043d000000000021043500000018010000290000000001010433000000000031004b00001d6c0000a13d00000001033000390000000a0030006c00000b850000413d00000006010000290000000001010433000000400900043d00000bf802000041000000000029043500000baa01100197000000040290003900000000001204350000000001000414000000050200002900000baa02200197000000040020008c000010880000c13d00000002010003670000000008000031000000200700008a0000109e0000013d00000b860090009c001f00000009001d00000b86030000410000000003094019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000bb6011001c72e152e100000040f0000000003010019000000600330027000000b860030019d00000b86083001970002000000010355000000010020019000001e5e0000613d000000200700008a0000001b0d000029000000600e0000390000001f0900002900000000047801700000000002490019000010a70000613d000000000501034f0000000006090019000000005305043c0000000006360436000000000026004b000010a30000c13d0000001f05800190000010b40000613d000000000641034f0000000303500210000000000402043300000000043401cf000000000434022f000000000506043b0000010003300089000000000535022f00000000033501cf000000000343019f0000000000320435001e000000010353001f00000008001d0000001f01800039000000000171016f00000000030900190000000002910019000000000012004b0000000004000039000000010400403900000ba70020009c000005790000213d0000000100400190000005790000c13d000000400020043f0000001f0100002900000bad0010009c000006070000213d0000001f01000029000000200010008c000006070000413d000000000503043300000ba70050009c000006070000213d0000001f043000290000000005350019000000000654004900000bad0060009c000006070000213d000000600060008c000006070000413d00000bc30020009c000005790000213d0000006006200039000000400060043f000000008705043400000ba70070009c000006070000213d00000000095700190000001f01900039000000000041004b000000000300001900000bae0300804100000bae0110019700000bae07400197000000000a71013f000000000071004b000000000100001900000bae0100404100000bae00a0009c000000000103c019000000000001004b000006070000c13d00000000a909043400000ba70090009c000005790000213d0000001f0190003900000bff011001970000003f0110003900000bff01100197000000000b61001900000ba700b0009c000005790000213d0000004000b0043f00000000009604350000000001a90019000000000041004b000006070000213d000000800b200039000000000009004b000011020000613d000000000c0000190000000001bc00190000000003ac001900000000030304330000000000310435000000200cc0003900000000009c004b000010fb0000413d0000000001b9001900000000000104350000000006620436000000000808043300000ba70080009c000006070000213d00000000085800190000001f01800039000000000041004b000000000300001900000bae0300804100000bae01100197000000000971013f000000000071004b000000000100001900000bae0100404100000bae0090009c000000000103c019000000000001004b000006070000c13d000000009808043400000ba70080009c000005790000213d0000001f0180003900000bff011001970000003f0110003900000bff01100197000000400a00043d000000000b1a00190000000000ab004b000000000c000039000000010c00403900000ba700b0009c000005790000213d0000000100c00190000005790000c13d0000004000b0043f000000000b8a04360000000001980019000000000041004b000006070000213d000000000008004b000011350000613d000000000c0000190000000001bc001900000000039c001900000000030304330000000000310435000000200cc0003900000000008c004b0000112e0000413d00000000018b001900000000000104350000000000a604350000004001500039000000000801043300000ba70080009c000006070000213d00000000055800190000001f01500039000000000041004b000000000300001900000bae0300804100000bae01100197000000000871013f000000000071004b000000000100001900000bae0100404100000bae0080009c000000000103c019000000000001004b000006070000c13d000000007505043400000ba70050009c000005790000213d0000001f0150003900000bff011001970000003f0110003900000bff01100197000000400300043d0000000008130019001900000003001d000000000038004b0000000009000039000000010900403900000ba70080009c000005790000213d0000000100900190000005790000c13d000000400080043f000000190100002900000000085104360000000001750019000000000041004b000006070000213d000000000005004b0000116b0000613d000000000400001900000000018400190000000003740019000000000303043300000000003104350000002004400039000000000054004b000011640000413d000000000158001900000000000104350000004001200039000000190300002900000000003104350000000001020433001500000001001d0000000001060433001200000001001d000000040200002900000080012000390000000001010433001300000001001d00000060012000390000000001010433001400000001001d00000020012000390000000001010433001600000001001d0000000001020433001700000001001d00000006010000290000000001010433000000400300043d00000be502000041001a00000003001d0000000000230435000000000200041400000baa01100197001d00000001001d000000040010008c000011900000c13d0000001f01000029000000200010008c00000020040000390000000004014019000011bf0000013d0000001a0100002900000b860010009c00000b8601008041000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c70000001d020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c001f00000003001d0000002004000039000000000403401900000020064001900000001a05600029000011ab0000613d000000000701034f0000001a08000029000000007307043c0000000008380436000000000058004b000011a70000c13d0000001f07400190000011b80000613d000000000861034f0000000303700210000000000605043300000000063601cf000000000636022f000000000708043b0000010003300089000000000737022f00000000033701cf000000000363019f00000000003504350000001f0000002f001e0000000103530002000000010355000000010020019000001e7a0000613d0000001b0d000029000000600e0000390000001f01400039000000600210018f0000001a01200029000000000021004b00000000040000390000000104004039001c00000001001d00000ba70010009c000005790000213d0000000100400190000005790000c13d0000001c01000029000000400010043f0000001f01000029000000200010008c000006070000413d0000001a010000290000000001010433001100000001001d00000baa0010009c000006070000213d00000bf9010000410000001c03000029000000000013043500000000040004140000001d01000029000000040010008c0000120d0000613d00000b860030009c00000b86010000410000000001034019000000400110021000000b860040009c00000b8604008041000000c002400210000000000112019f00000b8a011001c70000001d020000292e152e100000040f0000001c080000290000000003010019000000600330027000000b8603300197000000200030008c001f00000003001d0000002004000039000000000403401900000020064001900000000005680019000011f60000613d000000000701034f000000007307043c0000000008380436000000000058004b000011f20000c13d0000001f07400190000012030000613d000000000861034f0000000303700210000000000605043300000000063601cf000000000636022f000000000708043b0000010003300089000000000737022f00000000033701cf000000000363019f00000000003504350000001f0000002f001e0000000103530002000000010355000000010020019000001e870000613d0000001f01400039000000600210018f0000001b0d000029000000600e0000390000001c030000290000000001320019001a00000001001d00000ba70010009c000005790000213d0000001a01000029000000400010043f0000001f01000029000000200010008c000006070000413d0000001c010000290000000001010433001000000001001d00000bfa010000410000001a03000029000000000013043500000000040004140000001d01000029000000040010008c000012520000613d00000b860030009c00000b86010000410000000001034019000000400110021000000b860040009c00000b8604008041000000c002400210000000000112019f00000b8a011001c70000001d020000292e152e100000040f0000001a080000290000000003010019000000600330027000000b8603300197000000200030008c001f00000003001d00000020040000390000000004034019000000200640019000000000056800190000123b0000613d000000000701034f000000007307043c0000000008380436000000000058004b000012370000c13d0000001f07400190000012480000613d000000000861034f0000000303700210000000000605043300000000063601cf000000000636022f000000000708043b0000010003300089000000000737022f00000000033701cf000000000363019f00000000003504350000001f0000002f001e0000000103530002000000010355000000010020019000001e940000613d0000001f01400039000000600210018f0000001b0d000029000000600e0000390000001a030000290000000001320019001c00000001001d00000ba70010009c000005790000213d0000001c01000029000000400010043f0000001f01000029000000200010008c000006070000413d0000001a010000290000000001010433001a00000001001d00000bfb010000410000001c03000029000000000013043500000000040004140000001d01000029000000040010008c000012970000613d00000b860030009c00000b86010000410000000001034019000000400110021000000b860040009c00000b8604008041000000c002400210000000000112019f00000b8a011001c70000001d020000292e152e100000040f0000001c080000290000000003010019000000600330027000000b8603300197000000200030008c001f00000003001d0000002004000039000000000403401900000020064001900000000005680019000012800000613d000000000701034f000000007307043c0000000008380436000000000058004b0000127c0000c13d0000001f074001900000128d0000613d000000000861034f0000000303700210000000000605043300000000063601cf000000000636022f000000000708043b0000010003300089000000000737022f00000000033701cf000000000363019f00000000003504350000001f0000002f001e0000000103530002000000010355000000010020019000001ea10000613d0000001f01400039000000600210018f0000001b0d000029000000600e0000390000001c03000029000000000232001900000ba70020009c000005790000213d000000400020043f0000001f01000029000000200010008c000006070000413d00000bea0020009c000005790000213d0000001c010000290000000001010433000001a003200039000000400030043f0000018003200039000000180400002900000000004304350000016003200039000000000013043500000140012000390000001a030000290000000000310435000001200120003900000010030000290000000000310435000001000120003900000011030000290000000000310435000000e00120003900000019030000290000000000310435000000c00120003900000012030000290000000000310435000000a0012000390000001503000029000000000031043500000080012000390000001303000029000000000031043500000060012000390000001403000029000000000031043500000040012000390000001d030000290000000000310435000000160100002900000baa01100197000000200320003900000000001304350000001701000029000000000012043500000020010000290000000001010433000000080010006c00001d6c0000a13d0000000301d00029000000000021043500000020010000290000000001010433000000080010006c00001d6c0000a13d00000008020000290000000102200039000000020020006c00000a980000413d0000002e02000029000005450000013d0000000007000019000012e00000013d00000000042400190000000107700039000000000037004b000005500000813d0000000008150049000000400880008a00000000008404350000002006200029002000000006001d000000000806043300000000c9080434000001a006000039000000000b65043600000000d9090434000001a00a50003900000000009a0435000001c00a500039000000000009004b000012f70000613d000000000e000019000000000fae00190000000006ed0019000000000606043300000000006f0435000000200ee0003900000000009e004b000012f00000413d0000000006a90019000000000006043500000000060c043300000baa0660019700000000006b04350000004006800039000000000606043300000baa06600197000000400b50003900000000006b043500000060068000390000000006060433000000600b50003900000000006b043500000080068000390000000006060433000000800b50003900000000006b04350000001f0690003900000bff066001970000000006a600190000000009560049000000a00a500039000000a00b800039000000000b0b043300000000009a043500000000ba0b04340000000009a6043600000000000a004b0000131d0000613d000000000c00001900000000069c0019000000000dcb0019000000000d0d04330000000000d60435000000200cc000390000000000ac004b000013160000413d00000000069a001900000000000604350000001f06a0003900000bff066001970000000006960019000000c0098000390000000009090433000000000a560049000000c00b5000390000000000ab043500000000ba0904340000000009a6043600000000000a004b000013330000613d000000000c00001900000000069c0019000000000dcb0019000000000d0d04330000000000d60435000000200cc000390000000000ac004b0000132c0000413d00000000069a001900000000000604350000001f06a0003900000bff066001970000000006960019000000e0098000390000000009090433000000000a560049000000e00b5000390000000000ab043500000000ba0904340000000009a6043600000000000a004b000013490000613d000000000c00001900000000069c0019000000000dcb0019000000000d0d04330000000000d60435000000200cc000390000000000ac004b000013420000413d00000000069a001900000000000604350000010006800039000000000606043300000baa06600197000001000b50003900000000006b043500000120068000390000000006060433000001200b50003900000000006b043500000140068000390000000006060433000001400b50003900000000006b043500000160068000390000000006060433000001600b50003900000000006b04350000001f06a0003900000bff0660019700000000069600190000000009560049000001800550003900000180088000390000000008080433000000000095043500000000090804330000000005960436000000000009004b000012dc0000613d000000000a0000190000002008800039000000000b08043300000000c60b043400000baa066001970000000006650436000000000c0c04330000000000c604350000004006b000390000000006060433000000400c50003900000000006c04350000006006b000390000000006060433000000600c50003900000000006c04350000008006b000390000000006060433000000800c50003900000000006c0435000000a006b000390000000006060433000000a00c50003900000000006c0435000000c006b000390000000006060433000000c00c50003900000000006c0435000000e006b000390000000006060433000000e00c50003900000000006c04350000010006b000390000000006060433000001000c50003900000000006c04350000012006b000390000000006060433000001200c50003900000000006c04350000014006b000390000000006060433000001400c50003900000000006c04350000016006b000390000000006060433000000000006004b0000000006000039000000010600c039000001600c50003900000000006c04350000018006b000390000000006060433000001800c50003900000000006c0435000001a006b00039000000000606043300000baa06600197000001a00c50003900000000006c0435000001c006b000390000000006060433000001c00c50003900000000006c0435000001e006b000390000000006060433000001e00c50003900000000006c04350000020006b000390000000006060433000002000b50003900000000006b04350000022005500039000000010aa0003900000000009a004b000013690000413d000012dc0000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000013bc0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000013c80000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000013d40000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000013e00000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000013ec0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000013f80000c13d000006630000013d00150baa0020019b0000001e01000029001601a00010003d001d00000000001d001c00000000001d000000400100043d001e00000001001d00000bc20010009c000005790000213d0000001e020000290000004001200039000000400010043f0000000001020436001b00000001001d00000000000104350000001f0100002900000000010104330000001d02000029000000000021004b00001d6c0000a13d0000000504200210001900000004001d0000001605400029000000000105043300000baa011001970000001e0400002900000000001404350000001f010000290000000001010433000000000021004b00001d6c0000a13d0000000002050433000000400a00043d00000be60100004100000000001a0435000000000100041400000baa02200197000000040020008c001a00000005001d000014290000c13d000000200030008c00000020040000390000000004034019000014550000013d00000b8600a0009c00000b860300004100000000030a4019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000b8a011001c700200000000a001d2e152e100000040f000000200a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000014440000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000014400000c13d0000001f07400190000014510000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001d780000613d0000001f01400039000000600110018f00000000060a00190000000005a10019000000000015004b00000000020000390000000102004039002000000005001d00000ba70050009c000005790000213d0000000100200190000005790000c13d0000002002000029000000400020043f000000200040008c000006070000413d0000001f0200002900000000020204330000001d0020006c0000001a0200002900001d6c0000a13d0000000004060433001800000004001d000000000202043300000be70400004100000020050000290000000000450435000000040450003900000baa02200197000000000024043500000000040004140000001502000029000000040020008c0000147c0000c13d000000000115001900000ba70010009c000005790000213d000000400010043f000014af0000013d00000b860050009c00000b86010000410000000001054019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000bb6011001c72e152e100000040f000000200a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000014960000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000014920000c13d0000001f07400190000014a30000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001d840000613d0000001f01400039000000600110018f0000000001a1001900000ba70010009c000005790000213d000000400010043f000000200030008c000006070000413d00000020010000290000000002010433000000180400002900000000014200a9000000000004004b0000001d05000029000014b90000613d00000000044100d9000000000024004b00001d720000c13d00000bd10110012a0000001b020000290000000000120435000000170100002900000000010104330000000002010433000000000052004b00001d6c0000a13d000000190210002900000020022000390000001e0400002900000000004204350000000001010433000000000051004b00001d6c0000a13d0000001b0100002900000000010104330000001c0010002a00001d720000413d001c001c0010002d001d00010050003d0000001f0100002900000000010104330000001d0010006b000014020000413d000009b30000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000014da0000c13d000006630000013d0028001c0000002d000000400400043d002700000004001d001900000004001d0000000004460019000000000064004b0000000005000039000000010500403900000ba70040009c000005790000213d0000000100500190000005790000c13d000000400040043f00000019040000290000000004240436000000000002004b000015030000613d00000060020000390000000005000019000000400600043d00000bbf0060009c000005790000213d0000008007600039000000400070043f0000006007600039000000000027043500000040076000390000000000070435000000200760003900000000000704350000000000060435000000000754001900000000006704350000002005500039000000000015004b000014f20000413d002600000000003d0000001c010000290000000001010433000000000001004b000015400000c13d000000400100043d00000020020000390000000002210436000000190300002900000000030304330000000000320435000000400410003900000005023002100000000002420019000000000003004b000002180000613d00000080050000390000000006000019000000190c0000290000151a0000013d0000000106600039000000000036004b000002180000813d0000000007120049000000400770008a0000000004740436000000200cc0003900000000070c0433000000009807043400000baa088001970000000008820436000000000909043300000baa09900197000000000098043500000040087000390000000008080433000000400920003900000000008904350000006007700039000000000707043300000060082000390000000000580435000000800920003900000000080704330000000000890435000000a002200039000000000008004b000015170000613d00000000090000190000002007700039000000000a07043300000000ba0a043400000baa0aa00197000000000aa20436000000000b0b04330000000000ba043500000040022000390000000109900039000000000089004b000015340000413d000015170000013d001f00000000001d000000400100043d001d00000001001d00000bbf0010009c000005790000213d0000001d020000290000008001200039000000400010043f00000060042000390000006001000039001800000004001d00000000001404350000004001200039001600000001001d00000000000104350000002001200039001700000001001d00000000000104350000000000020435002500000002001d0000001c0100002900000000010104330000001f0010006c00001d6c0000a13d0000001f0400002900000005014002100000001c0200002900000000011200190000002001100039001a00000001001d000000000101043300000baa011001970000001d0500002900000000001504350000000001020433000000000041004b00001d6c0000a13d0000001a010000290000000002010433000000400400043d00000bc001000041001b00000004001d0000000000140435000000000100041400000baa02200197000000040020008c000015730000c13d000000200030008c000000200400003900000000040340190000159d0000013d0000001b0300002900000b860030009c00000b8603008041000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000b8a011001c72e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000001b056000290000158c0000613d000000000701034f0000001b08000029000000007907043c0000000008980436000000000058004b000015880000c13d0000001f07400190000015990000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f9c0000613d0000001f01400039000000600110018f0000001b02100029000000000012004b0000000004000039000000010400403900000ba70020009c000005790000213d0000000100400190000005790000c13d000000400020043f000000200030008c000006070000413d0000001b02000029000000000202043300000baa0020009c000006070000213d000000170400002900000000002404350000001c0200002900000000020204330000001f0020006c00001d6c0000a13d0000001a020000290000000002020433000000400500043d00000bc1040000410000000000450435000000200400002900000baa04400197001b00000005001d00000004055000390000000000450435000000000400041400000baa02200197000000040020008c000015ee0000613d0000001b0100002900000b860010009c00000b8601008041000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000bb6011001c72e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000001b05600029000015db0000613d000000000701034f0000001b08000029000000007907043c0000000008980436000000000058004b000015d70000c13d0000001f07400190000015e80000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001fa80000613d0000001f01400039000000600110018f0000001b02100029000000000012004b0000000001000039000000010100403900000ba70020009c000005790000213d0000000100100190000005790000c13d000000400020043f000000200030008c000006070000413d0000001b010000290000000001010433000000160200002900000000001204350000001c0100002900000000010104330000001f0010006c00001d6c0000a13d0000001e01000029000000000501043300000ba70050009c000005790000213d00000005015002100000003f0210003900000ba802200197000000400600043d0000000004260019001300000006001d000000000064004b0000000002000039000000010200403900000ba70040009c000005790000213d0000000100200190000005790000c13d0000001a020000290000000002020433000000400040043f00000013040000290000000004540436000000000005004b000016270000613d0000000005000019000000400600043d00000bc20060009c000005790000213d0000004007600039000000400070043f000000200760003900000000000704350000000000060435000000000754001900000000006704350000002005500039000000000015004b0000161a0000413d0000001e010000290000000001010433000000000001004b00001d510000613d001f0baa0020019b001d00000000001d000000400100043d002000000001001d00000bc30010009c000005790000213d00000020020000290000006001200039000000400010043f0000004001200039001600000001001d00000000000104350000000001020436001c00000001001d0000000000010435000000400100043d001a00000001001d00000bc30010009c000005790000213d0000001a020000290000006001200039000000400010043f0000004001200039001400000001001d00000000000104350000000001020436001700000001001d000000000001043500000ba50100004100000000001004430000000001000412000000040010044300000020010000390000002400100443000000000100041400000b860010009c00000b8601008041000000c00110021000000bc4011001c700008005020000392e152e100000040f000000010020019000001e440000613d000000000101043b000000000001004b0000001d020000290019000500200218000016750000613d0000001e010000290000000001010433000000000021004b00001d6c0000a13d00000019020000290000001e012000290000002001100039001500000001001d0000000001010433000000400300043d00000bc5020000410000000002230436001800000002001d00000baa01100197001b00000003001d0000000402300039000000000012043500000000010004140000001f02000029000000040020008c0000168f0000c13d0000000003000031000000600030008c00000060040000390000000004034019000016ba0000013d0000001e010000290000000001010433000000000021004b00001d6c0000a13d00000019020000290000001e012000290000002001100039001500000001001d0000000001010433000000400300043d00000bc8020000410000000002230436001800000002001d00000baa01100197001b00000003001d0000000402300039000000000012043500000000010004140000001f02000029000000040020008c0000172a0000c13d0000000003000031000000600030008c00000060040000390000000004034019000017550000013d0000001b0200002900000b860020009c00000b8602008041000000400220021000000b860010009c00000b8601008041000000c001100210000000000121019f00000bb6011001c70000001f020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000600030008c0000006004000039000000000403401900000060064001900000001b05600029000016a90000613d000000000701034f0000001b08000029000000007907043c0000000008980436000000000058004b000016a50000c13d0000001f07400190000016b60000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f240000613d0000001f01400039000000e00110018f0000001b02100029000000000012004b0000000004000039000000010400403900000ba70020009c000005790000213d0000000100400190000005790000c13d000000400020043f000000600030008c000006070000413d0000001b02000029000000000202043300000bc60020009c000006070000213d000000180400002900000000040404330000001b0500002900000040055000390000000005050433000000160600002900000000005604350000001c050000290000000000450435000000200400002900000000002404350000001e0200002900000000020204330000001d0020006c00001d6c0000a13d00000015020000290000000002020433000000400a00043d00000bc70400004100000000044a0436001b00000004001d00000baa022001970000000404a00039000000000024043500000000020004140000001f04000029000000040040008c000017160000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bb6011001c70000001f0200002900180000000a001d2e152e100000040f0000000003010019000000600330027000000b8603300197000000600030008c000000600400003900000000040340190000006006400190000000180a0000290000001805600029000017030000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000016ff0000c13d0000001f07400190000017100000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f300000613d0000001f01400039000000e00110018f00000000040a00190000000002a10019000000000012004b0000000001000039000000010100403900000ba70020009c000005790000213d0000000100100190000005790000c13d000000400020043f000000600030008c000006070000413d000000000104043300000bc60010009c000006070000213d0000001b02000029000000000202043300000040044000390000000004040433000017cc0000013d0000001b0200002900000b860020009c00000b8602008041000000400220021000000b860010009c00000b8601008041000000c001100210000000000121019f00000bb6011001c70000001f020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000600030008c0000006004000039000000000403401900000060064001900000001b05600029000017440000613d000000000701034f0000001b08000029000000007907043c0000000008980436000000000058004b000017400000c13d0000001f07400190000017510000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f3c0000613d0000001f01400039000000e00110018f0000001b02100029000000000012004b0000000004000039000000010400403900000ba70020009c000005790000213d0000000100400190000005790000c13d000000400020043f000000600030008c000006070000413d0000001b02000029000000000202043300000bc60020009c000006070000213d0000001804000029000000000404043300000b860040009c000006070000213d0000001b050000290000004005500039000000000505043300000b860050009c000006070000213d000000160600002900000000005604350000001c050000290000000000450435000000200400002900000000002404350000001e0200002900000000020204330000001d0020006c00001d6c0000a13d00000015020000290000000002020433000000400500043d00000bc9040000410000000004450436001800000004001d00000baa02200197001b00000005001d0000000404500039000000000024043500000000020004140000001f04000029000000040040008c000017b40000613d0000001b0100002900000b860010009c00000b8601008041000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bb6011001c70000001f020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000600030008c0000006004000039000000000403401900000060064001900000001b05600029000017a10000613d000000000701034f0000001b08000029000000007907043c0000000008980436000000000058004b0000179d0000c13d0000001f07400190000017ae0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f480000613d0000001f01400039000000e00110018f0000001b02100029000000000012004b0000000001000039000000010100403900000ba70020009c000005790000213d0000000100100190000005790000c13d000000400020043f000000600030008c000006070000413d0000001b01000029000000000101043300000bc60010009c000006070000213d0000001802000029000000000202043300000b860020009c000006070000213d0000001b040000290000004004400039000000000404043300000b860040009c000006070000213d00000014050000290000000000450435000000170400002900000000002404350000001a0200002900000000001204350000001e0100002900000000010104330000001d0010006c00001d6c0000a13d00000019020000290000001e012000290000002001100039001800000001001d0000000002010433000000400500043d00000bca010000410000000000150435000000000100041400000baa02200197000000040020008c0000002004000039001500000005001d0000180f0000613d00000b860050009c00000b86030000410000000003054019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000b8a011001c72e152e100000040f00000015080000290000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000000005680019000017fd0000613d000000000701034f000000007907043c0000000008980436000000000058004b000017f90000c13d0000001f074001900000180a0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001ed00000613d00000015050000290000001f01400039000000600110018f0000000004510019000000000014004b00000000020000390000000102004039001b00000004001d00000ba70040009c000005790000213d0000000100200190000005790000c13d0000001b02000029000000400020043f000000200030008c000006070000413d0000001b0200002900000bcb0020009c000005790000213d000000150200002900000000020204330000001b050000290000002004500039000000400040043f00000000002504350000001e0200002900000000020204330000001d0020006c00001d6c0000a13d00000018020000290000000002020433000000400500043d00000bcc04000041000000000045043500000baa042001970000000402500039001200000004001d000000000042043500000000020004140000001f04000029000000040040008c001500000005001d000018670000613d00000b860050009c00000b86010000410000000001054019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bb6011001c70000001f020000292e152e100000040f00000015080000290000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000000005680019000018530000613d000000000701034f000000007907043c0000000008980436000000000058004b0000184f0000c13d0000001f07400190000018600000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001edc0000613d0000001f01400039000000600110018f00000015050000290000000002510019000000000012004b0000000001000039000000010100403900000ba70020009c000005790000213d0000000100100190000005790000c13d000000400020043f000000200030008c000006070000413d00000015010000290000000001010433001500000001001d00000ba50100004100000000001004430000000001000412000000040010044300000040010000390000002400100443000000000100041400000b860010009c00000b8601008041000000c00110021000000bc4011001c700008005020000392e152e100000040f000000010020019000001e440000613d000000000101043b000000010010008c0000188d0000613d000000020010008c00001e4b0000c13d00000bcf0100004100000000001004430000000001000414000018900000013d00000bcd010000410000000000100443000000000100041400000b860010009c00000b8601008041000000c00110021000000bce011001c70000800b020000392e152e100000040f000000010020019000001e440000613d00000016020000290000000004020433000000000101043b000000000041004b00000000020000390000000102002039000000000004004b0000000003000039000000010300c039000000000023017000000000040160190000001c010000290000000001010433001600000004001d001000000014005300001d720000413d0000001d02000029000019470000613d000000150000006b000019440000613d000000400200043d00000bd001000041001100000002001d000000000012043500000000010004140000001202000029000000040020008c000018b90000c13d0000000003000031000000200030008c00000020040000390000000004034019000018e40000013d000000110200002900000b860020009c00000b8602008041000000400220021000000b860010009c00000b8601008041000000c001100210000000000121019f00000b8a011001c700000012020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000001105600029000018d30000613d000000000701034f0000001108000029000000007907043c0000000008980436000000000058004b000018cf0000c13d0000001f07400190000018e00000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f6c0000613d0000001f01400039000000600210018f0000001101200029000000000021004b0000000002000039000000010200403900000ba70010009c000005790000213d0000000100200190000005790000c13d000000400010043f000000200030008c000006070000413d0000001102000029000000000302043300000bd1023000d1000000000003004b000018f90000613d00000000033200d900000bd10030009c00001d720000c13d0000001b030000290000000003030433000000000003004b00001e450000613d000000100500002900000015045000b900000000055400d9000000150050006c00001d720000c13d000000000023004b000019080000a13d00000bcb0010009c0000000002000019000019180000a13d000005790000013d00000bcb0010009c000005790000213d0000002005100039000000400050043f000000000001043500000bd2054000d1000000000004004b000019130000613d00000000014500d900000bd20010009c00001d720000c13d000000400100043d00000bcb0010009c000005790000213d00000000023200d900000000022500d90000002003100039000000400030043f0000000000210435000000400200043d00000bcb0020009c000005790000213d000000200300002900000000030304330000002004200039000000400040043f00000bc6033001970000000000320435000000400300043d00000bcb0030009c000005790000213d0000002004300039000000400040043f000000000003043500000000020204330000000001010433000000000021001a00001d720000413d000000400300043d00000bcb0030009c000005790000213d00000000022100190000002001300039000000400010043f0000000000230435000000400100043d00000bc20010009c000005790000213d0000004003100039000000400030043f000000200310003900000bd30400004100000000004304350000001303000039000000000031043500000bd40020009c00001ebd0000813d000000200100002900000000002104350000001d020000290000001c01000029000000160300002900000000003104350000001e010000290000000001010433000000000021004b00001d6c0000a13d00000018010000290000000001010433000000400300043d00000bd602000041000000000023043500000baa02100197001c00000003001d0000000401300039001500000002001d000000000021043500000000010004140000001f02000029000000040020008c0000195e0000c13d0000000003000031000000200030008c00000020040000390000000004034019000019890000013d0000001c0200002900000b860020009c00000b8602008041000000400220021000000b860010009c00000b8601008041000000c001100210000000000121019f00000bb6011001c70000001f020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000001c05600029000019780000613d000000000701034f0000001c08000029000000007907043c0000000008980436000000000058004b000019740000c13d0000001f07400190000019850000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001ee80000613d0000001f01400039000000600210018f0000001c01200029000000000021004b0000000002000039000000010200403900000ba70010009c000005790000213d0000000100200190000005790000c13d000000400010043f000000200030008c000006070000413d0000001c010000290000000001010433001c00000001001d00000ba50100004100000000001004430000000001000412000000040010044300000040010000390000002400100443000000000100041400000b860010009c00000b8601008041000000c00110021000000bc4011001c700008005020000392e152e100000040f000000010020019000001e440000613d000000000101043b000000010010008c000019b10000613d000000020010008c00001e4b0000c13d00000bcf0100004100000000001004430000000001000414000019b40000013d00000bcd010000410000000000100443000000000100041400000b860010009c00000b8601008041000000c00110021000000bce011001c70000800b020000392e152e100000040f000000010020019000001e440000613d00000014020000290000000004020433000000000101043b000000000041004b00000000020000390000000102002039000000000004004b0000000003000039000000010300c0390000000000230170000000000401601900000017010000290000000001010433001600000004001d000000000114004b00001d720000413d0000001d0200002900001a610000613d001200000001001d0000001c0000006b00001a5e0000613d000000400200043d00000bd701000041001400000002001d000000000012043500000000010004140000001502000029000000040020008c000019de0000c13d0000000003000031000000200030008c0000002004000039000000000403401900001a090000013d000000140200002900000b860020009c00000b8602008041000000400220021000000b860010009c00000b8601008041000000c001100210000000000121019f00000b8a011001c700000015020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000001405600029000019f80000613d000000000701034f0000001408000029000000007907043c0000000008980436000000000058004b000019f40000c13d0000001f0740019000001a050000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f780000613d0000001f01400039000000600210018f0000001401200029000000000021004b0000000002000039000000010200403900000ba70010009c000005790000213d0000000100200190000005790000c13d000000400010043f000000200030008c000006070000413d00000012020000290000001c032000b900000000022300d90000001c0020006c00001d720000c13d00000014020000290000000002020433000000000002004b00001a2f0000613d00000bcb0010009c000005790000213d0000002004100039000000400040043f000000000001043500000bd2043000d1000000000003004b00001a2a0000613d00000000013400d900000bd20010009c00001d720000c13d000000400100043d00000bcb0010009c000005790000213d00000000022400d900001a320000013d00000bcb0010009c0000000002000019000005790000213d0000002003100039000000400030043f0000000000210435000000400200043d00000bcb0020009c000005790000213d0000001a0300002900000000030304330000002004200039000000400040043f00000bc6033001970000000000320435000000400300043d00000bcb0030009c000005790000213d0000002004300039000000400040043f000000000003043500000000020204330000000001010433000000000021001a00001d720000413d000000400300043d00000bcb0030009c000005790000213d00000000022100190000002001300039000000400010043f0000000000230435000000400100043d00000bc20010009c000005790000213d0000004003100039000000400030043f000000200310003900000bd30400004100000000004304350000001303000039000000000031043500000bd40020009c00001ebd0000813d0000001a0100002900000000002104350000001d020000290000001701000029000000160300002900000000003104350000001e010000290000000001010433000000000021004b00001d6c0000a13d000000400100043d001700000001001d00000bcb0010009c000005790000213d0000001801000029000000000101043300000baa031001970000002001000029000000000101043300000017040000290000002002400039000000400020043f00000bc6011001970000000000140435000000400400043d00000bd801000041000000000014043500000004014000390000002a02000029001600000003001d0000000000310435001c00000004001d0000002401400039002000000002001d00000baa02200197001800000002001d000000000021043500000000010004140000001f02000029000000040020008c00001a890000c13d0000000003000031000000200030008c0000002004000039000000000403401900001ab40000013d0000001c0200002900000b860020009c00000b8602008041000000400220021000000b860010009c00000b8601008041000000c001100210000000000121019f00000bbb011001c70000001f020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000001c0560002900001aa30000613d000000000701034f0000001c08000029000000007907043c0000000008980436000000000058004b00001a9f0000c13d0000001f0740019000001ab00000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001ef40000613d0000001f01400039000000600110018f0000001c04100029000000000014004b00000000020000390000000102004039001e00000004001d00000ba70040009c000005790000213d0000000100200190000005790000c13d0000001e02000029000000400020043f000000200030008c000006070000413d0000001e0200002900000bcb0020009c000005790000213d0000001c0200002900000000020204330000001e050000290000002004500039000000400040043f0000000000250435000000400a00043d000000000002004b00001b5d0000c13d00000017020000290000000002020433001500000002001d00000bd90200004100000000002a043500000000020004140000001f04000029000000040040008c00001b070000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c70000001f02000029001c0000000a001d2e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000001c0a0000290000001c0560002900001af40000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00001af00000c13d0000001f0740019000001b010000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f540000613d0000001f01400039000000600110018f00000000040a00190000000005a10019000000000015004b00000000020000390000000102004039001c00000005001d00000ba70050009c000005790000213d0000000100200190000005790000c13d0000001c02000029000000400020043f000000200030008c000006070000413d000000000204043300000bc60020009c000006070000213d000000150020006b00001b1c0000813d0000001c0a00002900001b5d0000013d00000bd9020000410000001c04000029000000000024043500000000020004140000001f04000029000000040040008c00001b500000613d0000001c0100002900000b860010009c00000b8601008041000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c70000001f020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000001c0560002900001b3d0000613d000000000701034f0000001c08000029000000007907043c0000000008980436000000000058004b00001b390000c13d0000001f0740019000001b4a0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f840000613d0000001f01400039000000600110018f0000001c0110002900000ba70010009c000005790000213d000000400010043f000000200030008c000006070000413d0000001c01000029000000000101043300000bc60010009c000006070000213d0000001e020000290000000000120435000000400a00043d00000000010a001900000bcb00a0009c000005790000213d00000000020100190000002001200039000000400010043f00000000000204350000001e01000029000000000101043300000017020000290000000002020433000000000112004b00001d720000413d000000400200043d001e00000002001d00000bcb0020009c000005790000213d0000001e040000290000002002400039000000400020043f0000000000140435000000400500043d00000bda01000041000000000015043500000004015000390000001802000029000000000021043500000000010004140000001602000029000000040020008c0000002004000039001700000005001d00001ba90000613d00000b860050009c00000b86030000410000000003054019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000bb6011001c72e152e100000040f00000017080000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000002006400190000000000568001900001b970000613d000000000701034f000000007907043c0000000008980436000000000058004b00001b930000c13d0000001f0740019000001ba40000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f000000613d00000017050000290000001f01400039000000600110018f0000000004510019000000000014004b00000000020000390000000102004039001c00000004001d00000ba70040009c000005790000213d0000000100200190000005790000c13d0000001c02000029000000400020043f000000200030008c000006070000413d0000001702000029000000000402043300000bd1024000d1000000000004004b00001bc00000613d00000000044200d900000bd10040009c00001d720000c13d0000001b040000290000000004040433000000000004004b00001e450000613d0000001e05000029000000000505043300000000064200d900170000006500ad000000000024004b00001bcd0000213d00000017026000f9000000000052004b00001d720000c13d0000002902000029001e00000002001d00000000020204330000001d0020006c00001d6c0000a13d0000001c0200002900000bcb0020009c000005790000213d00000019020000290000002004200039001500000004001d0000001e02400029001600000002001d000000000202043300000baa062001970000001a0200002900000000020204330000001c050000290000002004500039000000400040043f00000bc6022001970000000000250435000000400500043d00000024025000390000001804000029000000000042043500000bdb0200004100000000002504350000000402500039001900000006001d000000000062043500000000020004140000001f04000029000000040040008c001a00000005001d00001c1f0000613d00000b860050009c00000b86010000410000000001054019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bbb011001c70000001f020000292e152e100000040f0000001a080000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000002006400190000000000568001900001c0b0000613d000000000701034f000000007907043c0000000008980436000000000058004b00001c070000c13d0000001f0740019000001c180000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f0c0000613d0000001f01400039000000600110018f0000001a050000290000000004510019000000000014004b00000000020000390000000102004039001b00000004001d00000ba70040009c000005790000213d0000000100200190000005790000c13d0000001b02000029000000400020043f000000200030008c000006070000413d0000001b0200002900000bcb0020009c000005790000213d0000001a0200002900000000020204330000001b050000290000002004500039000000400040043f0000000000250435000000400a00043d000000000002004b00001cc60000c13d0000001c020000290000000002020433001400000002001d00000bd90200004100000000002a043500000000020004140000001f04000029000000040040008c00001c700000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c70000001f02000029001a0000000a001d2e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000001a0a0000290000001a0560002900001c5d0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00001c590000c13d0000001f0740019000001c6a0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f600000613d0000001f01400039000000600110018f00000000040a00190000000005a10019000000000015004b00000000020000390000000102004039001a00000005001d00000ba70050009c000005790000213d0000000100200190000005790000c13d0000001a02000029000000400020043f000000200030008c000006070000413d000000000204043300000bc60020009c000006070000213d000000140020006b00001c850000813d0000001a0a00002900001cc60000013d00000bd9020000410000001a04000029000000000024043500000000020004140000001f04000029000000040040008c00001cb90000613d0000001a0100002900000b860010009c00000b8601008041000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c70000001f020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000001a0560002900001ca60000613d000000000701034f0000001a08000029000000007907043c0000000008980436000000000058004b00001ca20000c13d0000001f0740019000001cb30000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f900000613d0000001f01400039000000600110018f0000001a0110002900000ba70010009c000005790000213d000000400010043f000000200030008c000006070000413d0000001a01000029000000000101043300000bc60010009c000006070000213d0000001b020000290000000000120435000000400a00043d00000000010a001900000bcb00a0009c000005790000213d00000000020100190000002001200039000000400010043f00000000000204350000001b0100002900000000010104330000001c020000290000000002020433000000000112004b00001d720000413d000000400200043d001c00000002001d00000bcb0020009c000005790000213d0000001c040000290000002002400039000000400020043f0000000000140435000000400500043d00000bb501000041000000000015043500000004015000390000001802000029000000000021043500000000010004140000001902000029000000040020008c0000002004000039001b00000005001d00001d120000613d00000b860050009c00000b86030000410000000003054019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000bb6011001c72e152e100000040f0000001b080000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000002006400190000000000568001900001d000000613d000000000701034f000000007907043c0000000008980436000000000058004b00001cfc0000c13d0000001f0740019000001d0d0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f180000613d0000001b050000290000001f01400039000000600210018f0000000001520019000000000021004b0000000002000039000000010200403900000ba70010009c000005790000213d0000000100200190000005790000c13d000000400010043f000000200030008c000006070000413d0000001c0200002900000000040204330000001b02000029000000000502043300000000025400a9000000000005004b00001d290000613d00000000055200d9000000000045004b00001d720000c13d00000bc20010009c000005790000213d0000004004100039000000400040043f000000000401043600000000000404350000001e0500002900000000050504330000001d07000029000000000075004b00001d6c0000a13d000000170500002900000bd20550012a00000bd20220012a0000001606000029000000000606043300000baa0660019700000000006104350000000002520019000000000024043500000013020000290000000002020433000000000072004b00001d6c0000a13d0000001304000029000000150240002900000000001204350000000001040433000000000071004b00001d6c0000a13d001d00010070003d0000001e0100002900000000010104330000001d0010006b0000162d0000413d001900270000002d001f00260000002d0000002501000029001d00000001001d001800600010003d000000130100002900000018020000290000000000120435000000190100002900000000010104330000001f0010006c00001d6c0000a13d0000001f0400002900000005014002100000001902000029000000000112001900000020011000390000001d0500002900000000005104350000000001020433000000000041004b00001d6c0000a13d0000001f02000029002600010020003d00000001022000390000002801000029001c00000001001d0000000001010433001f00000002001d000000000012004b000015410000413d000015080000013d00000bdc01000041000000000010043f0000003201000039000000040010043f00000bb60100004100002e170001043000000bdc01000041000000000010043f0000001101000039000000040010043f00000bb60100004100002e17000104300000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001d7f0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001d8b0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001d970000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001da30000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001daf0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001dbb0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001dc70000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001dd30000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001ddf0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001deb0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001df70000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e030000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e0f0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e1b0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e270000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e330000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e3f0000c13d000006630000013d000000000001042f00000bdc01000041000000000010043f0000001201000039000000040010043f00000bb60100004100002e170001043000000bdc01000041000000000010043f0000005101000039000000040010043f00000bb60100004100002e17000104300000001f010000290000001f0510018f00000b8806100198000000400200043d000000000462001900001ead0000613d0000001e0700035f0000000008020019000000007107043c0000000008180436000000000048004b00001e590000c13d00001ead0000013d000000000301034f0000001f0580018f000000000908001900000b8806800198000000400200043d000000000462001900001e6b0000613d000000000703034f0000000008020019000000007107043c0000000008180436000000000048004b00001e670000c13d000000000005004b00001e780000613d000000000163034f0000000303500210000000000504043300000000053501cf000000000535022f000000000101043b0000010003300089000000000131022f00000000013101cf000000000151019f00000000001404350000006001900210000006710000013d0000001f010000290000001f0510018f00000b8806100198000000400200043d000000000462001900001ead0000613d0000001e0700035f0000000008020019000000007107043c0000000008180436000000000048004b00001e820000c13d00001ead0000013d0000001f010000290000001f0510018f00000b8806100198000000400200043d000000000462001900001ead0000613d0000001e0700035f0000000008020019000000007107043c0000000008180436000000000048004b00001e8f0000c13d00001ead0000013d0000001f010000290000001f0510018f00000b8806100198000000400200043d000000000462001900001ead0000613d0000001e0700035f0000000008020019000000007107043c0000000008180436000000000048004b00001e9c0000c13d00001ead0000013d0000001f010000290000001f0510018f00000b8806100198000000400200043d000000000462001900001ead0000613d0000001e0700035f0000000008020019000000007107043c0000000008180436000000000048004b00001ea90000c13d000000000005004b00001eba0000613d0000001e0160035f0000000303500210000000000504043300000000053501cf000000000535022f000000000101043b0000010003300089000000000131022f00000000013101cf000000000151019f00000000001404350000001f010000290000006001100210000006710000013d000000400400043d002000000004001d00000bd502000041000000000024043500000004024000390000002003000039000000000032043500000024024000392e151fb40000040f0000002002000029000000000121004900000b860010009c00000b860100804100000b860020009c00000b860200804100000060011002100000004002200210000000000121019f00002e17000104300000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001ed70000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001ee30000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001eef0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001efb0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f070000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f130000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f1f0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f2b0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f370000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f430000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f4f0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f5b0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f670000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f730000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f7f0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f8b0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f970000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001fa30000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001faf0000c13d000006630000013d00000000430104340000000001320436000000000003004b00001fc00000613d000000000200001900000000051200190000000006240019000000000606043300000000006504350000002002200039000000000032004b00001fb90000413d000000000213001900000000000204350000001f0230003900000bff022001970000000001210019000000000001042d000000004301043400000baa03300197000000000332043600000000040404330000000000430435000000400310003900000000030304330000004004200039000000000034043500000060031000390000000003030433000000600420003900000000003404350000008003100039000000000303043300000080042000390000000000340435000000a0031000390000000003030433000000a0042000390000000000340435000000c0031000390000000003030433000000c0042000390000000000340435000000e0031000390000000003030433000000e004200039000000000034043500000100031000390000000003030433000001000420003900000000003404350000012003100039000000000303043300000120042000390000000000340435000001400310003900000000030304330000014004200039000000000034043500000160031000390000000003030433000000000003004b0000000003000039000000010300c039000001600420003900000000003404350000018003100039000000000303043300000180042000390000000000340435000001a003100039000000000303043300000baa03300197000001a0042000390000000000340435000001c0031000390000000003030433000001c0042000390000000000340435000001e0031000390000000003030433000001e00420003900000000003404350000020002200039000002000110003900000000010104330000000000120435000000000001042d0000000053010434000001a0040000390000000006420436000001a00420003900000000730304340000000000340435000001c004200039000000000003004b0000201d0000613d00000000080000190000000009480019000000000a870019000000000a0a04330000000000a904350000002008800039000000000038004b000020160000413d00000000074300190000000000070435000000000505043300000baa0550019700000000005604350000004005100039000000000505043300000baa0550019700000040062000390000000000560435000000600510003900000000050504330000006006200039000000000056043500000080051000390000000005050433000000800620003900000000005604350000001f0530003900000bff0550019700000000044500190000000005240049000000a006200039000000a0071000390000000007070433000000000056043500000000650704340000000004540436000000000005004b000020430000613d000000000700001900000000084700190000000009760019000000000909043300000000009804350000002007700039000000000057004b0000203c0000413d000000000645001900000000000604350000001f0550003900000bff055001970000000004450019000000c00510003900000000050504330000000006240049000000c007200039000000000067043500000000650504340000000004540436000000000005004b000020590000613d000000000700001900000000084700190000000009760019000000000909043300000000009804350000002007700039000000000057004b000020520000413d000000000645001900000000000604350000001f0550003900000bff055001970000000004450019000000e00510003900000000050504330000000006240049000000e007200039000000000067043500000000650504340000000004540436000000000005004b0000206f0000613d000000000700001900000000084700190000000009760019000000000909043300000000009804350000002007700039000000000057004b000020680000413d000000000645001900000000000604350000010006100039000000000606043300000baa06600197000001000720003900000000006704350000012006100039000000000606043300000120072000390000000000670435000001400610003900000000060604330000014007200039000000000067043500000160061000390000000006060433000001600720003900000000006704350000001f0550003900000bff0350019700000000044300190000000003240049000001800520003900000180011000390000000002010433000000000035043500000000030204330000000001340436000000000003004b000020da0000613d000000000400001900000020022000390000000005020433000000007605043400000baa06600197000000000661043600000000070704330000000000760435000000400650003900000000060604330000004007100039000000000067043500000060065000390000000006060433000000600710003900000000006704350000008006500039000000000606043300000080071000390000000000670435000000a0065000390000000006060433000000a0071000390000000000670435000000c0065000390000000006060433000000c0071000390000000000670435000000e0065000390000000006060433000000e007100039000000000067043500000100065000390000000006060433000001000710003900000000006704350000012006500039000000000606043300000120071000390000000000670435000001400650003900000000060604330000014007100039000000000067043500000160065000390000000006060433000000000006004b0000000006000039000000010600c039000001600710003900000000006704350000018006500039000000000606043300000180071000390000000000670435000001a006500039000000000606043300000baa06600197000001a0071000390000000000670435000001c0065000390000000006060433000001c0071000390000000000670435000001e0065000390000000006060433000001e0071000390000000000670435000002000550003900000000050504330000020006100039000000000056043500000220011000390000000104400039000000000034004b0000208f0000413d000000000001042d000000003101043400000baa01100197000000000112043600000000020304330000000000210435000000000001042d000000004301043400000baa03300197000000000332043600000000040404330000000000430435000000400310003900000000030304330000004004200039000000000034043500000060031000390000000003030433000000600420003900000000003404350000008003100039000000000303043300000080042000390000000000340435000000a002200039000000a00110003900000000010104330000000000120435000000000001042d000d000000000002000600000002001d000400000001001d000000400100043d00000c000010009c0000242b0000813d000001a002100039000000400020043f000001800210003900000060030000390000000000320435000000e0021000390000000000320435000000c0021000390000000000320435000000a0021000390000000000320435000000000231043600000160031000390000000000030435000001400310003900000000000304350000012003100039000000000003043500000100031000390000000000030435000000800310003900000000000304350000006003100039000000000003043500000040011000390000000000010435000000000002043500000006010000290000004001100039000500000001001d0000000002010433000000400900043d00000bbc010000410000000000190435000000000100041400000baa02200197000000040020008c000021260000c13d00000002010003670000000003000031000021390000013d00000b860090009c000d00000009001d00000b86030000410000000003094019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000b8a011001c72e152e100000040f0000000003010019000000600330027000000b860030019d00000b860330019700020000000103550000000100200190000024330000613d0000000d0900002900000bff043001980000001f0530018f0000000002490019000021430000613d000000000601034f0000000007090019000000006806043c0000000007870436000000000027004b0000213f0000c13d000000000005004b000021500000613d000000000141034f0000000304500210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001204350000001f0130003900000bff011001970000000002910019000000000012004b00000000010000390000000101004039000900000002001d00000ba70020009c0000242b0000213d00000001001001900000242b0000c13d0000000901000029000000400010043f00000bad0030009c000024310000213d0000001f0030008c000024310000a13d000000000109043300000ba70010009c000024310000213d000000000293001900000000019100190000001f03100039000000000023004b000000000400001900000bae0400804100000bae0330019700000bae05200197000000000653013f000000000053004b000000000300001900000bae0300404100000bae0060009c000000000304c019000000000003004b000024310000c13d0000000013010434000a00000003001d00000ba70030009c0000242b0000213d0000000a0300002900000005033002100000003f0430003900000ba804400197000000090440002900000ba70040009c0000242b0000213d000000400040043f00000009040000290000000a050000290000000004540436000800000004001d0000000003130019000000000023004b000024310000213d000000000031004b000021960000813d0000000902000029000000001401043400000baa0040009c000024310000213d00000020022000390000000000420435000000000031004b0000218a0000413d00000009010000290000000001010433000a00000001001d00000ba70010009c0000242b0000213d0000000a0100002900000005011002100000003f0210003900000ba802200197000000400300043d0000000002230019000d00000003001d000000000032004b0000000003000039000000010300403900000ba70020009c0000242b0000213d00000001003001900000242b0000c13d000000400020043f0000000d020000290000000a030000290000000005320436000000000003004b000021f20000613d0000000002000019000000400300043d00000beb0030009c0000242b0000213d0000022004300039000000400040043f00000200043000390000000000040435000001e0043000390000000000040435000001c0043000390000000000040435000001a00430003900000000000404350000018004300039000000000004043500000160043000390000000000040435000001400430003900000000000404350000012004300039000000000004043500000100043000390000000000040435000000e0043000390000000000040435000000c0043000390000000000040435000000a0043000390000000000040435000000800430003900000000000404350000006004300039000000000004043500000040043000390000000000040435000000200430003900000000000404350000000000030435000000000452001900000000003404350000002002200039000000000012004b000021ab0000413d0000000003000019000700000005001d00000009010000290000000001010433000000000031004b000024250000a13d0000000502300210000b00000002001d0000000801200029000000000101043300000baa01100197000c00000003001d2e1525b60000040f0000000c0300002900000007050000290000000d020000290000000002020433000000000032004b000024250000a13d0000000b0250002900000000001204350000000d010000290000000001010433000000000031004b000024250000a13d00000001033000390000000a0030006c000021d80000413d00000005010000290000000001010433000000400900043d00000bf802000041000000000029043500000baa01100197000000040290003900000000001204350000000001000414000000040200002900000baa02200197000000040020008c000022020000c13d00000002010003670000000003000031000022150000013d00000b860090009c000c00000009001d00000b86030000410000000003094019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000bb6011001c72e152e100000040f0000000003010019000000600330027000000b860030019d00000b8603300197000200000001035500000001002001900000243f0000613d0000000c0900002900000bff043001980000001f0530018f00000000024900190000221f0000613d000000000601034f0000000007090019000000006806043c0000000007870436000000000027004b0000221b0000c13d000000000005004b0000222c0000613d000000000141034f0000000304500210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001204350000001f0130003900000bff021001970000000001920019000000000021004b0000000002000039000000010200403900000ba70010009c0000242b0000213d00000001002001900000242b0000c13d000000400010043f00000bad0030009c000024310000213d000000200030008c000024310000413d000000000409043300000ba70040009c000024310000213d00000000029300190000000004940019000000000542004900000bad0050009c000024310000213d000000600050008c000024310000413d00000bc30010009c0000242b0000213d0000006005100039000000400050043f000000007604043400000ba70060009c000024310000213d00000000084600190000001f06800039000000000026004b000000000900001900000bae0900804100000bae0a60019700000bae06200197000000000b6a013f00000000006a004b000000000a00001900000bae0a00404100000bae00b0009c000000000a09c01900000000000a004b000024310000c13d000000009808043400000ba70080009c0000242b0000213d0000001f0a80003900000bff0aa001970000003f0aa0003900000bff0aa00197000000000a5a001900000ba700a0009c0000242b0000213d0000004000a0043f0000000000850435000000000a98001900000000002a004b000024310000213d000000800a100039000000000008004b000022750000613d000000000b000019000000000cab0019000000000d9b0019000000000d0d04330000000000dc0435000000200bb0003900000000008b004b0000226e0000413d0000000008a8001900000000000804350000000005510436000000000707043300000ba70070009c000024310000213d00000000074700190000001f08700039000000000028004b000000000900001900000bae0900804100000bae08800197000000000a68013f000000000068004b000000000800001900000bae0800404100000bae00a0009c000000000809c019000000000008004b000024310000c13d000000008707043400000ba70070009c0000242b0000213d0000001f0970003900000bff099001970000003f0990003900000bff0a900197000000400900043d000000000aa9001900000000009a004b000000000b000039000000010b00403900000ba700a0009c0000242b0000213d0000000100b001900000242b0000c13d0000004000a0043f000000000a790436000000000b87001900000000002b004b000024310000213d000000000007004b000022a80000613d000000000b000019000000000cab0019000000000d8b0019000000000d0d04330000000000dc0435000000200bb0003900000000007b004b000022a10000413d00000000077a0019000000000007043500000000009504350000004007400039000000000707043300000ba70070009c000024310000213d00000000044700190000001f07400039000000000027004b000000000800001900000bae0800804100000bae07700197000000000967013f000000000067004b000000000600001900000bae0600404100000bae0090009c000000000608c019000000000006004b000024310000c13d000000006404043400000ba70040009c0000242b0000213d0000001f0740003900000bff077001970000003f0770003900000bff07700197000000400a00043d00000000077a00190000000000a7004b0000000008000039000000010800403900000ba70070009c0000242b0000213d00000001008001900000242b0000c13d000000400070043f00000000074a04360000000008640019000000000028004b000024310000213d000000000004004b000c0000000a001d000022dd0000613d000000000200001900000000087200190000000009620019000000000909043300000000009804350000002002200039000000000042004b000022d60000413d0000000002470019000000000002043500000040021000390000000000a204350000000001010433000800000001001d0000000001050433000300000001001d000000060200002900000080012000390000000001010433000400000001001d00000060012000390000000001010433000700000001001d00000020012000390000000001010433000900000001001d0000000001020433000a00000001001d00000005010000290000000002010433000000400c00043d00000be50100004100000000001c0435000000000100041400000baa05200197000000040050008c000b00000005001d000022ff0000c13d000000200030008c000000200400003900000000040340190000232f0000013d00000b8600c0009c00000b860200004100000000020c4019000000400220021000000b860010009c00000b8601008041000000c001100210000000000121019f00000b8a011001c7000000000205001900060000000c001d2e152e100000040f000000060c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c00190000231c0000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000023180000c13d000000000006004b000023290000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000000c0a0000290000244b0000613d0000000b050000290000001f01400039000000600110018f000000000bc1001900000000001b004b0000000002000039000000010200403900000ba700b0009c0000242b0000213d00000001002001900000242b0000c13d0000004000b0043f000000200030008c000024310000413d00000000020c0433000600000002001d00000baa0020009c000024310000213d00000bf90200004100000000002b04350000000002000414000000040050008c000023770000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c7000000000205001900050000000b001d2e152e100000040f000000050b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000023620000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000235e0000c13d000000000006004b0000236f0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000000c0a000029000024570000613d0000001f01400039000000600110018f0000000b05000029000000000cb1001900000ba700c0009c0000242b0000213d0000004000c0043f000000200030008c000024310000413d00000000020b0433000500000002001d00000bfa0200004100000000002c04350000000002000414000000040050008c000023b60000613d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c7000000000205001900020000000c001d2e152e100000040f000000020c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000023a10000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b0000239d0000c13d000000000006004b000023ae0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000000c0a000029000024630000613d0000001f01400039000000600110018f0000000b05000029000000000bc1001900000ba700b0009c0000242b0000213d0000004000b0043f000000200030008c000024310000413d00000000060c043300000bfb0200004100000000002b04350000000002000414000000040050008c000023f60000613d000100000006001d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c7000000000205001900020000000b001d2e152e100000040f000000020b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000023e00000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000023dc0000c13d000000000006004b000023ed0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000000c0a0000290000246f0000613d0000001f01400039000000600110018f0000000b0500002900000001060000290000000001b1001900000ba70010009c0000242b0000213d000000400010043f000000200030008c000024310000413d00000bea0010009c0000242b0000213d00000000020b0433000001a003100039000000400030043f00000180031000390000000d0400002900000000004304350000016003100039000000000023043500000140021000390000000000620435000001200210003900000005030000290000000000320435000001000210003900000006030000290000000000320435000000e0021000390000000000a20435000000c00210003900000003030000290000000000320435000000a0021000390000000803000029000000000032043500000080021000390000000403000029000000000032043500000060021000390000000703000029000000000032043500000040021000390000000000520435000000090200002900000baa02200197000000200310003900000000002304350000000a020000290000000000210435000000000001042d00000bdc01000041000000000010043f0000003201000039000000040010043f00000bb60100004100002e170001043000000bdc01000041000000000010043f0000004101000039000000040010043f00000bb60100004100002e1700010430000000000100001900002e17000104300000001f0530018f00000b8806300198000000400200043d00000000046200190000247a0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000243a0000c13d0000247a0000013d0000001f0530018f00000b8806300198000000400200043d00000000046200190000247a0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000024460000c13d0000247a0000013d0000001f0530018f00000b8806300198000000400200043d00000000046200190000247a0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000024520000c13d0000247a0000013d0000001f0530018f00000b8806300198000000400200043d00000000046200190000247a0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000245e0000c13d0000247a0000013d0000001f0530018f00000b8806300198000000400200043d00000000046200190000247a0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000246a0000c13d0000247a0000013d0000001f0530018f00000b8806300198000000400200043d00000000046200190000247a0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000024760000c13d000000000005004b000024870000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000b860020009c00000b86020080410000004002200210000000000121019f00002e17000104300002000000000002000000400200043d00000c010020009c000025680000813d0000004003200039000000400030043f00000020032000390000000000030435000000000002043500000bed02000041000000400c00043d00000000002c0435000000000200041400000baa05100197000000040050008c000200000005001d000024a30000c13d0000000003000031000000200030008c00000020040000390000000004034019000024d20000013d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c7000000000205001900010000000c001d2e152e100000040f000000010c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000024c00000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000024bc0000c13d000000000006004b000024cd0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000256e0000613d00000002050000290000001f01400039000000600110018f000000000bc1001900000000001b004b0000000002000039000000010200403900000ba700b0009c000025680000213d0000000100200190000025680000c13d0000004000b0043f0000001f0030008c000025660000a13d00000000020c043300000baa0020009c000025660000213d00000be50400004100000000004b04350000000004000414000000040020008c000025170000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c700010000000b001d2e152e100000040f000000010b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000025030000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000024ff0000c13d000000000006004b000025100000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000258c0000613d0000001f01400039000000600110018f0000000205000029000000000cb1001900000ba700c0009c000025680000213d0000004000c0043f000000200030008c000025660000413d00000000020b043300000baa0020009c000025660000213d00000be70400004100000000004c04350000000404c0003900000000005404350000000004000414000000040020008c000025570000613d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000bb6011001c700010000000c001d2e152e100000040f000000010c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000025430000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b0000253f0000c13d000000000006004b000025500000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000025980000613d0000001f01400039000000600110018f00000002050000290000000001c1001900000ba70010009c000025680000213d000000400010043f000000200030008c000025660000413d00000bc20010009c000025680000213d00000000020c04330000004003100039000000400030043f000000200310003900000000002304350000000000510435000000000001042d000000000100001900002e170001043000000bdc01000041000000000010043f0000004101000039000000040010043f00000bb60100004100002e17000104300000001f0530018f00000b8806300198000000400200043d0000000004620019000025790000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000025750000c13d000000000005004b000025860000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000b860020009c00000b86020080410000004002200210000000000112019f00002e17000104300000001f0530018f00000b8806300198000000400200043d0000000004620019000025a30000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000025930000c13d000025a30000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000025a30000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000259f0000c13d000000000005004b000025b00000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000b860020009c00000b86020080410000004002200210000000000121019f00002e1700010430000f0000000000020000000005010019000000400100043d00000c020010009c00002a6f0000813d0000022002100039000000400020043f00000200021000390000000000020435000001e0021000390000000000020435000001c0021000390000000000020435000001a00210003900000000000204350000018002100039000000000002043500000160021000390000000000020435000001400210003900000000000204350000012002100039000000000002043500000100021000390000000000020435000000e0021000390000000000020435000000c0021000390000000000020435000000a002100039000000000002043500000080021000390000000000020435000000600210003900000000000204350000004002100039000000000002043500000020021000390000000000020435000000000001043500000baa01000041000001000010043f00000bec01000041000000400b00043d00000000001b0435000001000100043d000000000251016f0000000001000414000000040020008c000c00000005001d000025ee0000c13d0000000003000031000000200030008c000000200400003900000000040340190000261c0000013d00000b8600b0009c00000b860300004100000000030b4019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000b8a011001c7000f0000000b001d2e152e100000040f0000000f0b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b00190000260a0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000026060000c13d000000000006004b000026170000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002a930000613d0000000c050000290000001f01400039000000600110018f000000000cb1001900000000001c004b0000000002000039000000010200403900000ba700c0009c00002a6f0000213d000000010020019000002a6f0000c13d0000004000c0043f0000001f0030008c00002a6d0000a13d00000000020b0433000a00000002001d00000bed0200004100000000002c0435000001000200043d000000000252016f0000000004000414000000040020008c000026620000613d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c7000f0000000c001d2e152e100000040f0000000f0c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c00190000264e0000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b0000264a0000c13d000000000006004b0000265b0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002a9f0000613d0000001f01400039000000600110018f0000000c05000029000000000bc1001900000ba700b0009c00002a6f0000213d0000004000b0043f000000200030008c00002a6d0000413d00000000010c0433000f00000001001d00000baa0010009c00002a6d0000213d00000bee0100004100000000061b0436000001000100043d000000000151016f0000000402b000390000000000120435000001000100043d0000000f0210017f0000000001000414000000040020008c0000267b0000c13d000000400030008c00000040040000390000000004034019000026ab0000013d000d00000006001d00000b8600b0009c00000b860300004100000000030b4019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000bb6011001c7000e0000000b001d2e152e100000040f0000000e0b0000290000000003010019000000600330027000000b8603300197000000400030008c000000400400003900000000040340190000001f0640018f000000600740019000000000057b0019000026980000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000026940000c13d000000000006004b000026a50000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002aab0000613d0000000c050000290000000d060000290000001f01400039000000e00110018f000000000cb1001900000ba700c0009c00002a6f0000213d0000004000c0043f000000400030008c00002a6d0000413d00000000020b0433000000000002004b0000000001000039000000010100c039000900000002001d000000000012004b00002a6d0000c13d0000000001060433000800000001001d00000bb90100004100000000001c0435000001000100043d000000000251016f0000000001000414000000040020008c000026c50000c13d0000002004000039000026f30000013d00000b8600c0009c00000b860300004100000000030c4019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000b8a011001c7000e0000000c001d2e152e100000040f0000000e0c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000026e10000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000026dd0000c13d000000000006004b000026ee0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002ab70000613d0000000c050000290000001f01400039000000600110018f000000000bc1001900000ba700b0009c00002a6f0000213d0000004000b0043f000000200030008c00002a6d0000413d00000000020c0433000b00000002001d00000baa0020009c00002a6d0000213d00000bef0200004100000000002b0435000001000200043d0000000b0220017f0000000004000414000000040020008c000027360000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c7000e0000000b001d2e152e100000040f0000000e0b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000027220000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000271e0000c13d000000000006004b0000272f0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002ac30000613d0000001f01400039000000600110018f0000000c05000029000000000ab10019000000c00000043f00000ba700a0009c00002a6f0000213d0000004000a0043f000000200030008c00002a6d0000413d00000000010b0433000000ff0010008c00002a6d0000213d000000c00010043f000000e00000043f00000bf0060000410000002007000039000000000800001900000000006a04350000002401a00039000001000200043d0000000000810435000000000152016f0000000402a000390000000000120435000001000100043d0000000f0210017f0000000001000414000000040020008c0000000004070019000027830000613d000d00000008001d00000b8600a0009c00000b860300004100000000030a4019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000bbb011001c7000e0000000a001d2e152e100000040f0000000e0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000276e0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b0000276a0000c13d0000001f074001900000277b0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002a750000613d0000000c0500002900000bf00600004100000020070000390000000d080000290000001f01400039000000600110018f000000000ba1001900000000001b004b0000000002000039000000010200403900000ba700b0009c00002a6f0000213d000000010020019000002a6f0000c13d0000004000b0043f000000200030008c00002a6d0000413d00000000020a0433000000000002004b0000000004000039000000010400c039000000000042004b00002a6d0000c13d00000000028201cf000000e00400043d000000000224019f000000e00020043f0000000102800039000000ff0820018f000000080080008c000000000a0b0019000027450000a13d00000bf10200004100000000002b0435000001000200043d000000000252016f0000000004000414000000040020008c000027d60000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c7000e0000000b001d2e152e100000040f0000000e0b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000027c20000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000027be0000c13d000000000006004b000027cf0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002acf0000613d0000001f01400039000000600110018f0000000c05000029000000000cb1001900000ba700c0009c00002a6f0000213d0000004000c0043f000000200030008c00002a6d0000413d00000000020b0433000e00000002001d00000bf20200004100000000002c0435000001000200043d000000000252016f0000000004000414000000040020008c000028150000613d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c7000d0000000c001d2e152e100000040f0000000d0c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000028010000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000027fd0000c13d000000000006004b0000280e0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002adb0000613d0000001f01400039000000600110018f0000000c05000029000000000dc1001900000ba700d0009c00002a6f0000213d0000004000d0043f000000200030008c00002a6d0000413d00000000020c0433000d00000002001d00000bf30200004100000000002d0435000001000200043d000000000252016f0000000004000414000000040020008c000028540000613d00000b8600d0009c00000b860100004100000000010d4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c700070000000d001d2e152e100000040f000000070d0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057d0019000028400000613d000000000801034f00000000090d0019000000008a08043c0000000009a90436000000000059004b0000283c0000c13d000000000006004b0000284d0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002ae70000613d0000001f01400039000000600110018f0000000c05000029000000000bd1001900000ba700b0009c00002a6f0000213d0000004000b0043f000000200030008c00002a6d0000413d00000000020d0433000700000002001d00000bf40200004100000000002b0435000001000200043d000000000252016f0000000404b000390000000000240435000001000200043d0000000f0220017f0000000004000414000000040020008c000028970000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000bb6011001c700060000000b001d2e152e100000040f000000060b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000028830000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000287f0000c13d000000000006004b000028900000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002af30000613d0000001f01400039000000600110018f0000000c05000029000000000cb1001900000ba700c0009c00002a6f0000213d0000004000c0043f000000200030008c00002a6d0000413d00000000020b0433000600000002001d00000bf50200004100000000002c0435000001000200043d000000000252016f0000000404c000390000000000240435000001000200043d0000000f0220017f0000000004000414000000040020008c000028da0000613d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000bb6011001c7000f0000000c001d2e152e100000040f0000000f0c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000028c60000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000028c20000c13d000000000006004b000028d30000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002aff0000613d0000001f01400039000000600110018f0000000c05000029000000000bc1001900000ba700b0009c00002a6f0000213d0000004000b0043f000000200030008c00002a6d0000413d00000000020c0433000f00000002001d00000bd00200004100000000002b0435000001000200043d000000000252016f0000000004000414000000040020008c000029190000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c700050000000b001d2e152e100000040f000000050b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000029050000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000029010000c13d000000000006004b000029120000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002b0b0000613d0000001f01400039000000600110018f0000000c05000029000000000cb1001900000ba700c0009c00002a6f0000213d0000004000c0043f000000200030008c00002a6d0000413d00000000020b0433000500000002001d00000bf60200004100000000002c0435000001000200043d000000000252016f0000000004000414000000040020008c000029580000613d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c700040000000c001d2e152e100000040f000000040c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000029440000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000029400000c13d000000000006004b000029510000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002b170000613d0000001f01400039000000600110018f0000000c05000029000000000bc1001900000ba700b0009c00002a6f0000213d0000004000b0043f000000200030008c00002a6d0000413d00000000020c0433000400000002001d00000bd70200004100000000002b0435000001000200043d000000000252016f0000000004000414000000040020008c000029970000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c700030000000b001d2e152e100000040f000000030b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000029830000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000297f0000c13d000000000006004b000029900000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002b230000613d0000001f01400039000000600110018f0000000c05000029000000000cb1001900000ba700c0009c00002a6f0000213d0000004000c0043f000000200030008c00002a6d0000413d00000000020b0433000300000002001d00000bf70200004100000000002c0435000001000200043d000000000252016f0000000004000414000000040020008c000029d60000613d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c700020000000c001d2e152e100000040f000000020c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000029c20000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000029be0000c13d000000000006004b000029cf0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002b2f0000613d0000001f01400039000000600110018f0000000c05000029000000000bc1001900000ba700b0009c00002a6f0000213d0000004000b0043f000000200030008c00002a6d0000413d00000000060c043300000bef0200004100000000002b0435000001000200043d000000000252016f0000000004000414000000040020008c00002a160000613d000100000006001d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c700020000000b001d2e152e100000040f000000020b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900002a010000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000029fd0000c13d000000000006004b00002a0e0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002b3b0000613d0000001f01400039000000600110018f0000000c0500002900000001060000290000000001b10019000000800000043f00000ba70010009c00002a6f0000213d000000400010043f000000200030008c00002a6d0000413d00000000020b0433000000ff0020008c00002a6d0000213d000000800020043f000000a00010043f00000beb0010009c00002a6f0000213d0000022002100039000000400020043f000001000200043d000000000252016f0000000000210435000000a00100043d00000020011000390000000a020000290000000000210435000000a00100043d00000040011000390000000e020000290000000000210435000000a00100043d00000060011000390000000d020000290000000000210435000000a00100043d000000800110003900000007020000290000000000210435000000a00100043d000000a00110003900000006020000290000000000210435000000a00100043d000000c0011000390000000f020000290000000000210435000000a00100043d000000e00110003900000005020000290000000000210435000000a00100043d000001000110003900000004020000290000000000210435000000a00100043d000001200110003900000003020000290000000000210435000000a00100043d00000140011000390000000000610435000000a00100043d000001600110003900000009020000290000000000210435000000a00100043d000001800110003900000008020000290000000000210435000001000100043d0000000b0110017f000000a00200043d000001a0022000390000000000120435000000800100043d000000ff0110018f000000a00200043d000001c0022000390000000000120435000000c00100043d000000ff0110018f000000a00200043d000001e0022000390000000000120435000000a00100043d0000020001100039000000e00200043d0000000000210435000000a00100043d000000000001042d000000000100001900002e170001043000000bdc01000041000000000010043f0000004101000039000000040010043f00000bb60100004100002e17000104300000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002a7c0000c13d000000000005004b00002a8d0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000b860020009c00000b86020080410000004002200210000000000121019f00002e17000104300000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002a9a0000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002aa60000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002ab20000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002abe0000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002aca0000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002ad60000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002ae20000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002aee0000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002afa0000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002b060000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002b120000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002b1e0000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002b2a0000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002b360000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002b420000c13d00002a800000013d0007000000000002000000400300043d00000c030030009c00002cff0000813d000000c004300039000000400040043f000000a004300039000000000004043500000080043000390000000000040435000000600430003900000000000404350000004004300039000000000004043500000020043000390000000000040435000000000003043500000bb503000041000000400c00043d00000000003c043500000baa032001970000000402c00039000700000003001d0000000000320435000000000200041400000baa05100197000000040050008c000600000005001d00002b690000c13d0000000003000031000000200030008c0000002004000039000000000403401900002b980000013d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bb6011001c7000000000205001900050000000c001d2e152e100000040f000000050c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c001900002b860000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b00002b820000c13d000000000006004b00002b930000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002d070000613d00000006050000290000001f01400039000000600110018f000000000bc1001900000000001b004b0000000002000039000000010200403900000ba700b0009c00002cff0000213d000000010020019000002cff0000c13d0000004000b0043f0000001f0030008c00002d050000a13d00000000020c0433000500000002001d00000bb70200004100000000002b04350000000402b00039000000070400002900000000004204350000000002000414000000040050008c00002be00000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bb6011001c7000000000205001900040000000b001d2e152e0b0000040f000000040b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900002bcc0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00002bc80000c13d000000000006004b00002bd90000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002d130000613d0000001f01400039000000600110018f0000000605000029000000000cb1001900000ba700c0009c00002cff0000213d0000004000c0043f000000200030008c00002d050000413d00000000020b0433000400000002001d00000bb80200004100000000002c04350000000402c00039000000070400002900000000004204350000000002000414000000040050008c00002c210000613d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bb6011001c7000000000205001900030000000c001d2e152e0b0000040f000000030c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c001900002c0d0000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b00002c090000c13d000000000006004b00002c1a0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002d1f0000613d0000001f01400039000000600110018f0000000605000029000000000bc1001900000ba700b0009c00002cff0000213d0000004000b0043f000000200030008c00002d050000413d00000000020c0433000300000002001d00000bb90200004100000000002b04350000000002000414000000040050008c00002c5f0000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c7000000000205001900020000000b001d2e152e100000040f000000020b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900002c4b0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00002c470000c13d000000000006004b00002c580000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002d2b0000613d0000001f01400039000000600110018f0000000605000029000000000cb1001900000ba700c0009c00002cff0000213d0000004000c0043f000000200030008c00002d050000413d00000000020b043300000baa0020009c00002d050000213d00000bb50400004100000000004c04350000000406c00039000000070400002900000000004604350000000004000414000000040020008c00002ca20000613d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000bb6011001c7000100000002001d00020000000c001d2e152e100000040f000000020c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c001900002c8d0000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b00002c890000c13d000000000006004b00002c9a0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002d370000613d0000001f01400039000000600110018f00000006050000290000000102000029000000000bc1001900000ba700b0009c00002cff0000213d0000004000b0043f000000200030008c00002d050000413d00000000070c04330000002404b00039000000000054043500000bba0400004100000000004b04350000000406b00039000000070400002900000000004604350000000004000414000000040020008c00002ce50000613d000200000007001d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000bbb011001c700070000000b001d2e152e100000040f000000070b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900002cd00000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00002ccc0000c13d000000000006004b00002cdd0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002d430000613d0000001f01400039000000600110018f000000060500002900000002070000290000000001b1001900000ba70010009c00002cff0000213d000000400010043f000000200030008c00002d050000413d00000bb40010009c00002cff0000213d00000000020b0433000000c003100039000000400030043f000000a0031000390000000000230435000000800210003900000000007204350000006002100039000000030300002900000000003204350000004002100039000000040300002900000000003204350000002002100039000000050300002900000000003204350000000000510435000000000001042d00000bdc01000041000000000010043f0000004101000039000000040010043f00000bb60100004100002e1700010430000000000100001900002e17000104300000001f0530018f00000b8806300198000000400200043d000000000462001900002d4e0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d0e0000c13d00002d4e0000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002d4e0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d1a0000c13d00002d4e0000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002d4e0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d260000c13d00002d4e0000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002d4e0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d320000c13d00002d4e0000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002d4e0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d3e0000c13d00002d4e0000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002d4e0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d4a0000c13d000000000005004b00002d5b0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000b860020009c00000b86020080410000004002200210000000000121019f00002e17000104300007000000000002000400000001001d0000000021010434000300000002001d000500000001001d00000bfd0010009c00002dca0000813d000000050100002900000005011002100000003f0210003900000ba802200197000000400500043d0000000002250019000000000052004b0000000003000039000000010300403900000ba70020009c00002dca0000213d000000010030019000002dca0000c13d000000400020043f00000005020000290000000006250436000000000002004b00002dc20000613d0000000002000019000000400300043d00000beb0030009c00002dca0000213d0000022004300039000000400040043f00000200043000390000000000040435000001e0043000390000000000040435000001c0043000390000000000040435000001a00430003900000000000404350000018004300039000000000004043500000160043000390000000000040435000001400430003900000000000404350000012004300039000000000004043500000100043000390000000000040435000000e0043000390000000000040435000000c0043000390000000000040435000000a0043000390000000000040435000000800430003900000000000404350000006004300039000000000004043500000040043000390000000000040435000000200430003900000000000404350000000000030435000000000426001900000000003404350000002002200039000000000012004b00002d7b0000413d0000000003000019000200000005001d000100000006001d00000004010000290000000001010433000000000031004b00002dc40000a13d0000000502300210000600000002001d0000000301200029000000000101043300000baa01100197000700000003001d2e1525b60000040f0000000703000029000000010600002900000002050000290000000002050433000000000032004b00002dc40000a13d000000060260002900000000001204350000000001050433000000000031004b00002dc40000a13d0000000103300039000000050030006c00002da90000413d0000000001050019000000000001042d00000bdc01000041000000000010043f0000003201000039000000040010043f00000bb60100004100002e170001043000000bdc01000041000000000010043f0000004101000039000000040010043f00000bb60100004100002e1700010430000000010010008c00002dd80000613d000000020010008c00002de60000c13d00000bcf010000410000000000100443000000000100041400002ddb0000013d00000bcd010000410000000000100443000000000100041400000b860010009c00000b8601008041000000c00110021000000bce011001c70000800b020000392e152e100000040f000000010020019000002de50000613d000000000101043b000000000001042d000000000001042f00000bdc01000041000000000010043f0000005101000039000000040010043f00000bb60100004100002e1700010430000000000001042f00000000050100190000000000200443000000050030008c00002dfb0000413d000000040100003900000000020000190000000506200210000000000664001900000005066002700000000006060031000000000161043a0000000102200039000000000031004b00002df30000413d00000b860030009c00000b86030080410000006001300210000000000200041400000b860020009c00000b8602008041000000c002200210000000000112019f00000c04011001c700000000020500192e152e100000040f000000010020019000002e0a0000613d000000000101043b000000000001042d000000000001042f00002e0e002104210000000102000039000000000001042d0000000002000019000000000001042d00002e13002104230000000102000039000000000001042d0000000002000019000000000001042d00002e150000043200002e160001042e00002e170001043000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000000ffffffe009c8f7ec0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000001e13380ae0fcab3000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000100000001000000000000000000000000000000000000000000000000000000000000000000000000007c51b64100000000000000000000000000000000000000000000000000000000c7ad089400000000000000000000000000000000000000000000000000000000e0a67f1000000000000000000000000000000000000000000000000000000000e0a67f1100000000000000000000000000000000000000000000000000000000e1d146fb00000000000000000000000000000000000000000000000000000000c7ad089500000000000000000000000000000000000000000000000000000000d77ebf9600000000000000000000000000000000000000000000000000000000aa5dbd2200000000000000000000000000000000000000000000000000000000aa5dbd2300000000000000000000000000000000000000000000000000000000b3124239000000000000000000000000000000000000000000000000000000007c51b642000000000000000000000000000000000000000000000000000000007c84e3b30000000000000000000000000000000000000000000000000000000047d86a80000000000000000000000000000000000000000000000000000000006857249b000000000000000000000000000000000000000000000000000000006857249c000000000000000000000000000000000000000000000000000000007a27db570000000000000000000000000000000000000000000000000000000047d86a810000000000000000000000000000000000000000000000000000000055dd951500000000000000000000000000000000000000000000000000000000345954db00000000000000000000000000000000000000000000000000000000345954dc000000000000000000000000000000000000000000000000000000003e3e399c000000000000000000000000000000000000000000000000000000000d3ae318000000000000000000000000000000000000000000000000000000001f884fdf310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e0000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000000000000000000000000000000000fffffffffffffedf000000000000000000000000fffffffffffffffffffffffffffffffffffffffff36dba380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000012000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000120000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffe1f000000000000000000000000000000000000000000000000ffffffffffffff3f70a0823100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000017bfdfbc000000000000000000000000000000000000000000000000000000003af9e669000000000000000000000000000000000000000000000000000000006f307dc300000000000000000000000000000000000000000000000000000000dd62ed3e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044000000000000000000000000b0772d0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000120000000000000000061252fd100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff7ff7c618c1000000000000000000000000000000000000000000000000000000001627ee8900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffbf000000000000000000000000000000000000000000000000ffffffffffffff9f02000002000000000000000000000000000000440000000000000000000000008f693ec70000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff81814945000000000000000000000000000000000000000000000000000000002c427b570000000000000000000000000000000000000000000000000000000092a1823500000000000000000000000000000000000000000000000000000000aa5af0fd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffdf7c05a7c500000000000000000000000000000000000000000000000000000000796b89b91644bc98cd93958e4c9038275d622183e25ac5af08cc6b5d95539132020000020000000000000000000000000000000400000000000000000000000042cbb15ccdc3cad6266b0e7a08c0454b23bf29dc2df74b6f3c209e9336465bd147bd3718000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000c097ce7bc90715b34b9f10000000006e657720696e646578206f766572666c6f777300000000000000000000000000000000010000000000000000000000000000000000000000000000000000000008c379a00000000000000000000000000000000000000000000000000000000074c4c1cc0000000000000000000000000000000000000000000000000000000018160ddd000000000000000000000000000000000000000000000000000000006dfd08ca00000000000000000000000000000000000000000000000000000000160c3a030000000000000000000000000000000000000000000000000000000095dd919300000000000000000000000000000000000000000000000000000000552c0971000000000000000000000000000000000000000000000000000000004e487b7100000000000000000000000000000000000000000000000000000000266e0a7f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000440000012000000000000000007aee632d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000002c00000000000000000000000000000000000000000000000000000000000000000fffffffffffffd3f000000000000000000000000000000000000000000000000ffffffffffffff5f0000000000000000000000000000000000000004000001800000000000000000000000000000000000000000000000000000000000000000fffffffffffffe7f7dc0d1d000000000000000000000000000000000000000000000000000000000bbcac55700000000000000000000000000000000000000000000000000000000fc57d4df00000000000000000000000000000000000000000000000000000000d88ff1f40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fffffffffffffffe0000000000000000000000000000000000000000000000000fffffffffffffe5f000000000000000000000000000000000000000000000000fffffffffffffddf182df0f5000000000000000000000000000000000000000000000000000000005fe3b567000000000000000000000000000000000000000000000000000000008e8f294b00000000000000000000000000000000000000000000000000000000313ce56700000000000000000000000000000000000000000000000000000000e85a296000000000000000000000000000000000000000000000000000000000ae9d70b000000000000000000000000000000000000000000000000000000000f8f9da2800000000000000000000000000000000000000000000000000000000173b99040000000000000000000000000000000000000000000000000000000002c3bcbb000000000000000000000000000000000000000000000000000000004a584432000000000000000000000000000000000000000000000000000000008f840ddd000000000000000000000000000000000000000000000000000000003b1d21a200000000000000000000000000000000000000000000000000000000a3aefa2c00000000000000000000000000000000000000000000000000000000e8755446000000000000000000000000000000000000000000000000000000004ada90af00000000000000000000000000000000000000000000000000000000db5c65de00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffe9f0000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000fffffffffffffe3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000000000000000000000000000000000fffffffffffffe60000000000000000000000000000000000000000000000000ffffffffffffffc0000000000000000000000000000000000000000000000000fffffffffffffde0000000000000000000000000000000000000000000000000ffffffffffffff4002000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de74f27c00b5ac0ab41c9ffac27b97334e20a0fbe8993556965b047b8b013894", - "deployedBytecode": "0x0003000000000002002e000000000002000000000301034f0000000001030019000000600110027000000b8604100197000200000043035500010000000303550000000100200190000000510000c13d0000012009000039000000400090043f000000040040008c000006070000413d000000000543034f000000000203043b000000e00220027000000b8e0020009c0000007f0000213d00000b9a0020009c0000009a0000213d00000ba00020009c000000d90000213d00000ba30020009c000001650000613d00000ba40020009c000006070000c13d000000240040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000101043b00000ba70010009c000006070000213d0000002302100039000000000042004b000006070000813d0000000402100039000000000223034f000000000202043b001d00000002001d00000ba70020009c000006070000213d001c00240010003d0000001d0100002900000005021002100000001c01200029000000000041004b000006070000213d0000003f0120003900000ba80310019700000ba90030009c000005790000213d0000012001300039000000400010043f0000001d04000029000001200040043f000000000004004b000006470000c13d00000020020000390000000002210436000001200300043d00000000003204350000004002100039000000000003004b000002180000613d000001400400003900000000050000190000000046040434000000007606043400000baa0660019700000000066204360000000007070433000000000076043500000040022000390000000105500039000000000035004b000000460000413d000002180000013d0000000001000416000000000001004b000006070000c13d0000001f0140003900000b8701100197000000e001100039000000400010043f0000001f0240018f00000b8805400198000000e001500039000000620000613d000000e006000039000000000703034f000000007807043c0000000006860436000000000016004b0000005e0000c13d000000000002004b0000006f0000613d000000000353034f0000000302200210000000000501043300000000052501cf000000000525022f000000000303043b0000010002200089000000000323022f00000000022301cf000000000252019f0000000000210435000000400040008c000006070000413d000000e00100043d000000000001004b0000000002000039000000010200c039000000000021004b000006070000c13d000001000200043d000000000001004b000000f60000613d000000000002004b0000014c0000c13d00000b8b020000410000000103000039000001550000013d00000b8f0020009c000000bd0000213d00000b950020009c000000fb0000213d00000b980020009c000001ce0000613d00000b990020009c000006070000c13d000000240040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000101043b00000baa0010009c000006070000213d2e15248d0000040f000000400200043d002000000002001d2e1520db0000040f000000200100002900000b860010009c00000b8601008041000000400110021000000bb2011001c700002e160001042e00000b9b0020009c000001160000213d00000b9e0020009c000002210000613d00000b9f0020009c000006070000c13d000000640040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000201043b00000baa0020009c000006070000213d0000002401300370000000000101043b00000baa0010009c000006070000213d0000004403300370000000000303043b00000baa0030009c000006070000213d00000bdd04000041000001200040043f000001240010043f000001440030043f0000000001000414000000040020008c000005d80000c13d0000000003000031000000200030008c00000020040000390000000004034019000005fe0000013d00000b900020009c000001330000213d00000b930020009c000002490000613d00000b940020009c000006070000c13d000000440040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000201043b00000baa0020009c000006070000213d0000002401300370000000000301043b00000baa0030009c000006070000213d00000bab01000041000001200010043f000001240030043f0000000003000414000000040020008c000000000105034f000003820000c13d00000000030000310000038f0000013d00000ba10020009c0000025c0000613d00000ba20020009c000006070000c13d000000240040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000101043b002000000001001d00000baa0010009c000006070000213d0000018009000039000000400090043f000001200000043f000001400000043f0000006001000039000001600010043f00000bbc01000041000001800010043f00000000030004140000002002000029000000040020008c000000000105034f000003190000c13d0000000003000031000003260000013d000000000002004b000001540000c13d000000400100043d00000b89020000410000014e0000013d00000b960020009c0000026f0000613d00000b970020009c000006070000c13d000000440040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000101043b00000baa0010009c000006070000213d0000002402300370000000000202043b00000baa0020009c000006070000213d2e152b470000040f000000400200043d002000000002001d2e1520e10000040f000000200100002900000b860010009c00000b8601008041000000400110021000000bb0011001c700002e160001042e00000b9c0020009c000002820000613d00000b9d0020009c000006070000c13d000000440040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000101043b002000000001001d00000baa0010009c000006070000213d002a00200000002d0000002401300370000000000101043b001f00000001001d00000baa0010009c000006070000213d00000bbc01000041000001200010043f00000000030004140000001f02000029000000040020008c000000000105034f000003f30000c13d0000000003000031000003ff0000013d00000b910020009c000002920000613d00000b920020009c000006070000c13d0000000001000416000000000001004b000006070000c13d0000000001000412002200000001001d002100400000003d000080050100003900000044030000390000000004000415000000220440008a000000050440021000000ba5020000412e152ded0000040f2e152dd00000040f000000400200043d000000000012043500000b860020009c00000b8602008041000000400120021000000ba6011001c700002e160001042e000000400100043d00000b8c02000041000000000021043500000b860010009c00000b8601008041000000400110021000000b8a011001c700002e17000104300000000203000039000000a00010043f000000800020043f000000c00030043f0000014000000443000001600020044300000020020000390000018000200443000001a0001004430000004001000039000001c000100443000001e00030044300000100002004430000000301000039000001200010044300000b8d0100004100002e160001042e000000440040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000101043b00000baa0010009c000006070000213d0000002402300370000000000602043b00000ba70060009c000006070000213d000000000264004900000bad0020009c000006070000213d000000a40020008c000006070000413d000001c002000039000000400020043f0000000405600039000000000753034f000000000707043b00000ba70070009c000006070000213d00000000076700190000002306700039000000000046004b000006070000813d0000000408700039000000000683034f000000000606043b00000bfd0060009c000005790000813d0000001f0a60003900000bff0aa001970000003f0aa0003900000bff0aa0019700000bfe00a0009c000005790000213d000001c00aa000390000004000a0043f000001c00060043f00000000076700190000002407700039000000000047004b000006070000213d0000002004800039000000000743034f00000bff086001980000001f0960018f000001e004800039000001a00000613d000001e00a000039000000000b07034f00000000bc0b043c000000000aca043600000000004a004b0000019c0000c13d000000000009004b000001ad0000613d000000000787034f0000000308900210000000000904043300000000098901cf000000000989022f000000000707043b0000010008800089000000000787022f00000000078701cf000000000797019f0000000000740435000001e0046000390000000000040435000001200020043f0000002002500039000000000423034f000000000404043b00000baa0040009c000006070000213d000001400040043f0000002002200039000000000423034f000000000404043b00000baa0040009c000006070000213d000001600040043f0000002004200039000000000443034f000000000404043b000001800040043f0000004002200039000000000223034f000000000202043b000001a00020043f00000120020000392e1520f70000040f0000002002000039000000400300043d002000000003001d00000000022304362e15200c0000040f00000020020000290000000001210049000003110000013d000000440040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000101043b00000ba70010009c000006070000213d0000002302100039000000000042004b000006070000813d0000000402100039000000000223034f000000000202043b001900000002001d00000ba70020009c000006070000213d001800240010003d000000190100002900000005021002100000001801200029000000000041004b000006070000213d0000002401300370000000000301043b00000baa0030009c000006070000213d0000003f0120003900000ba80410019700000ba90040009c000005790000213d0000012001400039000000400010043f0000001905000029000001200050043f000000000005004b0000067a0000c13d00000020020000390000000002210436000001200300043d00000000003204350000004002100039000000000003004b000002180000613d0000012004000039000000000500001900000020044000390000000006040433000000008706043400000baa07700197000000000772043600000000080804330000000000870435000000400760003900000000070704330000004008200039000000000078043500000060076000390000000007070433000000600820003900000000007804350000008007600039000000000707043300000080082000390000000000780435000000a0066000390000000006060433000000a0072000390000000000670435000000c0022000390000000105500039000000000035004b000001fd0000413d000000000212004900000b860020009c00000b8602008041000000600220021000000b860010009c00000b86010080410000004001100210000000000112019f00002e160001042e000000440040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000101043b002000000001001d00000baa0010009c000006070000213d0000002401300370000000000201043b00000baa0020009c000006070000213d000002c009000039000000400090043f0000006001000039000001200010043f000001400000043f000001600000043f000001800000043f000001a00000043f000001c00010043f000001e00010043f000002000010043f000002200000043f000002400000043f000002600000043f000002800000043f000002a00010043f00000bdf01000041000002c00010043f000002c40020043f00000000030004140000002002000029000000040020008c000000000105034f000005520000c13d00000000030000310000055f0000013d0000000001000416000000000001004b000006070000c13d0000000001000412002400000001001d002300200000003d000080050100003900000044030000390000000004000415000000240440008a000000050440021000000ba5020000412e152ded0000040f000000000001004b0000000001000039000000010100c039000001200010043f00000baf0100004100002e160001042e0000000002000416000000000002004b000006070000c13d002e00200000003d000000240040008c000006070000413d0000000402300370000000000202043b00000baa0020009c000006070000213d002d00000002001d00000be803000041000001200030043f0000000003000414000000040020008c000000000105034f000004d50000c13d000000000a000031000004e10000013d000000240040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000101043b00000baa0010009c000006070000213d2e1525b60000040f000000400200043d002000000002001d2e151fc60000040f000000200100002900000b860010009c00000b8601008041000000400110021000000bb1011001c700002e160001042e0000000001000416000000000001004b000006070000c13d0000000001000412002c00000001001d002b00000000003d0000800501000039000000440300003900000000040004150000002c0440008a000000050440021000000ba5020000412e152ded0000040f000001200010043f00000baf0100004100002e160001042e000000240040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000101043b00000ba70010009c000006070000213d0000002302100039000000000042004b000006070000813d0000000402100039000000000223034f000000000502043b00000ba70050009c000005790000213d00000005025002100000003f0620003900000ba80660019700000ba90060009c000005790000213d0000012006600039000000400060043f000001200050043f00000024011000390000000002210019000000000042004b000006070000213d000000000005004b000002ba0000613d0000014004000039000000000513034f000000000505043b00000baa0050009c000006070000213d00000000045404360000002001100039000000000021004b000002b20000413d00000120010000392e152d610000040f0000002003000039000000400200043d0000000003320436000000000401043300000000004304350000004003200039000000000004004b000003100000613d000000000500001900000020011000390000000006010433000000008706043400000baa07700197000000000773043600000000080804330000000000870435000000400760003900000000070704330000004008300039000000000078043500000060076000390000000007070433000000600830003900000000007804350000008007600039000000000707043300000080083000390000000000780435000000a0076000390000000007070433000000a0083000390000000000780435000000c0076000390000000007070433000000c0083000390000000000780435000000e0076000390000000007070433000000e008300039000000000078043500000100076000390000000007070433000001000830003900000000007804350000012007600039000000000707043300000120083000390000000000780435000001400760003900000000070704330000014008300039000000000078043500000160076000390000000007070433000000000007004b0000000007000039000000010700c039000001600830003900000000007804350000018007600039000000000707043300000180083000390000000000780435000001a007600039000000000707043300000baa07700197000001a0083000390000000000780435000001c0076000390000000007070433000001c0083000390000000000780435000001e0076000390000000007070433000001e0083000390000000000780435000002000660003900000000060604330000020007300039000000000067043500000220033000390000000105500039000000000045004b000002c50000413d000000000123004900000b860010009c00000b8601008041000000600110021000000b860020009c00000b86020080410000004002200210000000000121019f00002e160001042e00000b860030009c00000b8603008041000000c00130021000000be3011001c72e152e100000040f0000000003010019000000600330027000000b860030019d00000b860330019700020000000103550000000100200190000004c90000613d000001800900003900000bff053001980000001f0630018f00000180045000390000032f0000613d000000000701034f000000007807043c0000000009890436000000000049004b0000032b0000c13d000000000006004b0000033c0000613d000000000151034f0000000305600210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000001f0130003900000bff01100197001e00000001001d00000be40010009c000005790000213d0000001e010000290000018001100039001f00000001001d000000400010043f00000bad0030009c000006070000213d000000200030008c000006070000413d000001800100043d00000ba70010009c000006070000213d00000180023000390000019f04100039000000000024004b000000000500001900000bae0500804100000bae0620019700000bae04400197000000000764013f000000000064004b000000000400001900000bae0400404100000bae0070009c000000000405c019000000000004004b000006070000c13d0000018004100039000000000504043300000ba70050009c000005790000213d00000005045002100000003f0640003900000ba8066001970000001f0660002900000ba70060009c000005790000213d000000400060043f0000001f060000290000000000560435000001a0011000390000000004140019000000000024004b000006070000213d000000000005004b000003760000613d0000001f02000029000000001501043400000baa0050009c000006070000213d00000020022000390000000000520435000000000041004b0000036f0000413d000000400200043d00000be501000041001d00000002001d000000000012043500000000010004140000002002000029000000040020008c000009470000c13d000000200030008c00000020040000390000000004034019000009730000013d00000b860030009c00000b8603008041000000c00130021000000bac011001c72e152e100000040f0000000003010019000000600330027000000b860030019d00000b860330019700020000000103550000000100200190000006090000613d000001200900003900000bff053001980000001f0630018f0000012004500039000003980000613d000000000701034f000000007807043c0000000009890436000000000049004b000003940000c13d000000000006004b000003a50000613d000000000151034f0000000305600210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000001f0130003900000bff0210019700000ba90020009c000005790000213d0000012001200039000000400010043f00000bad0030009c000006070000213d000000200030008c000006070000413d000001200400043d00000ba70040009c000006070000213d00000120033000390000013f05400039000000000035004b000000000600001900000bae0600804100000bae0730019700000bae05500197000000000875013f000000000075004b000000000500001900000bae0500404100000bae0080009c000000000506c019000000000005004b000006070000c13d0000012005400039000000000605043300000ba70060009c000005790000213d00000005056002100000003f0750003900000ba807700197000000000717001900000ba70070009c000005790000213d000000400070043f000000000061043500000140044000390000000005540019000000000035004b000006070000213d0000014002200039000000000006004b000003db0000613d0000000003020019000000004604043400000baa0060009c000006070000213d0000000003630436000000000054004b000003d50000413d000000400300043d00000020040000390000000005430436000000000401043300000000004504350000004001300039000000000004004b000003ea0000613d0000000005000019000000002602043400000baa0660019700000000016104360000000105500039000000000045004b000003e40000413d000000000131004900000b860010009c00000b8601008041000000600110021000000b860030009c00000b86030080410000004002300210000000000121019f00002e160001042e00000b860030009c00000b8603008041000000c00130021000000bbd011001c72e152e100000040f0000000003010019000000600330027000000b860030019d00000b860330019700020000000103550000000100200190000006150000613d00000bff043001980000001f0530018f0000012002400039000004090000613d0000012006000039000000000701034f000000007807043c0000000006860436000000000026004b000004050000c13d000000000005004b000004160000613d000000000641034f0000000304500210000000000502043300000000054501cf000000000545022f000000000606043b0000010004400089000000000646022f00000000044601cf000000000454019f0000000000420435000000000901034f0000001f0130003900000bff0210019700000ba90020009c000005790000213d0000012001200039001e00000001001d000000400010043f00000bad0030009c000006070000213d000000200030008c000006070000413d000001200400043d00000ba70040009c000006070000213d00000120053000390000013f01400039000000000051004b000000000600001900000bae0600804100000bae0750019700000bae01100197000000000871013f000000000071004b000000000100001900000bae0100404100000bae0080009c000000000106c019000000000001004b000006070000c13d0000012001400039000000000701043300000ba70070009c000005790000213d00000005067002100000003f0160003900000ba8011001970000001e0810002900000ba70080009c000005790000213d000000400080043f0000001e01000029000000000071043500000140044000390000000006460019000000000056004b000006070000213d000000000007004b0000044f0000613d0000001e05000029000000004704043400000baa0070009c000006070000213d00000020055000390000000000750435000000000064004b000004480000413d0029001e0000002d00000bbe01000041000000400400043d001d00000004001d000000000014043500000000040004140000001f01000029000000040010008c0000046d0000613d0000001d0100002900000b860010009c00000b8601008041000000400110021000000b860040009c00000b8604008041000000c002400210000000000112019f00000b8a011001c70000001f020000292e152e100000040f0000000003010019000000600330027000000b860030019d00000b8603300197000000000901034f0002000000010355000000010020019000000a3f0000613d0000001f0130003900000b870210019700000bff053001980000001f0630018f0000001d04500029000004770000613d000000000709034f0000001d08000029000000007107043c0000000008180436000000000048004b000004730000c13d000000000006004b000004840000613d000000000159034f0000000305600210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000001d04200029000000000024004b00000000010000390000000101004039001c00000004001d00000ba70040009c000005790000213d0000000100100190000005790000c13d0000001c01000029000000400010043f00000bad0030009c000006070000213d000000200030008c000006070000413d0000001d01000029000000000101043300000ba70010009c000006070000213d0000001d053000290000001d011000290000001f02100039000000000052004b000000000400001900000bae0400804100000bae0220019700000bae06500197000000000762013f000000000062004b000000000200001900000bae0200404100000bae0070009c000000000204c019000000000002004b000006070000c13d000000004201043400000ba70020009c000005790000213d00000005012002100000003f0610003900000ba8066001970000001c0760002900000ba70070009c000005790000213d000000400070043f0000001c0700002900000000002704350000000007140019000000000057004b000006070000213d000000000074004b000014df0000813d0000001c01000029000000004204043400000baa0020009c000006070000213d00000020011000390000000000210435000000000074004b000004b90000413d0000001c010000290000000002010433002800000001001d00000ba70020009c000005790000213d00000005012002100000003f0410003900000ba806400197000014e00000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000004d00000c13d000006630000013d00000b860030009c00000b8603008041000000c00130021000000bbd011001c72e152e100000040f0000000003010019000000600330027000000b860030019d00000b860a30019700020000000103550000000100200190000006210000613d00000bff04a001980000001f05a0018f0000012002400039000004eb0000613d0000012006000039000000000701034f000000007807043c0000000006860436000000000026004b000004e70000c13d000000000005004b000004f80000613d000000000441034f0000000305500210000000000602043300000000065601cf000000000656022f000000000404043b0000010005500089000000000454022f00000000045401cf000000000464019f0000000000420435001e000000010353001f0000000a001d0000001f02a0003900000bff0820019700000ba90080009c000005790000213d0000012001800039000700000001001d000000400010043f0000001f0100002900000bad0010009c000006070000213d0000001f01000029000000200010008c000006070000413d000001200600043d00000ba70060009c000006070000213d0000001f0100002900000120021000390000013f05600039000000000025004b000000000700001900000bae0700804100000bae0420019700000bae05500197000000000945013f000000000045004b000000000500001900000bae0500404100000bae0090009c000000000507c019000000000005004b000006070000c13d0000012001600039000000000901043300000ba70090009c000005790000213d00000005079002100000003f0a70003900000ba80aa00197000000070aa0002900000ba700a0009c000005790000213d0000004000a0043f0000000703000029000000000093043500000140066000390000000007670019000000000027004b000006070000213d000101400080003d000000000009004b000200000000001d000009e50000c13d000000020100002900000005021002100000003f0420003900000be905400197000000400100043d002000000001001d0000000004150019000000000054004b0000000005000039000000010500403900000ba70040009c000005790000213d0000000100500190000005790000c13d000000400040043f000000200100002900000002030000290000000001310436001b00000001001d000000000003004b00000a720000c13d0000002002000039000000400100043d00000000002104350000000004210019000000200300002900000000030304330000000000340435000000400410003900000005053002100000000005450019000000000003004b000012da0000c13d0000000002150049000002190000013d00000b860030009c00000b8603008041000000c00130021000000be0011001c72e152e100000040f0000000003010019000000600330027000000b860030019d00000b8603300197000200000001035500000001002001900000063b0000613d000002c00900003900000bff043001980000001f0630018f000002c002400039000005680000613d000000000701034f000000007807043c0000000009890436000000000029004b000005640000c13d000000000006004b000005750000613d000000000141034f0000000304600210000000000602043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f00000000001204350000001f0130003900000bff0110019700000be10010009c0000057f0000a13d00000bdc01000041000000000010043f0000004101000039000000040010043f00000bb60100004100002e1700010430000002c002100039000000400020043f00000bad0030009c000006070000213d000000200030008c000006070000413d000002c00400043d00000ba70040009c000006070000213d000002c006300039000002c007400039000000000376004900000bad0030009c000006070000213d000000a00030008c000006070000413d00000be20020009c000005790000213d0000036003100039000000400030043f000000000807043300000ba70080009c000006070000213d00000000077800190000001f08700039000000000068004b000000000900001900000bae0900804100000bae0880019700000bae0a600197000000000ba8013f0000000000a8004b000000000800001900000bae0800404100000bae00b0009c000000000809c019000000000008004b000006070000c13d000000008707043400000ba70070009c000005790000213d0000001f0970003900000bff099001970000003f0990003900000bff05900197000000000535001900000ba70050009c000005790000213d000000400050043f00000000007304350000000005870019000000000065004b000006070000213d0000038005100039000000000007004b000005bf0000613d00000000060000190000000009560019000000000a860019000000000a0a04330000000000a904350000002006600039000000000076004b000005b80000413d000000000557001900000000000504350000000000320435000002e003400039000000000303043300000baa0030009c000006070000213d000002e00510003900000000003504350000030003400039000000000303043300000baa0030009c000006070000213d00000300051000390000000000350435000003200340003900000000030304330000032005100039000000000035043500000340011000390000034003400039000000000303043300000000003104350000002001000029000001c50000013d00000b860010009c00000b8601008041000000c00110021000000bde011001c72e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000012005700039000005ed0000613d0000012008000039000000000901034f000000009a09043c0000000008a80436000000000058004b000005e90000c13d000000000006004b000005fa0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000006580000613d0000001f01400039000000600110018f0000012001100039000000400010043f000000200030008c000006070000413d000001200200043d00000baa0020009c000006760000a13d000000000100001900002e17000104300000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000006100000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000061c0000c13d000006630000013d0000001f05a0018f00000b8806a00198000000400200043d00000000046200190000062c0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000006280000c13d000000000005004b000006390000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000006001a00210000006710000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000006420000c13d000006630000013d00000bfc0030009c000005790000213d00000000030000190000004004100039000000400040043f000000200410003900000000000404350000000000010435000001400430003900000000001404350000002003300039000000000023004b000006930000813d000000400100043d00000bc20010009c0000064a0000a13d000005790000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000065f0000c13d000000000005004b000006700000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000b860020009c00000b86020080410000004002200210000000000112019f00002e17000104300000000000210435000000400110021000000ba6011001c700002e160001042e00000bb30040009c000005790000213d0000000004000019000000c005100039000000400050043f000000a0051000390000000000050435000000800510003900000000000504350000006005100039000000000005043500000040051000390000000000050435000000200510003900000000000504350000000000010435000001400540003900000000001504350000002004400039000000000024004b0000077e0000813d000000400100043d00000bb40010009c0000067d0000a13d000005790000013d0000000003000019001f00000003001d0000000502300210001e00000002001d0000001c012000290000000101100367000000000501043b00000baa0050009c000006070000213d000000400100043d00000bc20010009c000005790000213d0000004002100039000000400020043f000000200210003900000000000204350000000000010435000000400b00043d00000bed0100004100000000001b04350000000001000414000000040050008c002000000005001d000006b00000c13d0000000003000031000000200030008c00000020040000390000000004034019000006de0000013d00000b8600b0009c00000b860200004100000000020b4019000000400220021000000b860010009c00000b8601008041000000c001100210000000000121019f00000b8a011001c70000000002050019001b0000000b001d2e152e100000040f0000001b0b0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056b0019000006cc0000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b000006c80000c13d0000001f07400190000006d90000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000000a4e0000613d00000020050000290000001f01400039000000600110018f000000000ab1001900000000001a004b0000000002000039000000010200403900000ba700a0009c000005790000213d0000000100200190000005790000c13d0000004000a0043f000000200030008c000006070000413d00000000020b043300000baa0020009c000006070000213d00000be50400004100000000004a04350000000004000414000000040020008c000007220000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c7001b0000000a001d2e152e100000040f0000001b0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000070e0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b0000070a0000c13d0000001f074001900000071b0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000000a5a0000613d0000001f01400039000000600110018f0000002005000029000000000ba1001900000ba700b0009c000005790000213d0000004000b0043f000000200030008c000006070000413d00000000020a043300000baa0020009c000006070000213d00000be70400004100000000004b04350000000404b0003900000000005404350000000004000414000000040020008c000007610000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000bb6011001c7001b0000000b001d2e152e100000040f0000001b0b0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056b00190000074d0000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b000007490000c13d0000001f074001900000075a0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000000a660000613d0000001f01400039000000600110018f00000020050000290000000001b1001900000ba70010009c000005790000213d000000400010043f000000200030008c000006070000413d00000bc20010009c000005790000213d00000000020b04330000004003100039000000400030043f000000200310003900000000002304350000000000510435000001200200043d0000001f03000029000000000032004b00001d6c0000a13d0000001e0200002900000140022000390000000000120435000001200100043d000000000031004b00001d6c0000a13d00000001033000390000001d0030006c000006940000413d000000400100043d0000003d0000013d00200baa0030019b0000000003000019001e00000003001d0000000502300210001d00000002001d00000018012000290000000101100367000000000501043b00000baa0050009c000006070000213d000000400100043d00000bb40010009c000005790000213d000000c002100039000000400020043f000000a0021000390000000000020435000000800210003900000000000204350000006002100039000000000002043500000040021000390000000000020435000000200210003900000000000204350000000000010435000000400b00043d00000bb50100004100000000001b04350000000401b00039000000200200002900000000002104350000000001000414000000040050008c001f00000005001d000007a70000c13d0000000003000031000000200030008c00000020040000390000000004034019000007d50000013d00000b8600b0009c00000b860200004100000000020b4019000000400220021000000b860010009c00000b8601008041000000c001100210000000000121019f00000bb6011001c70000000002050019001c0000000b001d2e152e100000040f0000001c0b0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056b0019000007c30000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b000007bf0000c13d0000001f07400190000007d00000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000013b50000613d0000001f050000290000001f01400039000000600110018f000000000ab1001900000000001a004b0000000002000039000000010200403900000ba700a0009c000005790000213d0000000100200190000005790000c13d0000004000a0043f000000200030008c000006070000413d00000000020b0433001c00000002001d00000bb70200004100000000002a04350000000402a00039000000200400002900000000004204350000000002000414000000040050008c0000081c0000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bb6011001c70000000002050019001b0000000a001d2e152e0b0000040f0000001b0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000008080000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000008040000c13d0000001f07400190000008150000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000013c10000613d0000001f01400039000000600110018f0000001f05000029000000000ba1001900000ba700b0009c000005790000213d0000004000b0043f000000200030008c000006070000413d00000000020a0433001b00000002001d00000bb80200004100000000002b04350000000402b00039000000200400002900000000004204350000000002000414000000040050008c0000085c0000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bb6011001c70000000002050019001a0000000b001d2e152e0b0000040f0000001a0b0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056b0019000008480000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b000008440000c13d0000001f07400190000008550000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000013cd0000613d0000001f01400039000000600110018f0000001f05000029000000000ab1001900000ba700a0009c000005790000213d0000004000a0043f000000200030008c000006070000413d00000000020b0433001a00000002001d00000bb90200004100000000002a04350000000002000414000000040050008c000008990000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c7000000000205001900170000000a001d2e152e100000040f000000170a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000008850000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000008810000c13d0000001f07400190000008920000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000013d90000613d0000001f01400039000000600110018f0000001f05000029000000000ba1001900000ba700b0009c000005790000213d0000004000b0043f000000200030008c000006070000413d00000000060a043300000baa0060009c000006070000213d00000bb50200004100000000002b04350000000402b00039000000200400002900000000004204350000000002000414000000040060008c000008dc0000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bb6011001c7001600000006001d000000000206001900170000000b001d2e152e100000040f000000170b0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056b0019000008c70000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b000008c30000c13d0000001f07400190000008d40000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000013e50000613d0000001f01400039000000600110018f0000001f050000290000001606000029000000000ab1001900000ba700a0009c000005790000213d0000004000a0043f000000200030008c000006070000413d00000000070b04330000002402a00039000000000052043500000bba0200004100000000002a04350000000402a00039000000200400002900000000004204350000000002000414000000040060008c0000091f0000613d001600000007001d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bbb011001c7000000000206001900170000000a001d2e152e100000040f000000170a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000090a0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000009060000c13d0000001f07400190000009170000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000013f10000613d0000001f01400039000000600110018f0000001f0500002900000016070000290000000001a1001900000ba70010009c000005790000213d000000400010043f000000200030008c000006070000413d00000bb40010009c000005790000213d00000000020a0433000000c003100039000000400030043f000000a00310003900000000002304350000008002100039000000000072043500000060021000390000001a03000029000000000032043500000040021000390000001b03000029000000000032043500000020021000390000001c0300002900000000003204350000000000510435000001200200043d0000001e03000029000000000032004b00001d6c0000a13d0000001d0200002900000140022000390000000000120435000001200100043d000000000031004b00001d6c0000a13d0000000103300039000000190030006c000007800000413d000000400100043d000001f40000013d0000001d0200002900000b860020009c00000b8602008041000000400220021000000b860010009c00000b8601008041000000c001100210000000000121019f00000b8a011001c700000020020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000001d05700029000009620000613d000000000801034f0000001d09000029000000008a08043c0000000009a90436000000000059004b0000095e0000c13d000000000006004b0000096f0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000009d90000613d0000001f01400039000000600210018f0000001d01200029000000000021004b0000000002000039000000010200403900000ba70010009c000005790000213d0000000100200190000005790000c13d000000400010043f000000200030008c000006070000413d0000001d02000029000000000202043300000baa0020009c000006070000213d0000001f04000029000000000604043300000ba70060009c000005790000213d00000005046002100000003f0540003900000ba805500197000000000515001900000ba70050009c000005790000213d000000400050043f0000000005610436000000000006004b000009a00000613d0000000006000019000000400700043d00000bc20070009c000005790000213d0000004008700039000000400080043f000000200870003900000000000804350000000000070435000000000865001900000000007804350000002006600039000000000046004b000009930000413d000000400400043d001400000004001d00000bc30040009c000005790000213d00000014050000290000006004500039000000400040043f0000004004500039001700000004001d000000000014043500000020010000290000000001150436001300000001001d00000000000104350000001f010000290000000001010433000000000001004b001c00000000001d000013fd0000c13d00000013040000290000001c0100002900000000001404350000002002000039000000400100043d00000000022104360000001403000029000000000303043300000baa03300197000000000032043500000000020404330000004003100039000000000023043500000017020000290000000002020433000000600310003900000060040000390000000000430435000000800310003900000000040204330000000000430435000000a003100039000000000004004b000009d70000613d000000000500001900000020022000390000000006020433000000007606043400000baa0660019700000000066304360000000007070433000000000076043500000040033000390000000105500039000000000045004b000009cc0000413d0000000002130049000002190000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000009e00000c13d000006630000013d0000000108000029000000006906043400000ba70090009c000006070000213d0000000009190019000000200c900039000000000ac2004900000bad00a0009c000006070000213d000000a000a0008c000006070000413d000000400a00043d00000be200a0009c000005790000213d000000a00ba000390000004000b0043f000000000d0c043300000ba700d0009c000006070000213d000000000ccd00190000001f0dc0003900000000002d004b000000000e00001900000bae0e00804100000bae0dd00197000000000f4d013f00000000004d004b000000000d00001900000bae0d00404100000bae00f0009c000000000d0ec01900000000000d004b000006070000c13d00000000dc0c043400000ba700c0009c000005790000213d0000001f0ec0003900000bff0ee001970000003f0ee0003900000bff0ee00197000000000ebe001900000ba700e0009c000005790000213d0000004000e0043f0000000000cb0435000000000edc001900000000002e004b000006070000213d000000c00ea0003900000000000c004b00000a200000613d000000000f0000190000000003ef00190000000005df001900000000050504330000000000530435000000200ff000390000000000cf004b00000a190000413d0000000003ec00190000000000030435000000000bba04360000004003900039000000000c03043300000baa00c0009c000006070000213d0000000000cb04350000006003900039000000000b03043300000baa00b0009c000006070000213d0000004003a000390000000000b30435000000800390003900000000030304330000006005a000390000000000350435000000a00390003900000000030304330000008005a0003900000000003504350000000008a80436000000000076004b000009e60000413d00000007010000290000000001010433000200000001001d00000ba70010009c0000052f0000a13d000005790000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900000a4a0000613d000000000709034f0000000008020019000000007107043c0000000008180436000000000048004b00000a460000c13d000000000005004b000006700000613d000000000169034f000006660000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000a550000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000a610000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000a6d0000c13d000006630000013d000000600e00003900000000040000190000001b0d000029000000400500043d00000bea0050009c000005790000213d000001a001500039000000400010043f00000180015000390000000000e10435000000e0015000390000000000e10435000000c0015000390000000000e10435000000a0015000390000000000e104350000000001e504360000016003500039000000000003043500000140035000390000000000030435000001200350003900000000000304350000010003500039000000000003043500000080035000390000000000030435000000600350003900000000000304350000004003500039000000000003043500000000000104350000000001d4001900000000005104350000002004400039000000000024004b00000a750000413d000000000200001900000007010000290000000001010433000800000002001d000000000021004b00001d6c0000a13d000000400200043d00000bea0020009c000005790000213d0005002d0000002d00000008010000290000000503100210000300000003001d00000001013000290000000004010433000001a001200039000000400010043f00000180012000390000000000e10435000000e0012000390000000000e10435000000c0012000390000000000e10435000000a0012000390000000000e104350000000001e20436000001600320003900000000000304350000014003200039000000000003043500000120032000390000000000030435000001000320003900000000000304350000008003200039000000000003043500000060032000390000000000030435000000400220003900000000000204350000000000010435000400000004001d0000004001400039000600000001001d0000000001010433000000400900043d00000bbc020000410000000000290435000000000400041400000baa02100197000000040020008c00000ae10000613d00000b860090009c001d00000009001d00000b86010000410000000001094019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c72e152e100000040f0000000003010019000000600330027000000b860030019d001f0b860030019b001e0000000103530002000000010355000000010020019000001e510000613d0000001b0d000029000000600e0000390000001d090000290000001f0800002900000bff0480019800000000024900190000001e0300035f00000aec0000613d000000000503034f0000000006090019000000005105043c0000000006160436000000000026004b00000ae80000c13d0000001f0580019000000af90000613d000000000143034f0000000303500210000000000402043300000000043401cf000000000434022f000000000101043b0000010003300089000000000131022f00000000013101cf000000000141019f00000000001204350000001f0180003900000bff0110019700000000030900190000000002910019000000000012004b00000000010000390000000101004039000b00000002001d00000ba70020009c000005790000213d0000000100100190000005790000c13d0000000b01000029000000400010043f0000001f0100002900000bad0010009c000006070000213d0000001f01000029000000200010008c000006070000413d000000000103043300000ba70010009c000006070000213d00000000040300190000001f0340002900000000014100190000001f02100039000000000032004b000000000400001900000bae0400804100000bae0220019700000bae05300197000000000652013f000000000052004b000000000200001900000bae0200404100000bae0060009c000000000204c019000000000002004b000006070000c13d0000000021010434000a00000001001d00000ba70010009c000005790000213d0000000a0100002900000005011002100000003f0410003900000ba8054001970000000b0450002900000ba70040009c000005790000213d000000400040043f0000000b040000290000000a060000290000000004640436000900000004001d0000000004210019000000000034004b000006070000213d000000000042004b00000b470000813d0000000b01000029000000002302043400000baa0030009c000006070000213d00000020011000390000000000310435000000000042004b00000b370000413d0000000b010000290000000001010433000a00000001001d00000ba70010009c000005790000213d0000000a0100002900000005011002100000003f0210003900000ba805200197000000400300043d0000000002530019001800000003001d000000000032004b0000000003000039000000010300403900000ba70020009c000005790000213d0000000100300190000005790000c13d000000400020043f00000018020000290000000a030000290000000002320436001700000002001d000000000003004b000010770000613d0000000002000019000000400300043d00000beb0030009c000005790000213d0000022004300039000000400040043f00000200043000390000000000040435000001e0043000390000000000040435000001c0043000390000000000040435000001a00430003900000000000404350000018004300039000000000004043500000160043000390000000000040435000001400430003900000000000404350000012004300039000000000004043500000100043000390000000000040435000000e0043000390000000000040435000000c0043000390000000000040435000000a0043000390000000000040435000000800430003900000000000404350000006004300039000000000004043500000040043000390000000000040435000000200430003900000000000404350000000000030435000000170420002900000000003404350000002002200039000000000012004b00000b590000413d00000000030000190000000b010000290000000001010433000000000031004b00001d6c0000a13d001a00000003001d000000400100043d00000beb0010009c000005790000213d0000001a02000029000000050320021000000009023000290000000002020433001f0baa0020019b0000022002100039000000400020043f00000200021000390000000000020435000001e0021000390000000000020435000001c0021000390000000000020435000001a00210003900000000000204350000018002100039000000000002043500000160021000390000000000020435000001400210003900000000000204350000012002100039000000000002043500000100021000390000000000020435000000e0021000390000000000020435000000c0021000390000000000020435000000a002100039000000000002043500000080021000390000000000020435000000600210003900000000000204350000004002100039000000000002043500000020021000390000000000020435000000000001043500000baa01000041000001000010043f000000400a00043d00000bec0100004100000000001a0435000001000100043d0000001f0210017f0000000001000414000000040020008c001600000003001d00000bc50000c13d0000000003000031000000200030008c0000002004000039000000000403401900000bf30000013d00000b8600a0009c00000b860300004100000000030a4019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000b8a011001c7001e0000000a001d2e152e100000040f0000001e0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000be00000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000bdc0000c13d0000001f0740019000000bed0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001d900000613d0000001f01400039000000600110018f00000000050a00190000000004a10019000000000014004b00000000020000390000000102004039001e00000004001d00000ba70040009c000005790000213d0000000100200190000005790000c13d0000001e02000029000000400020043f000000200030008c000006070000413d0000000002050433001500000002001d00000bed020000410000001e0a00002900000000002a0435000001000200043d0000001f0220017f0000000004000414000000040020008c00000c3c0000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c72e152e100000040f0000001e0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000c270000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000c230000c13d0000001f0740019000000c340000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001d9c0000613d0000001f01400039000000600110018f0000000001a10019001d00000001001d00000ba70010009c000005790000213d0000001d01000029000000400010043f000000200030008c000006070000413d0000001e010000290000000001010433001e00000001001d00000baa0010009c000006070000213d00000bee010000410000001d0a00002900000000041a0436000001000100043d0000001f0110017f0000000402a000390000000000120435000001000100043d0000001e0210017f0000000001000414000000040020008c001900000004001d00000c5a0000c13d000000400030008c0000004004000039000000000403401900000c870000013d00000b8600a0009c00000b860300004100000000030a4019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000bb6011001c72e152e100000040f0000001d0a0000290000000003010019000000600330027000000b8603300197000000400030008c00000040040000390000000004034019000000600640019000000000056a001900000c740000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000c700000c13d0000001f0740019000000c810000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001da80000613d0000001f01400039000000e00110018f0000000001a10019001c00000001001d00000ba70010009c000005790000213d0000001c01000029000000400010043f000000400030008c000006070000413d0000001d010000290000000002010433000000000002004b0000000001000039000000010100c039001400000002001d000000000012004b000006070000c13d00000019010000290000000001010433001300000001001d00000bb9010000410000001c0a00002900000000001a0435000001000100043d0000001f0210017f0000000001000414000000040020008c000000200400003900000cd20000613d00000b8600a0009c00000b860300004100000000030a4019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000b8a011001c72e152e100000040f0000001c0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000cbf0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000cbb0000c13d0000001f0740019000000ccc0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001db40000613d0000001f01400039000000600110018f0000000002a10019001d00000002001d00000ba70020009c000005790000213d0000001d02000029000000400020043f000000200030008c000006070000413d0000001c020000290000000002020433001900000002001d00000baa0020009c000006070000213d00000bef020000410000001d0a00002900000000002a0435000001000200043d000000190220017f0000000004000414000000040020008c00000d180000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c72e152e100000040f0000001d0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000d030000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000cff0000c13d0000001f0740019000000d100000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001dc00000613d0000001f01400039000000600110018f000000000aa10019000000c00000043f00000ba700a0009c000005790000213d0000004000a0043f000000200030008c000006070000413d0000001d010000290000000001010433000000ff0010008c000006070000213d000000c00010043f000000e00000043f000000000500001900000bf00100004100000000001a04350000002401a00039000001000200043d00000000005104350000001f0120017f0000000402a000390000000000120435000001000100043d0000001e0210017f0000000001000414000000040020008c000000200400003900000d640000613d001c00000005001d00000b8600a0009c00000b860300004100000000030a4019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000bbb011001c7001d0000000a001d2e152e100000040f0000001d0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000d500000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000d4c0000c13d0000001f0740019000000d5d0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e000039000014d30000613d0000001c050000290000001f01400039000000600110018f000000000ba1001900000000001b004b0000000002000039000000010200403900000ba700b0009c000005790000213d0000000100200190000005790000c13d0000004000b0043f000000200030008c000006070000413d00000000020a0433000000000002004b0000000004000039000000010400c039000000000042004b000006070000c13d00000000025201cf000000e00400043d000000000224019f000000e00020043f0000000102500039000000ff0520018f000000080050008c000000000a0b001900000d260000a13d00000bf10200004100000000002b0435000001000200043d0000001f0220017f0000000004000414000000040020008c00000db70000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c7001d0000000b001d2e152e100000040f0000001d0b0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056b001900000da20000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b00000d9e0000c13d0000001f0740019000000daf0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001dcc0000613d0000001f01400039000000600110018f0000000002b10019001d00000002001d00000ba70020009c000005790000213d0000001d02000029000000400020043f000000200030008c000006070000413d00000000020b0433001200000002001d00000bf2020000410000001d0a00002900000000002a0435000001000200043d0000001f0220017f0000000004000414000000040020008c00000df80000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c72e152e100000040f0000001d0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000de30000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000ddf0000c13d0000001f0740019000000df00000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001dd80000613d0000001f01400039000000600110018f0000000002a10019001c00000002001d00000ba70020009c000005790000213d0000001c02000029000000400020043f000000200030008c000006070000413d0000001d020000290000000002020433001100000002001d00000bf3020000410000001c0a00002900000000002a0435000001000200043d0000001f0220017f0000000004000414000000040020008c00000e3a0000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c72e152e100000040f0000001c0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000e250000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000e210000c13d0000001f0740019000000e320000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001de40000613d0000001f01400039000000600110018f0000000002a10019001d00000002001d00000ba70020009c000005790000213d0000001d02000029000000400020043f000000200030008c000006070000413d0000001c020000290000000002020433001000000002001d00000bf4020000410000001d0a00002900000000002a0435000001000200043d0000001f0220017f0000000404a000390000000000240435000001000200043d0000001e0220017f0000000004000414000000040020008c00000e800000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000bb6011001c72e152e100000040f0000001d0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000e6b0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000e670000c13d0000001f0740019000000e780000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001df00000613d0000001f01400039000000600110018f0000000002a10019001c00000002001d00000ba70020009c000005790000213d0000001c02000029000000400020043f000000200030008c000006070000413d0000001d020000290000000002020433000f00000002001d00000bf5020000410000001c0a00002900000000002a0435000001000200043d0000001f0220017f0000000404a000390000000000240435000001000200043d0000001e0220017f0000000004000414000000040020008c00000ec60000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000bb6011001c72e152e100000040f0000001c0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000eb10000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000ead0000c13d0000001f0740019000000ebe0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001dfc0000613d0000001f01400039000000600110018f0000000002a10019001e00000002001d00000ba70020009c000005790000213d0000001e02000029000000400020043f000000200030008c000006070000413d0000001c020000290000000002020433001c00000002001d00000bd0020000410000001e0a00002900000000002a0435000001000200043d0000001f0220017f0000000004000414000000040020008c00000f080000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c72e152e100000040f0000001e0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000ef30000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000eef0000c13d0000001f0740019000000f000000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001e080000613d0000001f01400039000000600110018f0000000002a10019001d00000002001d00000ba70020009c000005790000213d0000001d02000029000000400020043f000000200030008c000006070000413d0000001e020000290000000002020433000e00000002001d00000bf6020000410000001d0a00002900000000002a0435000001000200043d0000001f0220017f0000000004000414000000040020008c00000f4a0000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c72e152e100000040f0000001d0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000f350000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000f310000c13d0000001f0740019000000f420000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001e140000613d0000001f01400039000000600110018f0000000002a10019001e00000002001d00000ba70020009c000005790000213d0000001e02000029000000400020043f000000200030008c000006070000413d0000001d020000290000000002020433000d00000002001d00000bd7020000410000001e0a00002900000000002a0435000001000200043d0000001f0220017f0000000004000414000000040020008c00000f8c0000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c72e152e100000040f0000001e0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000f770000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000f730000c13d0000001f0740019000000f840000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001e200000613d0000001f01400039000000600110018f0000000002a10019001d00000002001d00000ba70020009c000005790000213d0000001d02000029000000400020043f000000200030008c000006070000413d0000001e020000290000000002020433000c00000002001d00000bf7020000410000001d0a00002900000000002a0435000001000200043d0000001f0220017f0000000004000414000000040020008c00000fce0000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c72e152e100000040f0000001d0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000fb90000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000fb50000c13d0000001f0740019000000fc60000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001e2c0000613d0000001f01400039000000600110018f0000000002a10019001e00000002001d00000ba70020009c000005790000213d0000001e02000029000000400020043f000000200030008c000006070000413d0000001d020000290000000002020433001d00000002001d00000bef020000410000001e0a00002900000000002a0435000001000200043d0000001f0220017f0000000004000414000000040020008c000010100000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c72e152e100000040f0000001e0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000ffb0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000ff70000c13d0000001f07400190000010080000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001e380000613d0000001f01400039000000600110018f0000000001a10019000000800000043f00000ba70010009c000005790000213d000000400010043f000000200030008c000006070000413d0000001e020000290000000002020433000000ff0020008c000006070000213d000000800020043f000000a00010043f00000beb0010009c000005790000213d0000022002100039000000400020043f000001000200043d0000001f0220017f0000000000210435000000a00100043d000000200110003900000015020000290000000000210435000000a00100043d000000400110003900000012020000290000000000210435000000a00100043d000000600110003900000011020000290000000000210435000000a00100043d000000800110003900000010020000290000000000210435000000a00100043d000000a0011000390000000f020000290000000000210435000000a00100043d000000c0011000390000001c020000290000000000210435000000a00100043d000000e0011000390000000e020000290000000000210435000000a00100043d00000100011000390000000d020000290000000000210435000000a00100043d00000120011000390000000c020000290000000000210435000000a00100043d00000140011000390000001d020000290000000000210435000000a00100043d000001600110003900000014020000290000000000210435000000a00100043d000001800110003900000013020000290000000000210435000001000100043d000000190110017f000000a00200043d000001a0022000390000000000120435000000800100043d000000ff0110018f000000a00200043d000001c0022000390000000000120435000000c00100043d000000ff0110018f000000a00200043d000001e0022000390000000000120435000000a00100043d0000020001100039000000e00200043d0000000000210435000000180100002900000000010104330000001a03000029000000000031004b00001d6c0000a13d00000016020000290000001701200029000000a00200043d000000000021043500000018010000290000000001010433000000000031004b00001d6c0000a13d00000001033000390000000a0030006c00000b850000413d00000006010000290000000001010433000000400900043d00000bf802000041000000000029043500000baa01100197000000040290003900000000001204350000000001000414000000050200002900000baa02200197000000040020008c000010880000c13d00000002010003670000000008000031000000200700008a0000109e0000013d00000b860090009c001f00000009001d00000b86030000410000000003094019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000bb6011001c72e152e100000040f0000000003010019000000600330027000000b860030019d00000b86083001970002000000010355000000010020019000001e5e0000613d000000200700008a0000001b0d000029000000600e0000390000001f0900002900000000047801700000000002490019000010a70000613d000000000501034f0000000006090019000000005305043c0000000006360436000000000026004b000010a30000c13d0000001f05800190000010b40000613d000000000641034f0000000303500210000000000402043300000000043401cf000000000434022f000000000506043b0000010003300089000000000535022f00000000033501cf000000000343019f0000000000320435001e000000010353001f00000008001d0000001f01800039000000000171016f00000000030900190000000002910019000000000012004b0000000004000039000000010400403900000ba70020009c000005790000213d0000000100400190000005790000c13d000000400020043f0000001f0100002900000bad0010009c000006070000213d0000001f01000029000000200010008c000006070000413d000000000503043300000ba70050009c000006070000213d0000001f043000290000000005350019000000000654004900000bad0060009c000006070000213d000000600060008c000006070000413d00000bc30020009c000005790000213d0000006006200039000000400060043f000000008705043400000ba70070009c000006070000213d00000000095700190000001f01900039000000000041004b000000000300001900000bae0300804100000bae0110019700000bae07400197000000000a71013f000000000071004b000000000100001900000bae0100404100000bae00a0009c000000000103c019000000000001004b000006070000c13d00000000a909043400000ba70090009c000005790000213d0000001f0190003900000bff011001970000003f0110003900000bff01100197000000000b61001900000ba700b0009c000005790000213d0000004000b0043f00000000009604350000000001a90019000000000041004b000006070000213d000000800b200039000000000009004b000011020000613d000000000c0000190000000001bc00190000000003ac001900000000030304330000000000310435000000200cc0003900000000009c004b000010fb0000413d0000000001b9001900000000000104350000000006620436000000000808043300000ba70080009c000006070000213d00000000085800190000001f01800039000000000041004b000000000300001900000bae0300804100000bae01100197000000000971013f000000000071004b000000000100001900000bae0100404100000bae0090009c000000000103c019000000000001004b000006070000c13d000000009808043400000ba70080009c000005790000213d0000001f0180003900000bff011001970000003f0110003900000bff01100197000000400a00043d000000000b1a00190000000000ab004b000000000c000039000000010c00403900000ba700b0009c000005790000213d0000000100c00190000005790000c13d0000004000b0043f000000000b8a04360000000001980019000000000041004b000006070000213d000000000008004b000011350000613d000000000c0000190000000001bc001900000000039c001900000000030304330000000000310435000000200cc0003900000000008c004b0000112e0000413d00000000018b001900000000000104350000000000a604350000004001500039000000000801043300000ba70080009c000006070000213d00000000055800190000001f01500039000000000041004b000000000300001900000bae0300804100000bae01100197000000000871013f000000000071004b000000000100001900000bae0100404100000bae0080009c000000000103c019000000000001004b000006070000c13d000000007505043400000ba70050009c000005790000213d0000001f0150003900000bff011001970000003f0110003900000bff01100197000000400300043d0000000008130019001900000003001d000000000038004b0000000009000039000000010900403900000ba70080009c000005790000213d0000000100900190000005790000c13d000000400080043f000000190100002900000000085104360000000001750019000000000041004b000006070000213d000000000005004b0000116b0000613d000000000400001900000000018400190000000003740019000000000303043300000000003104350000002004400039000000000054004b000011640000413d000000000158001900000000000104350000004001200039000000190300002900000000003104350000000001020433001500000001001d0000000001060433001200000001001d000000040200002900000080012000390000000001010433001300000001001d00000060012000390000000001010433001400000001001d00000020012000390000000001010433001600000001001d0000000001020433001700000001001d00000006010000290000000001010433000000400300043d00000be502000041001a00000003001d0000000000230435000000000200041400000baa01100197001d00000001001d000000040010008c000011900000c13d0000001f01000029000000200010008c00000020040000390000000004014019000011bf0000013d0000001a0100002900000b860010009c00000b8601008041000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c70000001d020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c001f00000003001d0000002004000039000000000403401900000020064001900000001a05600029000011ab0000613d000000000701034f0000001a08000029000000007307043c0000000008380436000000000058004b000011a70000c13d0000001f07400190000011b80000613d000000000861034f0000000303700210000000000605043300000000063601cf000000000636022f000000000708043b0000010003300089000000000737022f00000000033701cf000000000363019f00000000003504350000001f0000002f001e0000000103530002000000010355000000010020019000001e7a0000613d0000001b0d000029000000600e0000390000001f01400039000000600210018f0000001a01200029000000000021004b00000000040000390000000104004039001c00000001001d00000ba70010009c000005790000213d0000000100400190000005790000c13d0000001c01000029000000400010043f0000001f01000029000000200010008c000006070000413d0000001a010000290000000001010433001100000001001d00000baa0010009c000006070000213d00000bf9010000410000001c03000029000000000013043500000000040004140000001d01000029000000040010008c0000120d0000613d00000b860030009c00000b86010000410000000001034019000000400110021000000b860040009c00000b8604008041000000c002400210000000000112019f00000b8a011001c70000001d020000292e152e100000040f0000001c080000290000000003010019000000600330027000000b8603300197000000200030008c001f00000003001d0000002004000039000000000403401900000020064001900000000005680019000011f60000613d000000000701034f000000007307043c0000000008380436000000000058004b000011f20000c13d0000001f07400190000012030000613d000000000861034f0000000303700210000000000605043300000000063601cf000000000636022f000000000708043b0000010003300089000000000737022f00000000033701cf000000000363019f00000000003504350000001f0000002f001e0000000103530002000000010355000000010020019000001e870000613d0000001f01400039000000600210018f0000001b0d000029000000600e0000390000001c030000290000000001320019001a00000001001d00000ba70010009c000005790000213d0000001a01000029000000400010043f0000001f01000029000000200010008c000006070000413d0000001c010000290000000001010433001000000001001d00000bfa010000410000001a03000029000000000013043500000000040004140000001d01000029000000040010008c000012520000613d00000b860030009c00000b86010000410000000001034019000000400110021000000b860040009c00000b8604008041000000c002400210000000000112019f00000b8a011001c70000001d020000292e152e100000040f0000001a080000290000000003010019000000600330027000000b8603300197000000200030008c001f00000003001d00000020040000390000000004034019000000200640019000000000056800190000123b0000613d000000000701034f000000007307043c0000000008380436000000000058004b000012370000c13d0000001f07400190000012480000613d000000000861034f0000000303700210000000000605043300000000063601cf000000000636022f000000000708043b0000010003300089000000000737022f00000000033701cf000000000363019f00000000003504350000001f0000002f001e0000000103530002000000010355000000010020019000001e940000613d0000001f01400039000000600210018f0000001b0d000029000000600e0000390000001a030000290000000001320019001c00000001001d00000ba70010009c000005790000213d0000001c01000029000000400010043f0000001f01000029000000200010008c000006070000413d0000001a010000290000000001010433001a00000001001d00000bfb010000410000001c03000029000000000013043500000000040004140000001d01000029000000040010008c000012970000613d00000b860030009c00000b86010000410000000001034019000000400110021000000b860040009c00000b8604008041000000c002400210000000000112019f00000b8a011001c70000001d020000292e152e100000040f0000001c080000290000000003010019000000600330027000000b8603300197000000200030008c001f00000003001d0000002004000039000000000403401900000020064001900000000005680019000012800000613d000000000701034f000000007307043c0000000008380436000000000058004b0000127c0000c13d0000001f074001900000128d0000613d000000000861034f0000000303700210000000000605043300000000063601cf000000000636022f000000000708043b0000010003300089000000000737022f00000000033701cf000000000363019f00000000003504350000001f0000002f001e0000000103530002000000010355000000010020019000001ea10000613d0000001f01400039000000600210018f0000001b0d000029000000600e0000390000001c03000029000000000232001900000ba70020009c000005790000213d000000400020043f0000001f01000029000000200010008c000006070000413d00000bea0020009c000005790000213d0000001c010000290000000001010433000001a003200039000000400030043f0000018003200039000000180400002900000000004304350000016003200039000000000013043500000140012000390000001a030000290000000000310435000001200120003900000010030000290000000000310435000001000120003900000011030000290000000000310435000000e00120003900000019030000290000000000310435000000c00120003900000012030000290000000000310435000000a0012000390000001503000029000000000031043500000080012000390000001303000029000000000031043500000060012000390000001403000029000000000031043500000040012000390000001d030000290000000000310435000000160100002900000baa01100197000000200320003900000000001304350000001701000029000000000012043500000020010000290000000001010433000000080010006c00001d6c0000a13d0000000301d00029000000000021043500000020010000290000000001010433000000080010006c00001d6c0000a13d00000008020000290000000102200039000000020020006c00000a980000413d0000002e02000029000005450000013d0000000007000019000012e00000013d00000000042400190000000107700039000000000037004b000005500000813d0000000008150049000000400880008a00000000008404350000002006200029002000000006001d000000000806043300000000c9080434000001a006000039000000000b65043600000000d9090434000001a00a50003900000000009a0435000001c00a500039000000000009004b000012f70000613d000000000e000019000000000fae00190000000006ed0019000000000606043300000000006f0435000000200ee0003900000000009e004b000012f00000413d0000000006a90019000000000006043500000000060c043300000baa0660019700000000006b04350000004006800039000000000606043300000baa06600197000000400b50003900000000006b043500000060068000390000000006060433000000600b50003900000000006b043500000080068000390000000006060433000000800b50003900000000006b04350000001f0690003900000bff066001970000000006a600190000000009560049000000a00a500039000000a00b800039000000000b0b043300000000009a043500000000ba0b04340000000009a6043600000000000a004b0000131d0000613d000000000c00001900000000069c0019000000000dcb0019000000000d0d04330000000000d60435000000200cc000390000000000ac004b000013160000413d00000000069a001900000000000604350000001f06a0003900000bff066001970000000006960019000000c0098000390000000009090433000000000a560049000000c00b5000390000000000ab043500000000ba0904340000000009a6043600000000000a004b000013330000613d000000000c00001900000000069c0019000000000dcb0019000000000d0d04330000000000d60435000000200cc000390000000000ac004b0000132c0000413d00000000069a001900000000000604350000001f06a0003900000bff066001970000000006960019000000e0098000390000000009090433000000000a560049000000e00b5000390000000000ab043500000000ba0904340000000009a6043600000000000a004b000013490000613d000000000c00001900000000069c0019000000000dcb0019000000000d0d04330000000000d60435000000200cc000390000000000ac004b000013420000413d00000000069a001900000000000604350000010006800039000000000606043300000baa06600197000001000b50003900000000006b043500000120068000390000000006060433000001200b50003900000000006b043500000140068000390000000006060433000001400b50003900000000006b043500000160068000390000000006060433000001600b50003900000000006b04350000001f06a0003900000bff0660019700000000069600190000000009560049000001800550003900000180088000390000000008080433000000000095043500000000090804330000000005960436000000000009004b000012dc0000613d000000000a0000190000002008800039000000000b08043300000000c60b043400000baa066001970000000006650436000000000c0c04330000000000c604350000004006b000390000000006060433000000400c50003900000000006c04350000006006b000390000000006060433000000600c50003900000000006c04350000008006b000390000000006060433000000800c50003900000000006c0435000000a006b000390000000006060433000000a00c50003900000000006c0435000000c006b000390000000006060433000000c00c50003900000000006c0435000000e006b000390000000006060433000000e00c50003900000000006c04350000010006b000390000000006060433000001000c50003900000000006c04350000012006b000390000000006060433000001200c50003900000000006c04350000014006b000390000000006060433000001400c50003900000000006c04350000016006b000390000000006060433000000000006004b0000000006000039000000010600c039000001600c50003900000000006c04350000018006b000390000000006060433000001800c50003900000000006c0435000001a006b00039000000000606043300000baa06600197000001a00c50003900000000006c0435000001c006b000390000000006060433000001c00c50003900000000006c0435000001e006b000390000000006060433000001e00c50003900000000006c04350000020006b000390000000006060433000002000b50003900000000006b04350000022005500039000000010aa0003900000000009a004b000013690000413d000012dc0000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000013bc0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000013c80000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000013d40000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000013e00000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000013ec0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000013f80000c13d000006630000013d00150baa0020019b0000001e01000029001601a00010003d001d00000000001d001c00000000001d000000400100043d001e00000001001d00000bc20010009c000005790000213d0000001e020000290000004001200039000000400010043f0000000001020436001b00000001001d00000000000104350000001f0100002900000000010104330000001d02000029000000000021004b00001d6c0000a13d0000000504200210001900000004001d0000001605400029000000000105043300000baa011001970000001e0400002900000000001404350000001f010000290000000001010433000000000021004b00001d6c0000a13d0000000002050433000000400a00043d00000be60100004100000000001a0435000000000100041400000baa02200197000000040020008c001a00000005001d000014290000c13d000000200030008c00000020040000390000000004034019000014550000013d00000b8600a0009c00000b860300004100000000030a4019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000b8a011001c700200000000a001d2e152e100000040f000000200a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000014440000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000014400000c13d0000001f07400190000014510000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001d780000613d0000001f01400039000000600110018f00000000060a00190000000005a10019000000000015004b00000000020000390000000102004039002000000005001d00000ba70050009c000005790000213d0000000100200190000005790000c13d0000002002000029000000400020043f000000200040008c000006070000413d0000001f0200002900000000020204330000001d0020006c0000001a0200002900001d6c0000a13d0000000004060433001800000004001d000000000202043300000be70400004100000020050000290000000000450435000000040450003900000baa02200197000000000024043500000000040004140000001502000029000000040020008c0000147c0000c13d000000000115001900000ba70010009c000005790000213d000000400010043f000014af0000013d00000b860050009c00000b86010000410000000001054019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000bb6011001c72e152e100000040f000000200a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000014960000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000014920000c13d0000001f07400190000014a30000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001d840000613d0000001f01400039000000600110018f0000000001a1001900000ba70010009c000005790000213d000000400010043f000000200030008c000006070000413d00000020010000290000000002010433000000180400002900000000014200a9000000000004004b0000001d05000029000014b90000613d00000000044100d9000000000024004b00001d720000c13d00000bd10110012a0000001b020000290000000000120435000000170100002900000000010104330000000002010433000000000052004b00001d6c0000a13d000000190210002900000020022000390000001e0400002900000000004204350000000001010433000000000051004b00001d6c0000a13d0000001b0100002900000000010104330000001c0010002a00001d720000413d001c001c0010002d001d00010050003d0000001f0100002900000000010104330000001d0010006b000014020000413d000009b30000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000014da0000c13d000006630000013d0028001c0000002d000000400400043d002700000004001d001900000004001d0000000004460019000000000064004b0000000005000039000000010500403900000ba70040009c000005790000213d0000000100500190000005790000c13d000000400040043f00000019040000290000000004240436000000000002004b000015030000613d00000060020000390000000005000019000000400600043d00000bbf0060009c000005790000213d0000008007600039000000400070043f0000006007600039000000000027043500000040076000390000000000070435000000200760003900000000000704350000000000060435000000000754001900000000006704350000002005500039000000000015004b000014f20000413d002600000000003d0000001c010000290000000001010433000000000001004b000015400000c13d000000400100043d00000020020000390000000002210436000000190300002900000000030304330000000000320435000000400410003900000005023002100000000002420019000000000003004b000002180000613d00000080050000390000000006000019000000190c0000290000151a0000013d0000000106600039000000000036004b000002180000813d0000000007120049000000400770008a0000000004740436000000200cc0003900000000070c0433000000009807043400000baa088001970000000008820436000000000909043300000baa09900197000000000098043500000040087000390000000008080433000000400920003900000000008904350000006007700039000000000707043300000060082000390000000000580435000000800920003900000000080704330000000000890435000000a002200039000000000008004b000015170000613d00000000090000190000002007700039000000000a07043300000000ba0a043400000baa0aa00197000000000aa20436000000000b0b04330000000000ba043500000040022000390000000109900039000000000089004b000015340000413d000015170000013d001f00000000001d000000400100043d001d00000001001d00000bbf0010009c000005790000213d0000001d020000290000008001200039000000400010043f00000060042000390000006001000039001800000004001d00000000001404350000004001200039001600000001001d00000000000104350000002001200039001700000001001d00000000000104350000000000020435002500000002001d0000001c0100002900000000010104330000001f0010006c00001d6c0000a13d0000001f0400002900000005014002100000001c0200002900000000011200190000002001100039001a00000001001d000000000101043300000baa011001970000001d0500002900000000001504350000000001020433000000000041004b00001d6c0000a13d0000001a010000290000000002010433000000400400043d00000bc001000041001b00000004001d0000000000140435000000000100041400000baa02200197000000040020008c000015730000c13d000000200030008c000000200400003900000000040340190000159d0000013d0000001b0300002900000b860030009c00000b8603008041000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000b8a011001c72e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000001b056000290000158c0000613d000000000701034f0000001b08000029000000007907043c0000000008980436000000000058004b000015880000c13d0000001f07400190000015990000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f9c0000613d0000001f01400039000000600110018f0000001b02100029000000000012004b0000000004000039000000010400403900000ba70020009c000005790000213d0000000100400190000005790000c13d000000400020043f000000200030008c000006070000413d0000001b02000029000000000202043300000baa0020009c000006070000213d000000170400002900000000002404350000001c0200002900000000020204330000001f0020006c00001d6c0000a13d0000001a020000290000000002020433000000400500043d00000bc1040000410000000000450435000000200400002900000baa04400197001b00000005001d00000004055000390000000000450435000000000400041400000baa02200197000000040020008c000015ee0000613d0000001b0100002900000b860010009c00000b8601008041000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000bb6011001c72e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000001b05600029000015db0000613d000000000701034f0000001b08000029000000007907043c0000000008980436000000000058004b000015d70000c13d0000001f07400190000015e80000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001fa80000613d0000001f01400039000000600110018f0000001b02100029000000000012004b0000000001000039000000010100403900000ba70020009c000005790000213d0000000100100190000005790000c13d000000400020043f000000200030008c000006070000413d0000001b010000290000000001010433000000160200002900000000001204350000001c0100002900000000010104330000001f0010006c00001d6c0000a13d0000001e01000029000000000501043300000ba70050009c000005790000213d00000005015002100000003f0210003900000ba802200197000000400600043d0000000004260019001300000006001d000000000064004b0000000002000039000000010200403900000ba70040009c000005790000213d0000000100200190000005790000c13d0000001a020000290000000002020433000000400040043f00000013040000290000000004540436000000000005004b000016270000613d0000000005000019000000400600043d00000bc20060009c000005790000213d0000004007600039000000400070043f000000200760003900000000000704350000000000060435000000000754001900000000006704350000002005500039000000000015004b0000161a0000413d0000001e010000290000000001010433000000000001004b00001d510000613d001f0baa0020019b001d00000000001d000000400100043d002000000001001d00000bc30010009c000005790000213d00000020020000290000006001200039000000400010043f0000004001200039001600000001001d00000000000104350000000001020436001c00000001001d0000000000010435000000400100043d001a00000001001d00000bc30010009c000005790000213d0000001a020000290000006001200039000000400010043f0000004001200039001400000001001d00000000000104350000000001020436001700000001001d000000000001043500000ba50100004100000000001004430000000001000412000000040010044300000020010000390000002400100443000000000100041400000b860010009c00000b8601008041000000c00110021000000bc4011001c700008005020000392e152e100000040f000000010020019000001e440000613d000000000101043b000000000001004b0000001d020000290019000500200218000016750000613d0000001e010000290000000001010433000000000021004b00001d6c0000a13d00000019020000290000001e012000290000002001100039001500000001001d0000000001010433000000400300043d00000bc5020000410000000002230436001800000002001d00000baa01100197001b00000003001d0000000402300039000000000012043500000000010004140000001f02000029000000040020008c0000168f0000c13d0000000003000031000000600030008c00000060040000390000000004034019000016ba0000013d0000001e010000290000000001010433000000000021004b00001d6c0000a13d00000019020000290000001e012000290000002001100039001500000001001d0000000001010433000000400300043d00000bc8020000410000000002230436001800000002001d00000baa01100197001b00000003001d0000000402300039000000000012043500000000010004140000001f02000029000000040020008c0000172a0000c13d0000000003000031000000600030008c00000060040000390000000004034019000017550000013d0000001b0200002900000b860020009c00000b8602008041000000400220021000000b860010009c00000b8601008041000000c001100210000000000121019f00000bb6011001c70000001f020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000600030008c0000006004000039000000000403401900000060064001900000001b05600029000016a90000613d000000000701034f0000001b08000029000000007907043c0000000008980436000000000058004b000016a50000c13d0000001f07400190000016b60000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f240000613d0000001f01400039000000e00110018f0000001b02100029000000000012004b0000000004000039000000010400403900000ba70020009c000005790000213d0000000100400190000005790000c13d000000400020043f000000600030008c000006070000413d0000001b02000029000000000202043300000bc60020009c000006070000213d000000180400002900000000040404330000001b0500002900000040055000390000000005050433000000160600002900000000005604350000001c050000290000000000450435000000200400002900000000002404350000001e0200002900000000020204330000001d0020006c00001d6c0000a13d00000015020000290000000002020433000000400a00043d00000bc70400004100000000044a0436001b00000004001d00000baa022001970000000404a00039000000000024043500000000020004140000001f04000029000000040040008c000017160000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bb6011001c70000001f0200002900180000000a001d2e152e100000040f0000000003010019000000600330027000000b8603300197000000600030008c000000600400003900000000040340190000006006400190000000180a0000290000001805600029000017030000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000016ff0000c13d0000001f07400190000017100000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f300000613d0000001f01400039000000e00110018f00000000040a00190000000002a10019000000000012004b0000000001000039000000010100403900000ba70020009c000005790000213d0000000100100190000005790000c13d000000400020043f000000600030008c000006070000413d000000000104043300000bc60010009c000006070000213d0000001b02000029000000000202043300000040044000390000000004040433000017cc0000013d0000001b0200002900000b860020009c00000b8602008041000000400220021000000b860010009c00000b8601008041000000c001100210000000000121019f00000bb6011001c70000001f020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000600030008c0000006004000039000000000403401900000060064001900000001b05600029000017440000613d000000000701034f0000001b08000029000000007907043c0000000008980436000000000058004b000017400000c13d0000001f07400190000017510000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f3c0000613d0000001f01400039000000e00110018f0000001b02100029000000000012004b0000000004000039000000010400403900000ba70020009c000005790000213d0000000100400190000005790000c13d000000400020043f000000600030008c000006070000413d0000001b02000029000000000202043300000bc60020009c000006070000213d0000001804000029000000000404043300000b860040009c000006070000213d0000001b050000290000004005500039000000000505043300000b860050009c000006070000213d000000160600002900000000005604350000001c050000290000000000450435000000200400002900000000002404350000001e0200002900000000020204330000001d0020006c00001d6c0000a13d00000015020000290000000002020433000000400500043d00000bc9040000410000000004450436001800000004001d00000baa02200197001b00000005001d0000000404500039000000000024043500000000020004140000001f04000029000000040040008c000017b40000613d0000001b0100002900000b860010009c00000b8601008041000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bb6011001c70000001f020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000600030008c0000006004000039000000000403401900000060064001900000001b05600029000017a10000613d000000000701034f0000001b08000029000000007907043c0000000008980436000000000058004b0000179d0000c13d0000001f07400190000017ae0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f480000613d0000001f01400039000000e00110018f0000001b02100029000000000012004b0000000001000039000000010100403900000ba70020009c000005790000213d0000000100100190000005790000c13d000000400020043f000000600030008c000006070000413d0000001b01000029000000000101043300000bc60010009c000006070000213d0000001802000029000000000202043300000b860020009c000006070000213d0000001b040000290000004004400039000000000404043300000b860040009c000006070000213d00000014050000290000000000450435000000170400002900000000002404350000001a0200002900000000001204350000001e0100002900000000010104330000001d0010006c00001d6c0000a13d00000019020000290000001e012000290000002001100039001800000001001d0000000002010433000000400500043d00000bca010000410000000000150435000000000100041400000baa02200197000000040020008c0000002004000039001500000005001d0000180f0000613d00000b860050009c00000b86030000410000000003054019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000b8a011001c72e152e100000040f00000015080000290000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000000005680019000017fd0000613d000000000701034f000000007907043c0000000008980436000000000058004b000017f90000c13d0000001f074001900000180a0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001ed00000613d00000015050000290000001f01400039000000600110018f0000000004510019000000000014004b00000000020000390000000102004039001b00000004001d00000ba70040009c000005790000213d0000000100200190000005790000c13d0000001b02000029000000400020043f000000200030008c000006070000413d0000001b0200002900000bcb0020009c000005790000213d000000150200002900000000020204330000001b050000290000002004500039000000400040043f00000000002504350000001e0200002900000000020204330000001d0020006c00001d6c0000a13d00000018020000290000000002020433000000400500043d00000bcc04000041000000000045043500000baa042001970000000402500039001200000004001d000000000042043500000000020004140000001f04000029000000040040008c001500000005001d000018670000613d00000b860050009c00000b86010000410000000001054019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bb6011001c70000001f020000292e152e100000040f00000015080000290000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000000005680019000018530000613d000000000701034f000000007907043c0000000008980436000000000058004b0000184f0000c13d0000001f07400190000018600000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001edc0000613d0000001f01400039000000600110018f00000015050000290000000002510019000000000012004b0000000001000039000000010100403900000ba70020009c000005790000213d0000000100100190000005790000c13d000000400020043f000000200030008c000006070000413d00000015010000290000000001010433001500000001001d00000ba50100004100000000001004430000000001000412000000040010044300000040010000390000002400100443000000000100041400000b860010009c00000b8601008041000000c00110021000000bc4011001c700008005020000392e152e100000040f000000010020019000001e440000613d000000000101043b000000010010008c0000188d0000613d000000020010008c00001e4b0000c13d00000bcf0100004100000000001004430000000001000414000018900000013d00000bcd010000410000000000100443000000000100041400000b860010009c00000b8601008041000000c00110021000000bce011001c70000800b020000392e152e100000040f000000010020019000001e440000613d00000016020000290000000004020433000000000101043b000000000041004b00000000020000390000000102002039000000000004004b0000000003000039000000010300c039000000000023017000000000040160190000001c010000290000000001010433001600000004001d001000000014005300001d720000413d0000001d02000029000019470000613d000000150000006b000019440000613d000000400200043d00000bd001000041001100000002001d000000000012043500000000010004140000001202000029000000040020008c000018b90000c13d0000000003000031000000200030008c00000020040000390000000004034019000018e40000013d000000110200002900000b860020009c00000b8602008041000000400220021000000b860010009c00000b8601008041000000c001100210000000000121019f00000b8a011001c700000012020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000001105600029000018d30000613d000000000701034f0000001108000029000000007907043c0000000008980436000000000058004b000018cf0000c13d0000001f07400190000018e00000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f6c0000613d0000001f01400039000000600210018f0000001101200029000000000021004b0000000002000039000000010200403900000ba70010009c000005790000213d0000000100200190000005790000c13d000000400010043f000000200030008c000006070000413d0000001102000029000000000302043300000bd1023000d1000000000003004b000018f90000613d00000000033200d900000bd10030009c00001d720000c13d0000001b030000290000000003030433000000000003004b00001e450000613d000000100500002900000015045000b900000000055400d9000000150050006c00001d720000c13d000000000023004b000019080000a13d00000bcb0010009c0000000002000019000019180000a13d000005790000013d00000bcb0010009c000005790000213d0000002005100039000000400050043f000000000001043500000bd2054000d1000000000004004b000019130000613d00000000014500d900000bd20010009c00001d720000c13d000000400100043d00000bcb0010009c000005790000213d00000000023200d900000000022500d90000002003100039000000400030043f0000000000210435000000400200043d00000bcb0020009c000005790000213d000000200300002900000000030304330000002004200039000000400040043f00000bc6033001970000000000320435000000400300043d00000bcb0030009c000005790000213d0000002004300039000000400040043f000000000003043500000000020204330000000001010433000000000021001a00001d720000413d000000400300043d00000bcb0030009c000005790000213d00000000022100190000002001300039000000400010043f0000000000230435000000400100043d00000bc20010009c000005790000213d0000004003100039000000400030043f000000200310003900000bd30400004100000000004304350000001303000039000000000031043500000bd40020009c00001ebd0000813d000000200100002900000000002104350000001d020000290000001c01000029000000160300002900000000003104350000001e010000290000000001010433000000000021004b00001d6c0000a13d00000018010000290000000001010433000000400300043d00000bd602000041000000000023043500000baa02100197001c00000003001d0000000401300039001500000002001d000000000021043500000000010004140000001f02000029000000040020008c0000195e0000c13d0000000003000031000000200030008c00000020040000390000000004034019000019890000013d0000001c0200002900000b860020009c00000b8602008041000000400220021000000b860010009c00000b8601008041000000c001100210000000000121019f00000bb6011001c70000001f020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000001c05600029000019780000613d000000000701034f0000001c08000029000000007907043c0000000008980436000000000058004b000019740000c13d0000001f07400190000019850000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001ee80000613d0000001f01400039000000600210018f0000001c01200029000000000021004b0000000002000039000000010200403900000ba70010009c000005790000213d0000000100200190000005790000c13d000000400010043f000000200030008c000006070000413d0000001c010000290000000001010433001c00000001001d00000ba50100004100000000001004430000000001000412000000040010044300000040010000390000002400100443000000000100041400000b860010009c00000b8601008041000000c00110021000000bc4011001c700008005020000392e152e100000040f000000010020019000001e440000613d000000000101043b000000010010008c000019b10000613d000000020010008c00001e4b0000c13d00000bcf0100004100000000001004430000000001000414000019b40000013d00000bcd010000410000000000100443000000000100041400000b860010009c00000b8601008041000000c00110021000000bce011001c70000800b020000392e152e100000040f000000010020019000001e440000613d00000014020000290000000004020433000000000101043b000000000041004b00000000020000390000000102002039000000000004004b0000000003000039000000010300c0390000000000230170000000000401601900000017010000290000000001010433001600000004001d000000000114004b00001d720000413d0000001d0200002900001a610000613d001200000001001d0000001c0000006b00001a5e0000613d000000400200043d00000bd701000041001400000002001d000000000012043500000000010004140000001502000029000000040020008c000019de0000c13d0000000003000031000000200030008c0000002004000039000000000403401900001a090000013d000000140200002900000b860020009c00000b8602008041000000400220021000000b860010009c00000b8601008041000000c001100210000000000121019f00000b8a011001c700000015020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000001405600029000019f80000613d000000000701034f0000001408000029000000007907043c0000000008980436000000000058004b000019f40000c13d0000001f0740019000001a050000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f780000613d0000001f01400039000000600210018f0000001401200029000000000021004b0000000002000039000000010200403900000ba70010009c000005790000213d0000000100200190000005790000c13d000000400010043f000000200030008c000006070000413d00000012020000290000001c032000b900000000022300d90000001c0020006c00001d720000c13d00000014020000290000000002020433000000000002004b00001a2f0000613d00000bcb0010009c000005790000213d0000002004100039000000400040043f000000000001043500000bd2043000d1000000000003004b00001a2a0000613d00000000013400d900000bd20010009c00001d720000c13d000000400100043d00000bcb0010009c000005790000213d00000000022400d900001a320000013d00000bcb0010009c0000000002000019000005790000213d0000002003100039000000400030043f0000000000210435000000400200043d00000bcb0020009c000005790000213d0000001a0300002900000000030304330000002004200039000000400040043f00000bc6033001970000000000320435000000400300043d00000bcb0030009c000005790000213d0000002004300039000000400040043f000000000003043500000000020204330000000001010433000000000021001a00001d720000413d000000400300043d00000bcb0030009c000005790000213d00000000022100190000002001300039000000400010043f0000000000230435000000400100043d00000bc20010009c000005790000213d0000004003100039000000400030043f000000200310003900000bd30400004100000000004304350000001303000039000000000031043500000bd40020009c00001ebd0000813d0000001a0100002900000000002104350000001d020000290000001701000029000000160300002900000000003104350000001e010000290000000001010433000000000021004b00001d6c0000a13d000000400100043d001700000001001d00000bcb0010009c000005790000213d0000001801000029000000000101043300000baa031001970000002001000029000000000101043300000017040000290000002002400039000000400020043f00000bc6011001970000000000140435000000400400043d00000bd801000041000000000014043500000004014000390000002a02000029001600000003001d0000000000310435001c00000004001d0000002401400039002000000002001d00000baa02200197001800000002001d000000000021043500000000010004140000001f02000029000000040020008c00001a890000c13d0000000003000031000000200030008c0000002004000039000000000403401900001ab40000013d0000001c0200002900000b860020009c00000b8602008041000000400220021000000b860010009c00000b8601008041000000c001100210000000000121019f00000bbb011001c70000001f020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000001c0560002900001aa30000613d000000000701034f0000001c08000029000000007907043c0000000008980436000000000058004b00001a9f0000c13d0000001f0740019000001ab00000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001ef40000613d0000001f01400039000000600110018f0000001c04100029000000000014004b00000000020000390000000102004039001e00000004001d00000ba70040009c000005790000213d0000000100200190000005790000c13d0000001e02000029000000400020043f000000200030008c000006070000413d0000001e0200002900000bcb0020009c000005790000213d0000001c0200002900000000020204330000001e050000290000002004500039000000400040043f0000000000250435000000400a00043d000000000002004b00001b5d0000c13d00000017020000290000000002020433001500000002001d00000bd90200004100000000002a043500000000020004140000001f04000029000000040040008c00001b070000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c70000001f02000029001c0000000a001d2e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000001c0a0000290000001c0560002900001af40000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00001af00000c13d0000001f0740019000001b010000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f540000613d0000001f01400039000000600110018f00000000040a00190000000005a10019000000000015004b00000000020000390000000102004039001c00000005001d00000ba70050009c000005790000213d0000000100200190000005790000c13d0000001c02000029000000400020043f000000200030008c000006070000413d000000000204043300000bc60020009c000006070000213d000000150020006b00001b1c0000813d0000001c0a00002900001b5d0000013d00000bd9020000410000001c04000029000000000024043500000000020004140000001f04000029000000040040008c00001b500000613d0000001c0100002900000b860010009c00000b8601008041000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c70000001f020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000001c0560002900001b3d0000613d000000000701034f0000001c08000029000000007907043c0000000008980436000000000058004b00001b390000c13d0000001f0740019000001b4a0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f840000613d0000001f01400039000000600110018f0000001c0110002900000ba70010009c000005790000213d000000400010043f000000200030008c000006070000413d0000001c01000029000000000101043300000bc60010009c000006070000213d0000001e020000290000000000120435000000400a00043d00000000010a001900000bcb00a0009c000005790000213d00000000020100190000002001200039000000400010043f00000000000204350000001e01000029000000000101043300000017020000290000000002020433000000000112004b00001d720000413d000000400200043d001e00000002001d00000bcb0020009c000005790000213d0000001e040000290000002002400039000000400020043f0000000000140435000000400500043d00000bda01000041000000000015043500000004015000390000001802000029000000000021043500000000010004140000001602000029000000040020008c0000002004000039001700000005001d00001ba90000613d00000b860050009c00000b86030000410000000003054019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000bb6011001c72e152e100000040f00000017080000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000002006400190000000000568001900001b970000613d000000000701034f000000007907043c0000000008980436000000000058004b00001b930000c13d0000001f0740019000001ba40000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f000000613d00000017050000290000001f01400039000000600110018f0000000004510019000000000014004b00000000020000390000000102004039001c00000004001d00000ba70040009c000005790000213d0000000100200190000005790000c13d0000001c02000029000000400020043f000000200030008c000006070000413d0000001702000029000000000402043300000bd1024000d1000000000004004b00001bc00000613d00000000044200d900000bd10040009c00001d720000c13d0000001b040000290000000004040433000000000004004b00001e450000613d0000001e05000029000000000505043300000000064200d900170000006500ad000000000024004b00001bcd0000213d00000017026000f9000000000052004b00001d720000c13d0000002902000029001e00000002001d00000000020204330000001d0020006c00001d6c0000a13d0000001c0200002900000bcb0020009c000005790000213d00000019020000290000002004200039001500000004001d0000001e02400029001600000002001d000000000202043300000baa062001970000001a0200002900000000020204330000001c050000290000002004500039000000400040043f00000bc6022001970000000000250435000000400500043d00000024025000390000001804000029000000000042043500000bdb0200004100000000002504350000000402500039001900000006001d000000000062043500000000020004140000001f04000029000000040040008c001a00000005001d00001c1f0000613d00000b860050009c00000b86010000410000000001054019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bbb011001c70000001f020000292e152e100000040f0000001a080000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000002006400190000000000568001900001c0b0000613d000000000701034f000000007907043c0000000008980436000000000058004b00001c070000c13d0000001f0740019000001c180000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f0c0000613d0000001f01400039000000600110018f0000001a050000290000000004510019000000000014004b00000000020000390000000102004039001b00000004001d00000ba70040009c000005790000213d0000000100200190000005790000c13d0000001b02000029000000400020043f000000200030008c000006070000413d0000001b0200002900000bcb0020009c000005790000213d0000001a0200002900000000020204330000001b050000290000002004500039000000400040043f0000000000250435000000400a00043d000000000002004b00001cc60000c13d0000001c020000290000000002020433001400000002001d00000bd90200004100000000002a043500000000020004140000001f04000029000000040040008c00001c700000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c70000001f02000029001a0000000a001d2e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000001a0a0000290000001a0560002900001c5d0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00001c590000c13d0000001f0740019000001c6a0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f600000613d0000001f01400039000000600110018f00000000040a00190000000005a10019000000000015004b00000000020000390000000102004039001a00000005001d00000ba70050009c000005790000213d0000000100200190000005790000c13d0000001a02000029000000400020043f000000200030008c000006070000413d000000000204043300000bc60020009c000006070000213d000000140020006b00001c850000813d0000001a0a00002900001cc60000013d00000bd9020000410000001a04000029000000000024043500000000020004140000001f04000029000000040040008c00001cb90000613d0000001a0100002900000b860010009c00000b8601008041000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c70000001f020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000001a0560002900001ca60000613d000000000701034f0000001a08000029000000007907043c0000000008980436000000000058004b00001ca20000c13d0000001f0740019000001cb30000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f900000613d0000001f01400039000000600110018f0000001a0110002900000ba70010009c000005790000213d000000400010043f000000200030008c000006070000413d0000001a01000029000000000101043300000bc60010009c000006070000213d0000001b020000290000000000120435000000400a00043d00000000010a001900000bcb00a0009c000005790000213d00000000020100190000002001200039000000400010043f00000000000204350000001b0100002900000000010104330000001c020000290000000002020433000000000112004b00001d720000413d000000400200043d001c00000002001d00000bcb0020009c000005790000213d0000001c040000290000002002400039000000400020043f0000000000140435000000400500043d00000bb501000041000000000015043500000004015000390000001802000029000000000021043500000000010004140000001902000029000000040020008c0000002004000039001b00000005001d00001d120000613d00000b860050009c00000b86030000410000000003054019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000bb6011001c72e152e100000040f0000001b080000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000002006400190000000000568001900001d000000613d000000000701034f000000007907043c0000000008980436000000000058004b00001cfc0000c13d0000001f0740019000001d0d0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f180000613d0000001b050000290000001f01400039000000600210018f0000000001520019000000000021004b0000000002000039000000010200403900000ba70010009c000005790000213d0000000100200190000005790000c13d000000400010043f000000200030008c000006070000413d0000001c0200002900000000040204330000001b02000029000000000502043300000000025400a9000000000005004b00001d290000613d00000000055200d9000000000045004b00001d720000c13d00000bc20010009c000005790000213d0000004004100039000000400040043f000000000401043600000000000404350000001e0500002900000000050504330000001d07000029000000000075004b00001d6c0000a13d000000170500002900000bd20550012a00000bd20220012a0000001606000029000000000606043300000baa0660019700000000006104350000000002520019000000000024043500000013020000290000000002020433000000000072004b00001d6c0000a13d0000001304000029000000150240002900000000001204350000000001040433000000000071004b00001d6c0000a13d001d00010070003d0000001e0100002900000000010104330000001d0010006b0000162d0000413d001900270000002d001f00260000002d0000002501000029001d00000001001d001800600010003d000000130100002900000018020000290000000000120435000000190100002900000000010104330000001f0010006c00001d6c0000a13d0000001f0400002900000005014002100000001902000029000000000112001900000020011000390000001d0500002900000000005104350000000001020433000000000041004b00001d6c0000a13d0000001f02000029002600010020003d00000001022000390000002801000029001c00000001001d0000000001010433001f00000002001d000000000012004b000015410000413d000015080000013d00000bdc01000041000000000010043f0000003201000039000000040010043f00000bb60100004100002e170001043000000bdc01000041000000000010043f0000001101000039000000040010043f00000bb60100004100002e17000104300000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001d7f0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001d8b0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001d970000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001da30000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001daf0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001dbb0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001dc70000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001dd30000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001ddf0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001deb0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001df70000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e030000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e0f0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e1b0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e270000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e330000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e3f0000c13d000006630000013d000000000001042f00000bdc01000041000000000010043f0000001201000039000000040010043f00000bb60100004100002e170001043000000bdc01000041000000000010043f0000005101000039000000040010043f00000bb60100004100002e17000104300000001f010000290000001f0510018f00000b8806100198000000400200043d000000000462001900001ead0000613d0000001e0700035f0000000008020019000000007107043c0000000008180436000000000048004b00001e590000c13d00001ead0000013d000000000301034f0000001f0580018f000000000908001900000b8806800198000000400200043d000000000462001900001e6b0000613d000000000703034f0000000008020019000000007107043c0000000008180436000000000048004b00001e670000c13d000000000005004b00001e780000613d000000000163034f0000000303500210000000000504043300000000053501cf000000000535022f000000000101043b0000010003300089000000000131022f00000000013101cf000000000151019f00000000001404350000006001900210000006710000013d0000001f010000290000001f0510018f00000b8806100198000000400200043d000000000462001900001ead0000613d0000001e0700035f0000000008020019000000007107043c0000000008180436000000000048004b00001e820000c13d00001ead0000013d0000001f010000290000001f0510018f00000b8806100198000000400200043d000000000462001900001ead0000613d0000001e0700035f0000000008020019000000007107043c0000000008180436000000000048004b00001e8f0000c13d00001ead0000013d0000001f010000290000001f0510018f00000b8806100198000000400200043d000000000462001900001ead0000613d0000001e0700035f0000000008020019000000007107043c0000000008180436000000000048004b00001e9c0000c13d00001ead0000013d0000001f010000290000001f0510018f00000b8806100198000000400200043d000000000462001900001ead0000613d0000001e0700035f0000000008020019000000007107043c0000000008180436000000000048004b00001ea90000c13d000000000005004b00001eba0000613d0000001e0160035f0000000303500210000000000504043300000000053501cf000000000535022f000000000101043b0000010003300089000000000131022f00000000013101cf000000000151019f00000000001404350000001f010000290000006001100210000006710000013d000000400400043d002000000004001d00000bd502000041000000000024043500000004024000390000002003000039000000000032043500000024024000392e151fb40000040f0000002002000029000000000121004900000b860010009c00000b860100804100000b860020009c00000b860200804100000060011002100000004002200210000000000121019f00002e17000104300000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001ed70000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001ee30000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001eef0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001efb0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f070000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f130000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f1f0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f2b0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f370000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f430000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f4f0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f5b0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f670000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f730000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f7f0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f8b0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f970000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001fa30000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001faf0000c13d000006630000013d00000000430104340000000001320436000000000003004b00001fc00000613d000000000200001900000000051200190000000006240019000000000606043300000000006504350000002002200039000000000032004b00001fb90000413d000000000213001900000000000204350000001f0230003900000bff022001970000000001210019000000000001042d000000004301043400000baa03300197000000000332043600000000040404330000000000430435000000400310003900000000030304330000004004200039000000000034043500000060031000390000000003030433000000600420003900000000003404350000008003100039000000000303043300000080042000390000000000340435000000a0031000390000000003030433000000a0042000390000000000340435000000c0031000390000000003030433000000c0042000390000000000340435000000e0031000390000000003030433000000e004200039000000000034043500000100031000390000000003030433000001000420003900000000003404350000012003100039000000000303043300000120042000390000000000340435000001400310003900000000030304330000014004200039000000000034043500000160031000390000000003030433000000000003004b0000000003000039000000010300c039000001600420003900000000003404350000018003100039000000000303043300000180042000390000000000340435000001a003100039000000000303043300000baa03300197000001a0042000390000000000340435000001c0031000390000000003030433000001c0042000390000000000340435000001e0031000390000000003030433000001e00420003900000000003404350000020002200039000002000110003900000000010104330000000000120435000000000001042d0000000053010434000001a0040000390000000006420436000001a00420003900000000730304340000000000340435000001c004200039000000000003004b0000201d0000613d00000000080000190000000009480019000000000a870019000000000a0a04330000000000a904350000002008800039000000000038004b000020160000413d00000000074300190000000000070435000000000505043300000baa0550019700000000005604350000004005100039000000000505043300000baa0550019700000040062000390000000000560435000000600510003900000000050504330000006006200039000000000056043500000080051000390000000005050433000000800620003900000000005604350000001f0530003900000bff0550019700000000044500190000000005240049000000a006200039000000a0071000390000000007070433000000000056043500000000650704340000000004540436000000000005004b000020430000613d000000000700001900000000084700190000000009760019000000000909043300000000009804350000002007700039000000000057004b0000203c0000413d000000000645001900000000000604350000001f0550003900000bff055001970000000004450019000000c00510003900000000050504330000000006240049000000c007200039000000000067043500000000650504340000000004540436000000000005004b000020590000613d000000000700001900000000084700190000000009760019000000000909043300000000009804350000002007700039000000000057004b000020520000413d000000000645001900000000000604350000001f0550003900000bff055001970000000004450019000000e00510003900000000050504330000000006240049000000e007200039000000000067043500000000650504340000000004540436000000000005004b0000206f0000613d000000000700001900000000084700190000000009760019000000000909043300000000009804350000002007700039000000000057004b000020680000413d000000000645001900000000000604350000010006100039000000000606043300000baa06600197000001000720003900000000006704350000012006100039000000000606043300000120072000390000000000670435000001400610003900000000060604330000014007200039000000000067043500000160061000390000000006060433000001600720003900000000006704350000001f0550003900000bff0350019700000000044300190000000003240049000001800520003900000180011000390000000002010433000000000035043500000000030204330000000001340436000000000003004b000020da0000613d000000000400001900000020022000390000000005020433000000007605043400000baa06600197000000000661043600000000070704330000000000760435000000400650003900000000060604330000004007100039000000000067043500000060065000390000000006060433000000600710003900000000006704350000008006500039000000000606043300000080071000390000000000670435000000a0065000390000000006060433000000a0071000390000000000670435000000c0065000390000000006060433000000c0071000390000000000670435000000e0065000390000000006060433000000e007100039000000000067043500000100065000390000000006060433000001000710003900000000006704350000012006500039000000000606043300000120071000390000000000670435000001400650003900000000060604330000014007100039000000000067043500000160065000390000000006060433000000000006004b0000000006000039000000010600c039000001600710003900000000006704350000018006500039000000000606043300000180071000390000000000670435000001a006500039000000000606043300000baa06600197000001a0071000390000000000670435000001c0065000390000000006060433000001c0071000390000000000670435000001e0065000390000000006060433000001e0071000390000000000670435000002000550003900000000050504330000020006100039000000000056043500000220011000390000000104400039000000000034004b0000208f0000413d000000000001042d000000003101043400000baa01100197000000000112043600000000020304330000000000210435000000000001042d000000004301043400000baa03300197000000000332043600000000040404330000000000430435000000400310003900000000030304330000004004200039000000000034043500000060031000390000000003030433000000600420003900000000003404350000008003100039000000000303043300000080042000390000000000340435000000a002200039000000a00110003900000000010104330000000000120435000000000001042d000d000000000002000600000002001d000400000001001d000000400100043d00000c000010009c0000242b0000813d000001a002100039000000400020043f000001800210003900000060030000390000000000320435000000e0021000390000000000320435000000c0021000390000000000320435000000a0021000390000000000320435000000000231043600000160031000390000000000030435000001400310003900000000000304350000012003100039000000000003043500000100031000390000000000030435000000800310003900000000000304350000006003100039000000000003043500000040011000390000000000010435000000000002043500000006010000290000004001100039000500000001001d0000000002010433000000400900043d00000bbc010000410000000000190435000000000100041400000baa02200197000000040020008c000021260000c13d00000002010003670000000003000031000021390000013d00000b860090009c000d00000009001d00000b86030000410000000003094019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000b8a011001c72e152e100000040f0000000003010019000000600330027000000b860030019d00000b860330019700020000000103550000000100200190000024330000613d0000000d0900002900000bff043001980000001f0530018f0000000002490019000021430000613d000000000601034f0000000007090019000000006806043c0000000007870436000000000027004b0000213f0000c13d000000000005004b000021500000613d000000000141034f0000000304500210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001204350000001f0130003900000bff011001970000000002910019000000000012004b00000000010000390000000101004039000900000002001d00000ba70020009c0000242b0000213d00000001001001900000242b0000c13d0000000901000029000000400010043f00000bad0030009c000024310000213d0000001f0030008c000024310000a13d000000000109043300000ba70010009c000024310000213d000000000293001900000000019100190000001f03100039000000000023004b000000000400001900000bae0400804100000bae0330019700000bae05200197000000000653013f000000000053004b000000000300001900000bae0300404100000bae0060009c000000000304c019000000000003004b000024310000c13d0000000013010434000a00000003001d00000ba70030009c0000242b0000213d0000000a0300002900000005033002100000003f0430003900000ba804400197000000090440002900000ba70040009c0000242b0000213d000000400040043f00000009040000290000000a050000290000000004540436000800000004001d0000000003130019000000000023004b000024310000213d000000000031004b000021960000813d0000000902000029000000001401043400000baa0040009c000024310000213d00000020022000390000000000420435000000000031004b0000218a0000413d00000009010000290000000001010433000a00000001001d00000ba70010009c0000242b0000213d0000000a0100002900000005011002100000003f0210003900000ba802200197000000400300043d0000000002230019000d00000003001d000000000032004b0000000003000039000000010300403900000ba70020009c0000242b0000213d00000001003001900000242b0000c13d000000400020043f0000000d020000290000000a030000290000000005320436000000000003004b000021f20000613d0000000002000019000000400300043d00000beb0030009c0000242b0000213d0000022004300039000000400040043f00000200043000390000000000040435000001e0043000390000000000040435000001c0043000390000000000040435000001a00430003900000000000404350000018004300039000000000004043500000160043000390000000000040435000001400430003900000000000404350000012004300039000000000004043500000100043000390000000000040435000000e0043000390000000000040435000000c0043000390000000000040435000000a0043000390000000000040435000000800430003900000000000404350000006004300039000000000004043500000040043000390000000000040435000000200430003900000000000404350000000000030435000000000452001900000000003404350000002002200039000000000012004b000021ab0000413d0000000003000019000700000005001d00000009010000290000000001010433000000000031004b000024250000a13d0000000502300210000b00000002001d0000000801200029000000000101043300000baa01100197000c00000003001d2e1525b60000040f0000000c0300002900000007050000290000000d020000290000000002020433000000000032004b000024250000a13d0000000b0250002900000000001204350000000d010000290000000001010433000000000031004b000024250000a13d00000001033000390000000a0030006c000021d80000413d00000005010000290000000001010433000000400900043d00000bf802000041000000000029043500000baa01100197000000040290003900000000001204350000000001000414000000040200002900000baa02200197000000040020008c000022020000c13d00000002010003670000000003000031000022150000013d00000b860090009c000c00000009001d00000b86030000410000000003094019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000bb6011001c72e152e100000040f0000000003010019000000600330027000000b860030019d00000b8603300197000200000001035500000001002001900000243f0000613d0000000c0900002900000bff043001980000001f0530018f00000000024900190000221f0000613d000000000601034f0000000007090019000000006806043c0000000007870436000000000027004b0000221b0000c13d000000000005004b0000222c0000613d000000000141034f0000000304500210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001204350000001f0130003900000bff021001970000000001920019000000000021004b0000000002000039000000010200403900000ba70010009c0000242b0000213d00000001002001900000242b0000c13d000000400010043f00000bad0030009c000024310000213d000000200030008c000024310000413d000000000409043300000ba70040009c000024310000213d00000000029300190000000004940019000000000542004900000bad0050009c000024310000213d000000600050008c000024310000413d00000bc30010009c0000242b0000213d0000006005100039000000400050043f000000007604043400000ba70060009c000024310000213d00000000084600190000001f06800039000000000026004b000000000900001900000bae0900804100000bae0a60019700000bae06200197000000000b6a013f00000000006a004b000000000a00001900000bae0a00404100000bae00b0009c000000000a09c01900000000000a004b000024310000c13d000000009808043400000ba70080009c0000242b0000213d0000001f0a80003900000bff0aa001970000003f0aa0003900000bff0aa00197000000000a5a001900000ba700a0009c0000242b0000213d0000004000a0043f0000000000850435000000000a98001900000000002a004b000024310000213d000000800a100039000000000008004b000022750000613d000000000b000019000000000cab0019000000000d9b0019000000000d0d04330000000000dc0435000000200bb0003900000000008b004b0000226e0000413d0000000008a8001900000000000804350000000005510436000000000707043300000ba70070009c000024310000213d00000000074700190000001f08700039000000000028004b000000000900001900000bae0900804100000bae08800197000000000a68013f000000000068004b000000000800001900000bae0800404100000bae00a0009c000000000809c019000000000008004b000024310000c13d000000008707043400000ba70070009c0000242b0000213d0000001f0970003900000bff099001970000003f0990003900000bff0a900197000000400900043d000000000aa9001900000000009a004b000000000b000039000000010b00403900000ba700a0009c0000242b0000213d0000000100b001900000242b0000c13d0000004000a0043f000000000a790436000000000b87001900000000002b004b000024310000213d000000000007004b000022a80000613d000000000b000019000000000cab0019000000000d8b0019000000000d0d04330000000000dc0435000000200bb0003900000000007b004b000022a10000413d00000000077a0019000000000007043500000000009504350000004007400039000000000707043300000ba70070009c000024310000213d00000000044700190000001f07400039000000000027004b000000000800001900000bae0800804100000bae07700197000000000967013f000000000067004b000000000600001900000bae0600404100000bae0090009c000000000608c019000000000006004b000024310000c13d000000006404043400000ba70040009c0000242b0000213d0000001f0740003900000bff077001970000003f0770003900000bff07700197000000400a00043d00000000077a00190000000000a7004b0000000008000039000000010800403900000ba70070009c0000242b0000213d00000001008001900000242b0000c13d000000400070043f00000000074a04360000000008640019000000000028004b000024310000213d000000000004004b000c0000000a001d000022dd0000613d000000000200001900000000087200190000000009620019000000000909043300000000009804350000002002200039000000000042004b000022d60000413d0000000002470019000000000002043500000040021000390000000000a204350000000001010433000800000001001d0000000001050433000300000001001d000000060200002900000080012000390000000001010433000400000001001d00000060012000390000000001010433000700000001001d00000020012000390000000001010433000900000001001d0000000001020433000a00000001001d00000005010000290000000002010433000000400c00043d00000be50100004100000000001c0435000000000100041400000baa05200197000000040050008c000b00000005001d000022ff0000c13d000000200030008c000000200400003900000000040340190000232f0000013d00000b8600c0009c00000b860200004100000000020c4019000000400220021000000b860010009c00000b8601008041000000c001100210000000000121019f00000b8a011001c7000000000205001900060000000c001d2e152e100000040f000000060c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c00190000231c0000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000023180000c13d000000000006004b000023290000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000000c0a0000290000244b0000613d0000000b050000290000001f01400039000000600110018f000000000bc1001900000000001b004b0000000002000039000000010200403900000ba700b0009c0000242b0000213d00000001002001900000242b0000c13d0000004000b0043f000000200030008c000024310000413d00000000020c0433000600000002001d00000baa0020009c000024310000213d00000bf90200004100000000002b04350000000002000414000000040050008c000023770000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c7000000000205001900050000000b001d2e152e100000040f000000050b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000023620000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000235e0000c13d000000000006004b0000236f0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000000c0a000029000024570000613d0000001f01400039000000600110018f0000000b05000029000000000cb1001900000ba700c0009c0000242b0000213d0000004000c0043f000000200030008c000024310000413d00000000020b0433000500000002001d00000bfa0200004100000000002c04350000000002000414000000040050008c000023b60000613d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c7000000000205001900020000000c001d2e152e100000040f000000020c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000023a10000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b0000239d0000c13d000000000006004b000023ae0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000000c0a000029000024630000613d0000001f01400039000000600110018f0000000b05000029000000000bc1001900000ba700b0009c0000242b0000213d0000004000b0043f000000200030008c000024310000413d00000000060c043300000bfb0200004100000000002b04350000000002000414000000040050008c000023f60000613d000100000006001d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c7000000000205001900020000000b001d2e152e100000040f000000020b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000023e00000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000023dc0000c13d000000000006004b000023ed0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000000c0a0000290000246f0000613d0000001f01400039000000600110018f0000000b0500002900000001060000290000000001b1001900000ba70010009c0000242b0000213d000000400010043f000000200030008c000024310000413d00000bea0010009c0000242b0000213d00000000020b0433000001a003100039000000400030043f00000180031000390000000d0400002900000000004304350000016003100039000000000023043500000140021000390000000000620435000001200210003900000005030000290000000000320435000001000210003900000006030000290000000000320435000000e0021000390000000000a20435000000c00210003900000003030000290000000000320435000000a0021000390000000803000029000000000032043500000080021000390000000403000029000000000032043500000060021000390000000703000029000000000032043500000040021000390000000000520435000000090200002900000baa02200197000000200310003900000000002304350000000a020000290000000000210435000000000001042d00000bdc01000041000000000010043f0000003201000039000000040010043f00000bb60100004100002e170001043000000bdc01000041000000000010043f0000004101000039000000040010043f00000bb60100004100002e1700010430000000000100001900002e17000104300000001f0530018f00000b8806300198000000400200043d00000000046200190000247a0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000243a0000c13d0000247a0000013d0000001f0530018f00000b8806300198000000400200043d00000000046200190000247a0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000024460000c13d0000247a0000013d0000001f0530018f00000b8806300198000000400200043d00000000046200190000247a0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000024520000c13d0000247a0000013d0000001f0530018f00000b8806300198000000400200043d00000000046200190000247a0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000245e0000c13d0000247a0000013d0000001f0530018f00000b8806300198000000400200043d00000000046200190000247a0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000246a0000c13d0000247a0000013d0000001f0530018f00000b8806300198000000400200043d00000000046200190000247a0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000024760000c13d000000000005004b000024870000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000b860020009c00000b86020080410000004002200210000000000121019f00002e17000104300002000000000002000000400200043d00000c010020009c000025680000813d0000004003200039000000400030043f00000020032000390000000000030435000000000002043500000bed02000041000000400c00043d00000000002c0435000000000200041400000baa05100197000000040050008c000200000005001d000024a30000c13d0000000003000031000000200030008c00000020040000390000000004034019000024d20000013d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c7000000000205001900010000000c001d2e152e100000040f000000010c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000024c00000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000024bc0000c13d000000000006004b000024cd0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000256e0000613d00000002050000290000001f01400039000000600110018f000000000bc1001900000000001b004b0000000002000039000000010200403900000ba700b0009c000025680000213d0000000100200190000025680000c13d0000004000b0043f0000001f0030008c000025660000a13d00000000020c043300000baa0020009c000025660000213d00000be50400004100000000004b04350000000004000414000000040020008c000025170000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c700010000000b001d2e152e100000040f000000010b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000025030000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000024ff0000c13d000000000006004b000025100000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000258c0000613d0000001f01400039000000600110018f0000000205000029000000000cb1001900000ba700c0009c000025680000213d0000004000c0043f000000200030008c000025660000413d00000000020b043300000baa0020009c000025660000213d00000be70400004100000000004c04350000000404c0003900000000005404350000000004000414000000040020008c000025570000613d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000bb6011001c700010000000c001d2e152e100000040f000000010c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000025430000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b0000253f0000c13d000000000006004b000025500000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000025980000613d0000001f01400039000000600110018f00000002050000290000000001c1001900000ba70010009c000025680000213d000000400010043f000000200030008c000025660000413d00000bc20010009c000025680000213d00000000020c04330000004003100039000000400030043f000000200310003900000000002304350000000000510435000000000001042d000000000100001900002e170001043000000bdc01000041000000000010043f0000004101000039000000040010043f00000bb60100004100002e17000104300000001f0530018f00000b8806300198000000400200043d0000000004620019000025790000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000025750000c13d000000000005004b000025860000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000b860020009c00000b86020080410000004002200210000000000112019f00002e17000104300000001f0530018f00000b8806300198000000400200043d0000000004620019000025a30000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000025930000c13d000025a30000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000025a30000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000259f0000c13d000000000005004b000025b00000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000b860020009c00000b86020080410000004002200210000000000121019f00002e1700010430000f0000000000020000000005010019000000400100043d00000c020010009c00002a6f0000813d0000022002100039000000400020043f00000200021000390000000000020435000001e0021000390000000000020435000001c0021000390000000000020435000001a00210003900000000000204350000018002100039000000000002043500000160021000390000000000020435000001400210003900000000000204350000012002100039000000000002043500000100021000390000000000020435000000e0021000390000000000020435000000c0021000390000000000020435000000a002100039000000000002043500000080021000390000000000020435000000600210003900000000000204350000004002100039000000000002043500000020021000390000000000020435000000000001043500000baa01000041000001000010043f00000bec01000041000000400b00043d00000000001b0435000001000100043d000000000251016f0000000001000414000000040020008c000c00000005001d000025ee0000c13d0000000003000031000000200030008c000000200400003900000000040340190000261c0000013d00000b8600b0009c00000b860300004100000000030b4019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000b8a011001c7000f0000000b001d2e152e100000040f0000000f0b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b00190000260a0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000026060000c13d000000000006004b000026170000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002a930000613d0000000c050000290000001f01400039000000600110018f000000000cb1001900000000001c004b0000000002000039000000010200403900000ba700c0009c00002a6f0000213d000000010020019000002a6f0000c13d0000004000c0043f0000001f0030008c00002a6d0000a13d00000000020b0433000a00000002001d00000bed0200004100000000002c0435000001000200043d000000000252016f0000000004000414000000040020008c000026620000613d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c7000f0000000c001d2e152e100000040f0000000f0c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c00190000264e0000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b0000264a0000c13d000000000006004b0000265b0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002a9f0000613d0000001f01400039000000600110018f0000000c05000029000000000bc1001900000ba700b0009c00002a6f0000213d0000004000b0043f000000200030008c00002a6d0000413d00000000010c0433000f00000001001d00000baa0010009c00002a6d0000213d00000bee0100004100000000061b0436000001000100043d000000000151016f0000000402b000390000000000120435000001000100043d0000000f0210017f0000000001000414000000040020008c0000267b0000c13d000000400030008c00000040040000390000000004034019000026ab0000013d000d00000006001d00000b8600b0009c00000b860300004100000000030b4019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000bb6011001c7000e0000000b001d2e152e100000040f0000000e0b0000290000000003010019000000600330027000000b8603300197000000400030008c000000400400003900000000040340190000001f0640018f000000600740019000000000057b0019000026980000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000026940000c13d000000000006004b000026a50000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002aab0000613d0000000c050000290000000d060000290000001f01400039000000e00110018f000000000cb1001900000ba700c0009c00002a6f0000213d0000004000c0043f000000400030008c00002a6d0000413d00000000020b0433000000000002004b0000000001000039000000010100c039000900000002001d000000000012004b00002a6d0000c13d0000000001060433000800000001001d00000bb90100004100000000001c0435000001000100043d000000000251016f0000000001000414000000040020008c000026c50000c13d0000002004000039000026f30000013d00000b8600c0009c00000b860300004100000000030c4019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000b8a011001c7000e0000000c001d2e152e100000040f0000000e0c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000026e10000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000026dd0000c13d000000000006004b000026ee0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002ab70000613d0000000c050000290000001f01400039000000600110018f000000000bc1001900000ba700b0009c00002a6f0000213d0000004000b0043f000000200030008c00002a6d0000413d00000000020c0433000b00000002001d00000baa0020009c00002a6d0000213d00000bef0200004100000000002b0435000001000200043d0000000b0220017f0000000004000414000000040020008c000027360000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c7000e0000000b001d2e152e100000040f0000000e0b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000027220000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000271e0000c13d000000000006004b0000272f0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002ac30000613d0000001f01400039000000600110018f0000000c05000029000000000ab10019000000c00000043f00000ba700a0009c00002a6f0000213d0000004000a0043f000000200030008c00002a6d0000413d00000000010b0433000000ff0010008c00002a6d0000213d000000c00010043f000000e00000043f00000bf0060000410000002007000039000000000800001900000000006a04350000002401a00039000001000200043d0000000000810435000000000152016f0000000402a000390000000000120435000001000100043d0000000f0210017f0000000001000414000000040020008c0000000004070019000027830000613d000d00000008001d00000b8600a0009c00000b860300004100000000030a4019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000bbb011001c7000e0000000a001d2e152e100000040f0000000e0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000276e0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b0000276a0000c13d0000001f074001900000277b0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002a750000613d0000000c0500002900000bf00600004100000020070000390000000d080000290000001f01400039000000600110018f000000000ba1001900000000001b004b0000000002000039000000010200403900000ba700b0009c00002a6f0000213d000000010020019000002a6f0000c13d0000004000b0043f000000200030008c00002a6d0000413d00000000020a0433000000000002004b0000000004000039000000010400c039000000000042004b00002a6d0000c13d00000000028201cf000000e00400043d000000000224019f000000e00020043f0000000102800039000000ff0820018f000000080080008c000000000a0b0019000027450000a13d00000bf10200004100000000002b0435000001000200043d000000000252016f0000000004000414000000040020008c000027d60000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c7000e0000000b001d2e152e100000040f0000000e0b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000027c20000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000027be0000c13d000000000006004b000027cf0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002acf0000613d0000001f01400039000000600110018f0000000c05000029000000000cb1001900000ba700c0009c00002a6f0000213d0000004000c0043f000000200030008c00002a6d0000413d00000000020b0433000e00000002001d00000bf20200004100000000002c0435000001000200043d000000000252016f0000000004000414000000040020008c000028150000613d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c7000d0000000c001d2e152e100000040f0000000d0c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000028010000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000027fd0000c13d000000000006004b0000280e0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002adb0000613d0000001f01400039000000600110018f0000000c05000029000000000dc1001900000ba700d0009c00002a6f0000213d0000004000d0043f000000200030008c00002a6d0000413d00000000020c0433000d00000002001d00000bf30200004100000000002d0435000001000200043d000000000252016f0000000004000414000000040020008c000028540000613d00000b8600d0009c00000b860100004100000000010d4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c700070000000d001d2e152e100000040f000000070d0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057d0019000028400000613d000000000801034f00000000090d0019000000008a08043c0000000009a90436000000000059004b0000283c0000c13d000000000006004b0000284d0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002ae70000613d0000001f01400039000000600110018f0000000c05000029000000000bd1001900000ba700b0009c00002a6f0000213d0000004000b0043f000000200030008c00002a6d0000413d00000000020d0433000700000002001d00000bf40200004100000000002b0435000001000200043d000000000252016f0000000404b000390000000000240435000001000200043d0000000f0220017f0000000004000414000000040020008c000028970000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000bb6011001c700060000000b001d2e152e100000040f000000060b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000028830000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000287f0000c13d000000000006004b000028900000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002af30000613d0000001f01400039000000600110018f0000000c05000029000000000cb1001900000ba700c0009c00002a6f0000213d0000004000c0043f000000200030008c00002a6d0000413d00000000020b0433000600000002001d00000bf50200004100000000002c0435000001000200043d000000000252016f0000000404c000390000000000240435000001000200043d0000000f0220017f0000000004000414000000040020008c000028da0000613d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000bb6011001c7000f0000000c001d2e152e100000040f0000000f0c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000028c60000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000028c20000c13d000000000006004b000028d30000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002aff0000613d0000001f01400039000000600110018f0000000c05000029000000000bc1001900000ba700b0009c00002a6f0000213d0000004000b0043f000000200030008c00002a6d0000413d00000000020c0433000f00000002001d00000bd00200004100000000002b0435000001000200043d000000000252016f0000000004000414000000040020008c000029190000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c700050000000b001d2e152e100000040f000000050b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000029050000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000029010000c13d000000000006004b000029120000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002b0b0000613d0000001f01400039000000600110018f0000000c05000029000000000cb1001900000ba700c0009c00002a6f0000213d0000004000c0043f000000200030008c00002a6d0000413d00000000020b0433000500000002001d00000bf60200004100000000002c0435000001000200043d000000000252016f0000000004000414000000040020008c000029580000613d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c700040000000c001d2e152e100000040f000000040c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000029440000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000029400000c13d000000000006004b000029510000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002b170000613d0000001f01400039000000600110018f0000000c05000029000000000bc1001900000ba700b0009c00002a6f0000213d0000004000b0043f000000200030008c00002a6d0000413d00000000020c0433000400000002001d00000bd70200004100000000002b0435000001000200043d000000000252016f0000000004000414000000040020008c000029970000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c700030000000b001d2e152e100000040f000000030b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000029830000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000297f0000c13d000000000006004b000029900000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002b230000613d0000001f01400039000000600110018f0000000c05000029000000000cb1001900000ba700c0009c00002a6f0000213d0000004000c0043f000000200030008c00002a6d0000413d00000000020b0433000300000002001d00000bf70200004100000000002c0435000001000200043d000000000252016f0000000004000414000000040020008c000029d60000613d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c700020000000c001d2e152e100000040f000000020c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000029c20000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000029be0000c13d000000000006004b000029cf0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002b2f0000613d0000001f01400039000000600110018f0000000c05000029000000000bc1001900000ba700b0009c00002a6f0000213d0000004000b0043f000000200030008c00002a6d0000413d00000000060c043300000bef0200004100000000002b0435000001000200043d000000000252016f0000000004000414000000040020008c00002a160000613d000100000006001d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c700020000000b001d2e152e100000040f000000020b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900002a010000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000029fd0000c13d000000000006004b00002a0e0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002b3b0000613d0000001f01400039000000600110018f0000000c0500002900000001060000290000000001b10019000000800000043f00000ba70010009c00002a6f0000213d000000400010043f000000200030008c00002a6d0000413d00000000020b0433000000ff0020008c00002a6d0000213d000000800020043f000000a00010043f00000beb0010009c00002a6f0000213d0000022002100039000000400020043f000001000200043d000000000252016f0000000000210435000000a00100043d00000020011000390000000a020000290000000000210435000000a00100043d00000040011000390000000e020000290000000000210435000000a00100043d00000060011000390000000d020000290000000000210435000000a00100043d000000800110003900000007020000290000000000210435000000a00100043d000000a00110003900000006020000290000000000210435000000a00100043d000000c0011000390000000f020000290000000000210435000000a00100043d000000e00110003900000005020000290000000000210435000000a00100043d000001000110003900000004020000290000000000210435000000a00100043d000001200110003900000003020000290000000000210435000000a00100043d00000140011000390000000000610435000000a00100043d000001600110003900000009020000290000000000210435000000a00100043d000001800110003900000008020000290000000000210435000001000100043d0000000b0110017f000000a00200043d000001a0022000390000000000120435000000800100043d000000ff0110018f000000a00200043d000001c0022000390000000000120435000000c00100043d000000ff0110018f000000a00200043d000001e0022000390000000000120435000000a00100043d0000020001100039000000e00200043d0000000000210435000000a00100043d000000000001042d000000000100001900002e170001043000000bdc01000041000000000010043f0000004101000039000000040010043f00000bb60100004100002e17000104300000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002a7c0000c13d000000000005004b00002a8d0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000b860020009c00000b86020080410000004002200210000000000121019f00002e17000104300000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002a9a0000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002aa60000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002ab20000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002abe0000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002aca0000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002ad60000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002ae20000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002aee0000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002afa0000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002b060000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002b120000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002b1e0000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002b2a0000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002b360000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002b420000c13d00002a800000013d0007000000000002000000400300043d00000c030030009c00002cff0000813d000000c004300039000000400040043f000000a004300039000000000004043500000080043000390000000000040435000000600430003900000000000404350000004004300039000000000004043500000020043000390000000000040435000000000003043500000bb503000041000000400c00043d00000000003c043500000baa032001970000000402c00039000700000003001d0000000000320435000000000200041400000baa05100197000000040050008c000600000005001d00002b690000c13d0000000003000031000000200030008c0000002004000039000000000403401900002b980000013d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bb6011001c7000000000205001900050000000c001d2e152e100000040f000000050c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c001900002b860000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b00002b820000c13d000000000006004b00002b930000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002d070000613d00000006050000290000001f01400039000000600110018f000000000bc1001900000000001b004b0000000002000039000000010200403900000ba700b0009c00002cff0000213d000000010020019000002cff0000c13d0000004000b0043f0000001f0030008c00002d050000a13d00000000020c0433000500000002001d00000bb70200004100000000002b04350000000402b00039000000070400002900000000004204350000000002000414000000040050008c00002be00000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bb6011001c7000000000205001900040000000b001d2e152e0b0000040f000000040b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900002bcc0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00002bc80000c13d000000000006004b00002bd90000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002d130000613d0000001f01400039000000600110018f0000000605000029000000000cb1001900000ba700c0009c00002cff0000213d0000004000c0043f000000200030008c00002d050000413d00000000020b0433000400000002001d00000bb80200004100000000002c04350000000402c00039000000070400002900000000004204350000000002000414000000040050008c00002c210000613d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bb6011001c7000000000205001900030000000c001d2e152e0b0000040f000000030c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c001900002c0d0000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b00002c090000c13d000000000006004b00002c1a0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002d1f0000613d0000001f01400039000000600110018f0000000605000029000000000bc1001900000ba700b0009c00002cff0000213d0000004000b0043f000000200030008c00002d050000413d00000000020c0433000300000002001d00000bb90200004100000000002b04350000000002000414000000040050008c00002c5f0000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c7000000000205001900020000000b001d2e152e100000040f000000020b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900002c4b0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00002c470000c13d000000000006004b00002c580000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002d2b0000613d0000001f01400039000000600110018f0000000605000029000000000cb1001900000ba700c0009c00002cff0000213d0000004000c0043f000000200030008c00002d050000413d00000000020b043300000baa0020009c00002d050000213d00000bb50400004100000000004c04350000000406c00039000000070400002900000000004604350000000004000414000000040020008c00002ca20000613d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000bb6011001c7000100000002001d00020000000c001d2e152e100000040f000000020c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c001900002c8d0000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b00002c890000c13d000000000006004b00002c9a0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002d370000613d0000001f01400039000000600110018f00000006050000290000000102000029000000000bc1001900000ba700b0009c00002cff0000213d0000004000b0043f000000200030008c00002d050000413d00000000070c04330000002404b00039000000000054043500000bba0400004100000000004b04350000000406b00039000000070400002900000000004604350000000004000414000000040020008c00002ce50000613d000200000007001d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000bbb011001c700070000000b001d2e152e100000040f000000070b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900002cd00000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00002ccc0000c13d000000000006004b00002cdd0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002d430000613d0000001f01400039000000600110018f000000060500002900000002070000290000000001b1001900000ba70010009c00002cff0000213d000000400010043f000000200030008c00002d050000413d00000bb40010009c00002cff0000213d00000000020b0433000000c003100039000000400030043f000000a0031000390000000000230435000000800210003900000000007204350000006002100039000000030300002900000000003204350000004002100039000000040300002900000000003204350000002002100039000000050300002900000000003204350000000000510435000000000001042d00000bdc01000041000000000010043f0000004101000039000000040010043f00000bb60100004100002e1700010430000000000100001900002e17000104300000001f0530018f00000b8806300198000000400200043d000000000462001900002d4e0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d0e0000c13d00002d4e0000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002d4e0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d1a0000c13d00002d4e0000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002d4e0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d260000c13d00002d4e0000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002d4e0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d320000c13d00002d4e0000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002d4e0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d3e0000c13d00002d4e0000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002d4e0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d4a0000c13d000000000005004b00002d5b0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000b860020009c00000b86020080410000004002200210000000000121019f00002e17000104300007000000000002000400000001001d0000000021010434000300000002001d000500000001001d00000bfd0010009c00002dca0000813d000000050100002900000005011002100000003f0210003900000ba802200197000000400500043d0000000002250019000000000052004b0000000003000039000000010300403900000ba70020009c00002dca0000213d000000010030019000002dca0000c13d000000400020043f00000005020000290000000006250436000000000002004b00002dc20000613d0000000002000019000000400300043d00000beb0030009c00002dca0000213d0000022004300039000000400040043f00000200043000390000000000040435000001e0043000390000000000040435000001c0043000390000000000040435000001a00430003900000000000404350000018004300039000000000004043500000160043000390000000000040435000001400430003900000000000404350000012004300039000000000004043500000100043000390000000000040435000000e0043000390000000000040435000000c0043000390000000000040435000000a0043000390000000000040435000000800430003900000000000404350000006004300039000000000004043500000040043000390000000000040435000000200430003900000000000404350000000000030435000000000426001900000000003404350000002002200039000000000012004b00002d7b0000413d0000000003000019000200000005001d000100000006001d00000004010000290000000001010433000000000031004b00002dc40000a13d0000000502300210000600000002001d0000000301200029000000000101043300000baa01100197000700000003001d2e1525b60000040f0000000703000029000000010600002900000002050000290000000002050433000000000032004b00002dc40000a13d000000060260002900000000001204350000000001050433000000000031004b00002dc40000a13d0000000103300039000000050030006c00002da90000413d0000000001050019000000000001042d00000bdc01000041000000000010043f0000003201000039000000040010043f00000bb60100004100002e170001043000000bdc01000041000000000010043f0000004101000039000000040010043f00000bb60100004100002e1700010430000000010010008c00002dd80000613d000000020010008c00002de60000c13d00000bcf010000410000000000100443000000000100041400002ddb0000013d00000bcd010000410000000000100443000000000100041400000b860010009c00000b8601008041000000c00110021000000bce011001c70000800b020000392e152e100000040f000000010020019000002de50000613d000000000101043b000000000001042d000000000001042f00000bdc01000041000000000010043f0000005101000039000000040010043f00000bb60100004100002e1700010430000000000001042f00000000050100190000000000200443000000050030008c00002dfb0000413d000000040100003900000000020000190000000506200210000000000664001900000005066002700000000006060031000000000161043a0000000102200039000000000031004b00002df30000413d00000b860030009c00000b86030080410000006001300210000000000200041400000b860020009c00000b8602008041000000c002200210000000000112019f00000c04011001c700000000020500192e152e100000040f000000010020019000002e0a0000613d000000000101043b000000000001042d000000000001042f00002e0e002104210000000102000039000000000001042d0000000002000019000000000001042d00002e13002104230000000102000039000000000001042d0000000002000019000000000001042d00002e150000043200002e160001042e00002e170001043000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000000ffffffe009c8f7ec0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000001e13380ae0fcab3000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000100000001000000000000000000000000000000000000000000000000000000000000000000000000007c51b64100000000000000000000000000000000000000000000000000000000c7ad089400000000000000000000000000000000000000000000000000000000e0a67f1000000000000000000000000000000000000000000000000000000000e0a67f1100000000000000000000000000000000000000000000000000000000e1d146fb00000000000000000000000000000000000000000000000000000000c7ad089500000000000000000000000000000000000000000000000000000000d77ebf9600000000000000000000000000000000000000000000000000000000aa5dbd2200000000000000000000000000000000000000000000000000000000aa5dbd2300000000000000000000000000000000000000000000000000000000b3124239000000000000000000000000000000000000000000000000000000007c51b642000000000000000000000000000000000000000000000000000000007c84e3b30000000000000000000000000000000000000000000000000000000047d86a80000000000000000000000000000000000000000000000000000000006857249b000000000000000000000000000000000000000000000000000000006857249c000000000000000000000000000000000000000000000000000000007a27db570000000000000000000000000000000000000000000000000000000047d86a810000000000000000000000000000000000000000000000000000000055dd951500000000000000000000000000000000000000000000000000000000345954db00000000000000000000000000000000000000000000000000000000345954dc000000000000000000000000000000000000000000000000000000003e3e399c000000000000000000000000000000000000000000000000000000000d3ae318000000000000000000000000000000000000000000000000000000001f884fdf310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e0000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000000000000000000000000000000000fffffffffffffedf000000000000000000000000fffffffffffffffffffffffffffffffffffffffff36dba380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000012000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000120000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffe1f000000000000000000000000000000000000000000000000ffffffffffffff3f70a0823100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000017bfdfbc000000000000000000000000000000000000000000000000000000003af9e669000000000000000000000000000000000000000000000000000000006f307dc300000000000000000000000000000000000000000000000000000000dd62ed3e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044000000000000000000000000b0772d0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000120000000000000000061252fd100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff7ff7c618c1000000000000000000000000000000000000000000000000000000001627ee8900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffbf000000000000000000000000000000000000000000000000ffffffffffffff9f02000002000000000000000000000000000000440000000000000000000000008f693ec70000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff81814945000000000000000000000000000000000000000000000000000000002c427b570000000000000000000000000000000000000000000000000000000092a1823500000000000000000000000000000000000000000000000000000000aa5af0fd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffdf7c05a7c500000000000000000000000000000000000000000000000000000000796b89b91644bc98cd93958e4c9038275d622183e25ac5af08cc6b5d95539132020000020000000000000000000000000000000400000000000000000000000042cbb15ccdc3cad6266b0e7a08c0454b23bf29dc2df74b6f3c209e9336465bd147bd3718000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000c097ce7bc90715b34b9f10000000006e657720696e646578206f766572666c6f777300000000000000000000000000000000010000000000000000000000000000000000000000000000000000000008c379a00000000000000000000000000000000000000000000000000000000074c4c1cc0000000000000000000000000000000000000000000000000000000018160ddd000000000000000000000000000000000000000000000000000000006dfd08ca00000000000000000000000000000000000000000000000000000000160c3a030000000000000000000000000000000000000000000000000000000095dd919300000000000000000000000000000000000000000000000000000000552c0971000000000000000000000000000000000000000000000000000000004e487b7100000000000000000000000000000000000000000000000000000000266e0a7f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000440000012000000000000000007aee632d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000002c00000000000000000000000000000000000000000000000000000000000000000fffffffffffffd3f000000000000000000000000000000000000000000000000ffffffffffffff5f0000000000000000000000000000000000000004000001800000000000000000000000000000000000000000000000000000000000000000fffffffffffffe7f7dc0d1d000000000000000000000000000000000000000000000000000000000bbcac55700000000000000000000000000000000000000000000000000000000fc57d4df00000000000000000000000000000000000000000000000000000000d88ff1f40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fffffffffffffffe0000000000000000000000000000000000000000000000000fffffffffffffe5f000000000000000000000000000000000000000000000000fffffffffffffddf182df0f5000000000000000000000000000000000000000000000000000000005fe3b567000000000000000000000000000000000000000000000000000000008e8f294b00000000000000000000000000000000000000000000000000000000313ce56700000000000000000000000000000000000000000000000000000000e85a296000000000000000000000000000000000000000000000000000000000ae9d70b000000000000000000000000000000000000000000000000000000000f8f9da2800000000000000000000000000000000000000000000000000000000173b99040000000000000000000000000000000000000000000000000000000002c3bcbb000000000000000000000000000000000000000000000000000000004a584432000000000000000000000000000000000000000000000000000000008f840ddd000000000000000000000000000000000000000000000000000000003b1d21a200000000000000000000000000000000000000000000000000000000a3aefa2c00000000000000000000000000000000000000000000000000000000e8755446000000000000000000000000000000000000000000000000000000004ada90af00000000000000000000000000000000000000000000000000000000db5c65de00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffe9f0000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000fffffffffffffe3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000000000000000000000000000000000fffffffffffffe60000000000000000000000000000000000000000000000000ffffffffffffffc0000000000000000000000000000000000000000000000000fffffffffffffde0000000000000000000000000000000000000000000000000ffffffffffffff4002000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de74f27c00b5ac0ab41c9ffac27b97334e20a0fbe8993556965b047b8b013894", + "bytecode": "0x00030000000000020036000000000002000000000301034f0000000001030019000000600110027000000dae04100197000200000043035500010000000303550000000100200190000000320000c13d0000008009000039000000400090043f000000040040008c0000005b0000413d000000000543034f000000000203043b000000e00220027000000db70020009c0000005d0000a13d00000db80020009c000000a10000a13d00000db90020009c0000013a0000a13d00000dba0020009c000002f40000613d00000dbb0020009c000001b20000613d00000dbc0020009c0000005b0000c13d0000000001000416000000000001004b0000005b0000c13d0000000001000412001f00000001001d001e00400000003d0000800501000039000000440300003900000000040004150000001f0440008a000000050440021000000dcf0200004136b5368d0000040f36b536700000040f000000400200043d000000000012043500000dae0020009c00000dae02008041000000400120021000000dd0011001c7000036b60001042e0000000001000416000000000001004b0000005b0000c13d0000001f0140003900000daf011001970000010001100039000000400010043f0000001f0240018f00000db0054001980000010001500039000000430000613d0000010006000039000000000703034f000000007807043c0000000006860436000000000016004b0000003f0000c13d000000000002004b000000500000613d000000000353034f0000000302200210000000000501043300000000052501cf000000000525022f000000000303043b0000010002200089000000000323022f00000000022301cf000000000252019f0000000000210435000000600040008c0000005b0000413d000001000100043d000000000001004b0000000002000039000000010200c039000000000021004b0000005b0000c13d000001400200043d00000db10020009c000000dd0000a13d0000000001000019000036b70001043000000dc40020009c000000ba0000213d00000dca0020009c000001000000213d00000dcd0020009c000002420000613d00000dce0020009c0000005b0000c13d000000240040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000101043b00000dd10010009c0000005b0000213d0000002302100039000000000042004b0000005b0000813d0000000402100039000000000223034f000000000202043b001a00000002001d00000dd10020009c0000005b0000213d001900240010003d0000001a0100002900000005021002100000001901200029000000000041004b0000005b0000213d0000003f0120003900000dd20310019700000dd30030009c000006870000213d0000008001300039000000400010043f0000001a04000029000000800040043f000000000004004b0000065e0000c13d00000020020000390000000003210436000000800200043d00000000002304350000004003100039000000000002004b0000009f0000613d000000800400003900000000050000190000000006010019000000000703001900000020044000390000000003040433000000008303043400000db103300197000000000037043500000060036000390000000006080433000000000063043500000040037000390000000105500039000000000025004b0000000006070019000000910000413d00000000021300490000023a0000013d00000dbf0020009c000000e50000213d00000dc20020009c000001540000613d00000dc30020009c0000005b0000c13d000000240040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000101043b00000db10010009c0000005b0000213d36b52d7c0000040f000000400200043d001d00000002001d36b5293c0000040f0000001d0100002900000dae0010009c00000dae01008041000000400110021000000def011001c7000036b60001042e00000dc50020009c0000011d0000213d00000dc80020009c000002aa0000613d00000dc90020009c0000005b0000c13d000000640040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000201043b00000db10020009c0000005b0000213d0000002401300370000000000101043b00000db10010009c0000005b0000213d0000004403300370000000000303043b00000db10030009c0000005b0000213d00000e1404000041000000800040043f000000840010043f000000a40030043f0000000001000414000000040020008c000005f10000c13d0000000003000031000000200030008c00000020040000390000000004034019000006170000013d000001200300043d000000000001004b0000014f0000613d000000000003004b0000031d0000c13d00000db4030000410000000104000039000003260000013d00000dc00020009c0000019f0000613d00000dc10020009c0000005b0000c13d000000440040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000101043b00000db10010009c0000005b0000213d0000002402300370000000000202043b00000db10020009c0000005b0000213d36b534560000040f000000400200043d001d00000002001d36b529420000040f0000001d0100002900000dae0010009c00000dae01008041000000400110021000000ded011001c7000036b60001042e00000dcb0020009c000002d20000613d00000dcc0020009c0000005b0000c13d000000240040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000101043b001600000001001d00000db10010009c0000005b0000213d000000e009000039000000400090043f000000800000043f000000a00000043f0000006001000039000000c00010043f00000df601000041000000e00010043f00000000010004140000001602000029000000040020008c000003ba0000c13d0000000003000031000000000105034f000003c70000013d00000dc60020009c000002e40000613d00000dc70020009c0000005b0000c13d0000000001000416000000000001004b0000005b0000c13d000000440040008c0000005b0000413d0000000401300370000000000201043b00000db10020009c0000005b0000213d0000002401300370000000000101043b001600000001001d00000db10010009c0000005b0000213d002c0db100000045002d00000002001d00000df601000041000000800010043f00000000010004140000001602000029000000040020008c0000056c0000c13d0000000003000031000000000105034f000005780000013d00000dbd0020009c0000030a0000613d00000dbe0020009c0000005b0000c13d0000000001000416000000000001004b0000005b0000c13d0000000001000412002100000001001d002000600000003d000080050100003900000044030000390000000004000415000000210440008a000000050440021000000dcf0200004136b5368d0000040f00000db101100197000000800010043f00000dec01000041000036b60001042e000000000003004b000003250000c13d000000400100043d00000db2020000410000031f0000013d000000440040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000101043b00000dd10010009c0000005b0000213d0000002302100039000000000042004b0000005b0000813d0000000402100039000000000223034f000000000202043b001600000002001d00000dd10020009c0000005b0000213d001500240010003d000000160100002900000005021002100000001501200029000000000041004b0000005b0000213d0000002401300370000000000301043b00000db10030009c0000005b0000213d0000003f0120003900000dd20410019700000dd30040009c000006870000213d0000008001400039000000400010043f0000001605000029000000800050043f000000000005004b0000066f0000c13d00000020020000390000000002210436000000800300043d00000000003204350000004002100039000000000003004b000002390000613d0000008004000039000000000500001900000020044000390000000006040433000000008706043400000db107700197000000000772043600000000080804330000000000870435000000400760003900000000070704330000004008200039000000000078043500000060076000390000000007070433000000600820003900000000007804350000008007600039000000000707043300000080082000390000000000780435000000a0066000390000000006060433000000a0072000390000000000670435000000c0022000390000000105500039000000000035004b000001830000413d000002390000013d000000240040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000101043b00000db10010009c0000005b0000213d36b52e930000040f000000400200043d001d00000002001d36b528240000040f0000001d0100002900000dae0010009c00000dae01008041000000400110021000000dee011001c7000036b60001042e000000240040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000101043b00000dd10010009c0000005b0000213d0000002302100039000000000042004b0000005b0000813d0000000402100039000000000223034f000000000502043b00000dd10050009c000006870000213d00000005025002100000003f0620003900000dd20660019700000dd30060009c000006870000213d0000008006600039000000400060043f000000800050043f00000024011000390000000002120019000000000042004b0000005b0000213d000000000005004b0000000004000019000006240000c13d000a00000004001d00000005014002100000003f0210003900000dd4032001970000000002630019000000000032004b0000000003000039000000010300403900000dd10020009c000006870000213d0000000100300190000006870000c13d000000400020043f0000000a020000290000000005260436000000000002004b001900000006001d0000068d0000c13d000000400100043d00000020020000390000000002210436000000000306043300000000003204350000004002100039000000000003004b000002390000613d0000000004000019000000190800002900000020088000390000000005080433000000007605043400000db106600197000000000662043600000000070704330000000000760435000000400650003900000000060604330000004007200039000000000067043500000060065000390000000006060433000000600720003900000000006704350000008006500039000000000606043300000080072000390000000000670435000000a0065000390000000006060433000000a0072000390000000000670435000000c0065000390000000006060433000000c0072000390000000000670435000000e0065000390000000006060433000000e007200039000000000067043500000100065000390000000006060433000001000720003900000000006704350000012006500039000000000606043300000120072000390000000000670435000001400650003900000000060604330000014007200039000000000067043500000160065000390000000006060433000000000006004b0000000006000039000000010600c039000001600720003900000000006704350000018006500039000000000606043300000180072000390000000000670435000001a006500039000000000606043300000db106600197000001a0072000390000000000670435000001c0065000390000000006060433000001c0072000390000000000670435000001e0065000390000000006060433000001e0072000390000000000670435000002000550003900000000050504330000020006200039000000000056043500000220022000390000000104400039000000000034004b000001ee0000413d000000000212004900000dae0020009c00000dae02008041000000600220021000000dae0010009c00000dae010080410000004001100210000000000112019f000036b60001042e000000440040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000101043b00000db10010009c0000005b0000213d0000002402300370000000000602043b00000dd10060009c0000005b0000213d000000000264004900000dea0020009c0000005b0000213d000000a40020008c0000005b0000413d0000012002000039000000400020043f0000000405600039000000000753034f000000000707043b00000dd10070009c0000005b0000213d00000000076700190000002306700039000000000046004b0000005b0000813d0000000408700039000000000683034f000000000606043b00000dd10060009c000006870000213d0000001f0a60003900000e250aa001970000003f0aa0003900000e250aa0019700000e2400a0009c000006870000213d000001200aa000390000004000a0043f000001200060043f00000000076700190000002407700039000000000047004b0000005b0000213d0000002004800039000000000743034f00000e25086001980000001f0960018f00000140048000390000027d0000613d000001400a000039000000000b07034f00000000bc0b043c000000000aca043600000000004a004b000002790000c13d000000000009004b0000028a0000613d000000000787034f0000000308900210000000000904043300000000098901cf000000000989022f000000000707043b0000010008800089000000000787022f00000000078701cf000000000797019f000000000074043500000140046000390000000000040435000000800020043f0000002002500039000000000423034f000000000404043b00000db10040009c0000005b0000213d000000a00040043f0000002002200039000000000423034f000000000404043b00000db10040009c0000005b0000213d000000c00040043f0000002004200039000000000443034f000000000404043b000000e00040043f0000004002200039000000000223034f000000000202043b000001000020043f000000800200003936b529580000040f0000000002010019000000400100043d001d00000001001d36b5286a0000040f0000001d020000290000000001210049000005260000013d000000440040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000101043b001d00000001001d00000db10010009c0000005b0000213d0000002401300370000000000201043b00000db10020009c0000005b0000213d0000022009000039000000400090043f0000006001000039000000800010043f000000a00000043f000000c00000043f000000e00000043f000001000000043f000001200010043f000001400010043f000001600010043f000001800000043f000001a00000043f000001c00000043f000001e00000043f000002000010043f00000e1601000041000002200010043f000002240020043f00000000010004140000001d02000029000000040020008c0000043c0000c13d0000000003000031000000000105034f000004490000013d000000240040008c0000005b0000413d0000000002000416000000000002004b0000005b0000c13d0000000402300370000000000202043b003600000002001d00000db10020009c0000005b0000213d00000e1e03000041000000800030043f0000000003000414000000040020008c0000033a0000c13d000000000a000031000000000105034f000003460000013d0000000001000416000000000001004b0000005b0000c13d0000000001000412002f00000001001d002e00000000003d0000800501000039000000440300003900000000040004150000002f0440008a000000050440021000000dcf0200004136b5368d0000040f000000800010043f00000dec01000041000036b60001042e000000440040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000201043b00000db10020009c0000005b0000213d0000002401300370000000000301043b00000db10030009c0000005b0000213d00000de801000041000000800010043f000000840030043f0000000003000414000000040020008c000004bc0000c13d0000000003000031000000000105034f000004c90000013d0000000001000416000000000001004b0000005b0000c13d0000000001000412002300000001001d002200200000003d000080050100003900000044030000390000000004000415000000230440008a000000050440021000000dcf0200004136b5368d0000040f000000000001004b0000000001000039000000010100c039000000800010043f00000dec01000041000036b60001042e000000400100043d00000db502000041000000000021043500000dae0010009c00000dae01008041000000400110021000000db3011001c7000036b7000104300000000204000039000000a00010043f000000800030043f000000c00040043f000000e00020043f0000014000000443000001600030044300000020030000390000018000300443000001a0001004430000004001000039000001c000100443000001e00040044300000060010000390000020000100443000002200020044300000100003004430000000401000039000001200010044300000db601000041000036b60001042e00000dae0030009c00000dae03008041000000c00130021000000df7011001c736b536b00000040f0000000003010019000000600330027000000dae0030019d00000dae0a300197000200000001035500000001002001900000052e0000613d00000e2504a001980000001f05a0018f0000008002400039000003500000613d0000008006000039000000000701034f000000007807043c0000000006860436000000000026004b0000034c0000c13d000000000005004b0000035d0000613d000000000441034f0000000305500210000000000602043300000000065601cf000000000656022f000000000404043b0000010005500089000000000454022f00000000045401cf000000000464019f0000000000420435001c000000010353001d0000000a001d0000001f02a0003900000e250220019700000dd30020009c000006870000213d0000008001200039001b00000001001d000000400010043f0000001d0100002900000dea0010009c0000005b0000213d0000001d01000029000000200010008c0000005b0000413d000000800700043d00000dd10070009c0000005b0000213d0000001d0100002900000080041000390000009f02700039000000000042004b000000000600001900000deb0600804100000deb0540019700000deb02200197000000000852013f000000000052004b000000000200001900000deb0200404100000deb0080009c000000000206c019000000000002004b0000005b0000c13d0000008001700039000000000901043300000dd10090009c000006870000213d00000005029002100000003f0820003900000dd2088001970000001b0880002900000dd10080009c000006870000213d000000400080043f0000001b030000290000000000930435000000a0077000390000000008720019000000000048004b0000005b0000213d000000000009004b00000e850000c13d0035001b0000002d0000000001000415000000340110008a00010005001002180000000001000415000000330110008a0002000500100218003400000000003d000000000600001900000005046002100000003f0140003900000dd401100197000000400200043d0000000005210019000000000015004b0000000007000039000000010700403900000dd10050009c000006870000213d0000000100700190000006870000c13d000000400050043f0000000005620436000000000006004b00000ffd0000c13d00000002010000290000000501100270000000000102001f000000400100043d0000002003000039000000000431043600000000030204330000000000340435000000400410003900000005053002100000000005450019000000000003004b000019bb0000c13d00000000021500490000023a0000013d00000dae0010009c00000dae01008041000000c00110021000000e19011001c736b536b00000040f0000000003010019000000600330027000000dae0030019d00000dae0330019700020000000103550000000100200190000005480000613d000000e00900003900000e25053001980000001f0630018f000000e004500039000003d00000613d000000000701034f000000007807043c0000000009890436000000000049004b000003cc0000c13d000000000006004b000003dd0000613d000000000151034f0000000305600210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000001f0130003900000e2501100197001d00000001001d00000e1a0010009c000006870000213d0000001d01000029000000e007100039000000400070043f00000dea0030009c0000005b0000213d000000200030008c0000005b0000413d000000e00100043d00000dd10010009c0000005b0000213d000000e002300039000000ff03100039000000000023004b000000000400001900000deb0400804100000deb0520019700000deb03300197000000000653013f000000000053004b000000000300001900000deb0300404100000deb0060009c000000000304c019000000000003004b0000005b0000c13d000000e003100039000000000403043300000dd10040009c000006870000213d00000005034002100000003f0530003900000dd205500197000000000575001900000dd10050009c000006870000213d000000400050043f000000000047043500000100011000390000000003130019000000000023004b0000005b0000213d000000000004004b000004150000613d0000000002070019000000001401043400000db10040009c0000005b0000213d00000020022000390000000000420435000000000031004b0000040e0000413d001900000007001d00000dcf0100004100000000001004430000000001000412000000040010044300000060010000390000002400100443000000000100041400000dae0010009c00000dae01008041000000c00110021000000df8011001c7000080050200003936b536b00000040f0000000100200190000026890000613d000000000101043b00000db101100197000000160010006b0000042f0000613d00000019050000290000000006050433000000000006004b000000000700001900000f770000c13d0000000000750435000000400200043d00000e1b01000041001d00000002001d000000000012043500000000010004140000001602000029000000040020008c00000ee70000c13d0000000003000031000000200030008c0000002004000039000000000403401900000f130000013d00000dae0010009c00000dae01008041000000c00110021000000e17011001c736b536b00000040f0000000003010019000000600330027000000dae0030019d00000dae0330019700020000000103550000000100200190000005540000613d000002200900003900000e25043001980000001f0630018f0000022002400039000004520000613d000000000701034f000000007807043c0000000009890436000000000029004b0000044e0000c13d000000000006004b0000045f0000613d000000000141034f0000000304600210000000000602043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f00000000001204350000001f0130003900000e250110019700000dd50010009c000006870000213d0000022002100039000000400020043f00000dea0030009c0000005b0000213d000000200030008c0000005b0000413d000002200400043d00000dd10040009c0000005b0000213d00000220063000390000022007400039000000000376004900000dea0030009c0000005b0000213d000000a00030008c0000005b0000413d00000e180020009c000006870000213d000002c003100039000000400030043f000000000807043300000dd10080009c0000005b0000213d00000000077800190000001f08700039000000000068004b000000000900001900000deb0900804100000deb0880019700000deb0a600197000000000ba8013f0000000000a8004b000000000800001900000deb0800404100000deb00b0009c000000000809c019000000000008004b0000005b0000c13d000000008707043400000dd10070009c000006870000213d0000001f0970003900000e25099001970000003f0990003900000e2505900197000000000535001900000dd10050009c000006870000213d000000400050043f00000000007304350000000005870019000000000065004b0000005b0000213d000002e005100039000000000007004b000004a30000613d00000000060000190000000009560019000000000a860019000000000a0a04330000000000a904350000002006600039000000000076004b0000049c0000413d0000000005570019000000000005043500000000003204350000024003400039000000000303043300000db10030009c0000005b0000213d000002400510003900000000003504350000026003400039000000000303043300000db10030009c0000005b0000213d000002600510003900000000003504350000028003400039000000000303043300000280051000390000000000350435000002a001100039000002a003400039000000000303043300000000003104350000001d01000029000002a20000013d00000dae0030009c00000dae03008041000000c00130021000000de9011001c736b536b00000040f0000000003010019000000600330027000000dae0030019d00000dae0330019700020000000103550000000100200190000005600000613d000000800900003900000e25053001980000001f0630018f0000008004500039000004d20000613d000000000701034f000000007807043c0000000009890436000000000049004b000004ce0000c13d000000000006004b000004df0000613d000000000151034f0000000305600210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000001f0130003900000e250110019700000dd30010009c000006870000213d0000008001100039000000400010043f00000dea0030009c0000005b0000213d000000200030008c0000005b0000413d000000800200043d00000dd10020009c0000005b0000213d00000080033000390000009f04200039000000000034004b000000000500001900000deb0500804100000deb0630019700000deb04400197000000000764013f000000000064004b000000000400001900000deb0400404100000deb0070009c000000000405c019000000000004004b0000005b0000c13d0000008004200039000000000504043300000dd10050009c000006870000213d00000005045002100000003f0640003900000dd206600197000000000616001900000dd10060009c000006870000213d000000400060043f0000000000510435000000a0022000390000000004240019000000000034004b0000005b0000213d000000000005004b000005150000613d0000000003010019000000002502043400000db10050009c0000005b0000213d00000020033000390000000000530435000000000042004b0000050e0000413d000000400200043d00000020030000390000000003320436000000000401043300000000004304350000004003200039000000000004004b000005250000613d00000000050000190000002001100039000000000601043300000db10660019700000000036304360000000105500039000000000045004b0000051e0000413d000000000123004900000dae0010009c00000dae01008041000000600110021000000dae0020009c00000dae020080410000004002200210000000000121019f000036b60001042e0000001f05a0018f00000db006a00198000000400200043d0000000004620019000005390000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000005350000c13d000000000005004b000005460000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000006001a00210000006590000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000054f0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000055b0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000005670000c13d0000064b0000013d00000dae0010009c00000dae01008041000000c00110021000000df7011001c736b536b00000040f0000000003010019000000600330027000000dae0030019d00000dae0330019700020000000103550000000100200190000006340000613d00000e25043001980000001f0530018f0000008002400039000005820000613d0000008006000039000000000701034f000000007807043c0000000006860436000000000026004b0000057e0000c13d000000000005004b0000058f0000613d000000000141034f0000000304500210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001204350000001f0130003900000e2501100197001c00000001001d00000dd30010009c000006870000213d0000001c010000290000008001100039001d00000001001d000000400010043f00000dea0030009c0000005b0000213d000000200030008c0000005b0000413d000000800100043d00000dd10010009c0000005b0000213d00000080023000390000009f03100039000000000023004b000000000400001900000deb0400804100000deb0520019700000deb03300197000000000653013f000000000053004b000000000300001900000deb0300404100000deb0060009c000000000304c019000000000003004b0000005b0000c13d0000008003100039000000000403043300000dd10040009c000006870000213d00000005034002100000003f0530003900000dd2055001970000001d0550002900000dd10050009c000006870000213d000000400050043f0000001d050000290000000000450435000000a0011000390000000003130019000000000023004b0000005b0000213d000000000004004b000005c90000613d0000001d02000029000000001401043400000db10040009c0000005b0000213d00000020022000390000000000420435000000000031004b000005c20000413d00000dcf0100004100000000001004430000000001000412000000040010044300000060010000390000002400100443000000000100041400000dae0010009c00000dae01008041000000c00110021000000df8011001c7000080050200003936b536b00000040f0000000100200190000026890000613d000000000101043b00000db101100197000000160010006b000005e30000613d0000001d010000290000000005010433000000000005004b000000000600001900001a940000c13d0000001d010000290000000000610435002b001d0000002d002a00400000003d00000dfa01000041000000400200043d001d00000002001d0000000000120435002900040000003d00000000010004140000001602000029000000040020008c000019480000c13d000000020100036700000000030000310000195a0000013d00000dae0010009c00000dae01008041000000c00110021000000e15011001c736b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000080057001bf000006060000613d0000008008000039000000000901034f000000009a09043c0000000008a80436000000000058004b000006020000c13d000000000006004b000006130000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000006400000613d0000001f01400039000000600110018f00000080011001bf000000400010043f000000200030008c0000005b0000413d000000800200043d00000db10020009c0000005b0000213d0000000000210435000000400110021000000dd0011001c7000036b60001042e000000a004000039000000000513034f000000000505043b00000db10050009c0000005b0000213d00000000045404360000002001100039000000000021004b000006250000413d000000800200043d000000000102001900000dd10020009c000006870000213d000000400600043d0000000004010019000001d20000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000063b0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000006470000c13d000000000005004b000006580000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000dae0020009c00000dae020080410000004002200210000000000112019f000036b70001043000000df10030009c000006870000213d00000000030000190000004004100039000000400040043f000000200410003900000000000404350000000000010435000000a00430003900000000001404350000002003300039000000000023004b00000bd10000813d000000400100043d00000dfd0010009c000006610000a13d000006870000013d00000df00040009c000006870000213d0000000004000019000000c005100039000000400050043f000000a0051000390000000000050435000000800510003900000000000504350000006005100039000000000005043500000040051000390000000000050435000000200510003900000000000504350000000000010435000000a00540003900000000001504350000002004400039000000000024004b00000cbc0000813d000000400100043d00000df10010009c000006720000a13d00000e1301000041000000000010043f0000004101000039000000040010043f00000dd901000041000036b7000104300000000002000019000000400300043d00000dd50030009c000006870000213d0000022004300039000000400040043f00000200043000390000000000040435000001e0043000390000000000040435000001c0043000390000000000040435000001a00430003900000000000404350000018004300039000000000004043500000160043000390000000000040435000001400430003900000000000404350000012004300039000000000004043500000100043000390000000000040435000000e0043000390000000000040435000000c0043000390000000000040435000000a0043000390000000000040435000000800430003900000000000404350000006004300039000000000004043500000040043000390000000000040435000000200430003900000000000404350000000000030435000000000452001900000000003404350000002002200039000000000012004b0000068e0000413d0000000003000019001800000005001d000000800100043d000000000031004b0000268a0000a13d001500000003001d000000400100043d00000dd50010009c000006870000213d00000015020000290000000502200210001400000002001d000000a002200039000000000202043300000db1072001970000022002100039000000400020043f00000200021000390000000000020435000001e0021000390000000000020435000001c0021000390000000000020435000001a00210003900000000000204350000018002100039000000000002043500000160021000390000000000020435000001400210003900000000000204350000012002100039000000000002043500000100021000390000000000020435000000e0021000390000000000020435000000c0021000390000000000020435000000a0021000390000000000020435000000800210003900000000000204350000006002100039000000000002043500000040021000390000000000020435000000200210003900000000000204350000000000010435000000400a00043d00000dd60100004100000000001a04350000000001000414000000040070008c001a00000007001d000006f70000c13d0000000003000031000000200030008c00000020040000390000000004034019000007270000013d00000dae00a0009c00000dae0200004100000000020a4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c70000000002070019001d0000000a001d36b536b00000040f0000001d0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000007130000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b0000070f0000c13d0000001f07400190000007200000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001b6f0000613d000000190600002900000018050000290000001a070000290000001f01400039000000600110018f000000000ba1001900000000001b004b0000000002000039000000010200403900000dd100b0009c000006870000213d0000000100200190000006870000c13d0000004000b0043f000000200030008c0000005b0000413d00000000020a0433001300000002001d00000dd70200004100000000002b04350000000002000414000000040070008c0000076d0000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000000002070019001d0000000b001d36b536b00000040f0000001d0b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b0019000007570000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b000007530000c13d0000001f07400190000007640000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001b7b0000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a07000029000000000ab1001900000dd100a0009c000006870000213d0000004000a0043f000000200030008c0000005b0000413d00000000090b043300000db10090009c0000005b0000213d00000dd80100004100000000081a04360000000401a0003900000000007104350000000001000414000000040090008c001700000009001d000007820000c13d000000400030008c00000040040000390000000004034019000007b50000013d001c00000008001d00000dae00a0009c00000dae0200004100000000020a4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000dd9011001c70000000002090019001d0000000a001d36b536b00000040f0000001d0a0000290000000003010019000000600330027000000dae03300197000000400030008c00000040040000390000000004034019000000600640019000000000056a00190000079f0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b0000079b0000c13d0000001f07400190000007ac0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000170900002900001b870000613d000000190600002900000018050000290000001a070000290000001c080000290000001f01400039000000e00110018f000000000ba1001900000dd100b0009c000006870000213d0000004000b0043f000000400030008c0000005b0000413d00000000020a0433000000000002004b0000000001000039000000010100c039001200000002001d000000000012004b0000005b0000c13d0000000001080433001100000001001d00000dda0100004100000000001b04350000000001000414000000040070008c0000002004000039000007fd0000613d00000dae00b0009c00000dae0200004100000000020b4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c70000000002070019001d0000000b001d36b536b00000040f0000001d0b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b0019000007e80000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b000007e40000c13d0000001f07400190000007f50000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000170900002900001b930000613d000000190600002900000018050000290000001a070000290000001f01400039000000600110018f000000000ab1001900000dd100a0009c000006870000213d0000004000a0043f000000200030008c0000005b0000413d00000000020b0433001600000002001d00000db10020009c0000005b0000213d00000ddb0200004100000000002a043500000000020004140000001604000029000000040040008c000008420000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000001602000029001d0000000a001d36b536b00000040f0000001d0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000082b0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000008270000c13d0000001f07400190000008380000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000170900002900001b9f0000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000000004a1001900000dd10040009c000006870000213d000000400040043f000000200030008c0000005b0000413d00000000010a0433001000000001001d000000ff0010008c0000005b0000213d000000040090008c000008680000c13d000000000100001900000000080000190000002402400039000000000012043500000ddc02000041000000000b2404360000000402400039000000000072043500000dde0040009c000006870000213d0000004000b0043f0000000002040433000000000002004b0000000004000039000000010400c039000000000042004b0000005b0000c13d00000000021201cf000000000882019f0000000101100039000000ff0110018f000000090010008c00000000040b0019000008500000413d0000002001000039000008c00000013d00000000020000190000000008000019001c00000004001d001d00000008001d0000002401400039001b00000002001d000000000021043500000ddc0100004100000000001404350000000401400039000000000071043500000dae0040009c00000dae0100004100000000010440190000004001100210000000000200041400000dae0020009c00000dae02008041000000c002200210000000000112019f00000ddd011001c7000000000209001936b536b00000040f0000001c0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000088f0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b0000088b0000c13d0000001f074001900000089c0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000170900002900000fe50000613d0000001f01400039000000600110018f000000000ba1001900000000001b004b0000000002000039000000010200403900000dd100b0009c000000190600002900000018050000290000001a070000290000001d08000029000006870000213d0000000100200190000006870000c13d0000004000b0043f000000200030008c0000005b0000413d00000000020a0433000000000002004b0000000004000039000000010400c039000000000042004b0000005b0000c13d0000001b0400002900000000024201cf000000000882019f0000000102400039000000ff0220018f000000080020008c00000000040b00190000086a0000a13d00000ddf0200004100000000002b04350000000002000414000000040070008c001d00000008001d000008fa0000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000000002070019001c0000000b001d36b536b00000040f0000001c0b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b0019000008e20000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b000008de0000c13d0000001f07400190000008ef0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000170900002900001bab0000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000001d08000029000000000ab1001900000dd100a0009c000006870000213d0000004000a0043f000000200030008c0000005b0000413d00000000020b0433000000000002004b000009460000613d00000de00200004100000000002a04350000000002000414000000040070008c0000093c0000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000000002070019001b0000000a001d36b536b00000040f0000001b0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000009240000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000009200000c13d0000001f07400190000009310000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000170900002900001c2f0000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000001d080000290000000001a1001900000dd10010009c000006870000213d000000400010043f000000200030008c0000005b0000413d00000000020a0433001c00000002001d000000000a010019000009470000013d001c00000000001d00000de10100004100000000001a04350000000001000414000000040070008c00000020040000390000097f0000613d00000dae00a0009c00000dae0200004100000000020a4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c70000000002070019001b0000000a001d36b536b00000040f0000001b0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000009690000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000009650000c13d0000001f07400190000009760000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000170900002900001bb70000613d000000190600002900000018050000290000001a070000290000001d080000290000001f01400039000000600110018f000000000ba1001900000dd100b0009c000006870000213d0000004000b0043f000000200030008c0000005b0000413d00000000020a0433001b00000002001d00000de20200004100000000002b04350000000002000414000000040070008c000009c20000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000000002070019000f0000000b001d36b536b00000040f0000000f0b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b0019000009aa0000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b000009a60000c13d0000001f07400190000009b70000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000170900002900001bc30000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000001d08000029000000000ab1001900000dd100a0009c000006870000213d0000004000a0043f000000200030008c0000005b0000413d00000000020b0433000f00000002001d00000de30200004100000000002a04350000000402a0003900000000007204350000000002000414000000040090008c00000a050000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c70000000002090019000e0000000a001d36b536b00000040f0000000e0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000009ed0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000009e90000c13d0000001f07400190000009fa0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000170900002900001bcf0000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000001d08000029000000000ba1001900000dd100b0009c000006870000213d0000004000b0043f000000200030008c0000005b0000413d00000000020a0433001700000002001d00000de40200004100000000002b04350000000402b0003900000000007204350000000002000414000000040090008c00000a470000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c70000000002090019000e0000000b001d36b536b00000040f0000000e0b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b001900000a300000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b00000a2c0000c13d0000001f0740019000000a3d0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001bdb0000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000001d08000029000000000ab1001900000dd100a0009c000006870000213d0000004000a0043f000000200030008c0000005b0000413d00000000020b0433000e00000002001d00000de50200004100000000002a04350000000002000414000000040070008c00000a870000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000000002070019000d0000000a001d36b536b00000040f0000000d0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000a700000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000a6c0000c13d0000001f0740019000000a7d0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001be70000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000001d08000029000000000ba1001900000dd100b0009c000006870000213d0000004000b0043f000000200030008c0000005b0000413d00000000020a0433000d00000002001d00000de60200004100000000002b04350000000002000414000000040070008c00000ac70000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000000002070019000c0000000b001d36b536b00000040f0000000c0b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b001900000ab00000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b00000aac0000c13d0000001f0740019000000abd0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001bf30000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000001d08000029000000000ab1001900000dd100a0009c000006870000213d0000004000a0043f000000200030008c0000005b0000413d00000000020b0433000c00000002001d00000ddf0200004100000000002a04350000000002000414000000040070008c00000b070000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000000002070019000b0000000a001d36b536b00000040f0000000b0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000af00000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000aec0000c13d0000001f0740019000000afd0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001bff0000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000001d08000029000000000ba1001900000dd100b0009c000006870000213d0000004000b0043f000000200030008c0000005b0000413d00000000020a0433000b00000002001d00000de70200004100000000002b04350000000002000414000000040070008c00000b470000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000207001900090000000b001d36b536b00000040f000000090b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b001900000b300000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b00000b2c0000c13d0000001f0740019000000b3d0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001c0b0000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000001d08000029000000000ab1001900000dd100a0009c000006870000213d0000004000a0043f000000200030008c0000005b0000413d00000000090b043300000ddb0200004100000000002a04350000000002000414000000040070008c00000b880000613d000900000009001d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000207001900080000000a001d36b536b00000040f000000080a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000b700000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000b6c0000c13d0000001f0740019000000b7d0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000090900002900001c170000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000001d080000290000000001a1001900000dd10010009c000006870000213d000000400010043f000000200030008c0000005b0000413d00000000020a0433000000ff0020008c0000005b0000213d00000dd50010009c000006870000213d0000022003100039000000400030043f000002000310003900000000008304350000001003000029000000ff0330018f000001e0041000390000000000340435000001c0031000390000000000230435000001a002100039000000160300002900000000003204350000018002100039000000110300002900000000003204350000016002100039000000120300002900000000003204350000014002100039000000000092043500000120021000390000000b03000029000000000032043500000100021000390000000c030000290000000000320435000000e0021000390000000d030000290000000000320435000000c0021000390000000e030000290000000000320435000000a0021000390000001703000029000000000032043500000080021000390000000f03000029000000000032043500000060021000390000001b03000029000000000032043500000040021000390000001c030000290000000000320435000000200210003900000013030000290000000000320435000000000071043500000000020604330000001503000029000000000032004b0000268a0000a13d000000140250002900000000001204350000000001060433000000000031004b0000268a0000a13d00000001033000390000000a0030006c000006bb0000413d000001e40000013d0000000003000019001c00000003001d0000000502300210001b00000002001d00000019012000290000000101100367000000000501043b00000db10050009c0000005b0000213d000000400100043d00000dfd0010009c000006870000213d0000004002100039000000400020043f000000200210003900000000000204350000000000010435000000400b00043d00000dd70100004100000000001b04350000000001000414000000040050008c001d00000005001d00000bee0000c13d0000000003000031000000200030008c0000002004000039000000000403401900000c1c0000013d00000dae00b0009c00000dae0200004100000000020b4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c7000000000205001900180000000b001d36b536b00000040f000000180b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b001900000c0a0000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b00000c060000c13d0000001f0740019000000c170000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000019240000613d0000001d050000290000001f01400039000000600110018f000000000ab1001900000000001a004b0000000002000039000000010200403900000dd100a0009c000006870000213d0000000100200190000006870000c13d0000004000a0043f000000200030008c0000005b0000413d00000000020b043300000db10020009c0000005b0000213d00000e1b0400004100000000004a04350000000004000414000000040020008c00000c600000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000db3011001c700180000000a001d36b536b00000040f000000180a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000c4c0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000c480000c13d0000001f0740019000000c590000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000019300000613d0000001f01400039000000600110018f0000001d05000029000000000ba1001900000dd100b0009c000006870000213d0000004000b0043f000000200030008c0000005b0000413d00000000020a043300000db10020009c0000005b0000213d00000e1d0400004100000000004b04350000000404b0003900000000005404350000000004000414000000040020008c00000c9f0000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000dd9011001c700180000000b001d36b536b00000040f000000180b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b001900000c8b0000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b00000c870000c13d0000001f0740019000000c980000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000193c0000613d0000001f01400039000000600110018f0000001d050000290000000001b1001900000dd10010009c000006870000213d000000400010043f000000200030008c0000005b0000413d00000dfd0010009c000006870000213d00000000020b04330000004003100039000000400030043f000000200310003900000000002304350000000000510435000000800200043d0000001c03000029000000000032004b0000268a0000a13d0000001b02000029000000a0022000390000000000120435000000800100043d000000000031004b0000268a0000a13d00000001033000390000001a0030006c00000bd20000413d000000400100043d000000870000013d001d0db10030019b0000000003000019001b00000003001d0000000502300210001a00000002001d00000015012000290000000101100367000000000501043b00000db10050009c0000005b0000213d000000400100043d00000df10010009c000006870000213d000000c002100039000000400020043f000000a0021000390000000000020435000000800210003900000000000204350000006002100039000000000002043500000040021000390000000000020435000000200210003900000000000204350000000000010435000000400b00043d00000df20100004100000000001b04350000000401b000390000001d0200002900000000002104350000000001000414000000040050008c001c00000005001d00000ce50000c13d0000000003000031000000200030008c0000002004000039000000000403401900000d130000013d00000dae00b0009c00000dae0200004100000000020b4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000dd9011001c7000000000205001900190000000b001d36b536b00000040f000000190b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b001900000d010000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b00000cfd0000c13d0000001f0740019000000d0e0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001b0f0000613d0000001c050000290000001f01400039000000600110018f000000000ab1001900000000001a004b0000000002000039000000010200403900000dd100a0009c000006870000213d0000000100200190000006870000c13d0000004000a0043f000000200030008c0000005b0000413d00000000020b0433001900000002001d00000df30200004100000000002a04350000000402a000390000001d0400002900000000004204350000000002000414000000040050008c00000d5a0000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c7000000000205001900180000000a001d36b536ab0000040f000000180a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000d460000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000d420000c13d0000001f0740019000000d530000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001b1b0000613d0000001f01400039000000600110018f0000001c05000029000000000ba1001900000dd100b0009c000006870000213d0000004000b0043f000000200030008c0000005b0000413d00000000020a0433001800000002001d00000df40200004100000000002b04350000000402b000390000001d0400002900000000004204350000000002000414000000040050008c00000d9a0000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c7000000000205001900170000000b001d36b536ab0000040f000000170b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b001900000d860000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b00000d820000c13d0000001f0740019000000d930000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001b270000613d0000001f01400039000000600110018f0000001c05000029000000000ab1001900000dd100a0009c000006870000213d0000004000a0043f000000200030008c0000005b0000413d00000000020b0433001700000002001d00000dda0200004100000000002a04350000000002000414000000040050008c00000dd70000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900140000000a001d36b536b00000040f000000140a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000dc30000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000dbf0000c13d0000001f0740019000000dd00000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001b330000613d0000001f01400039000000600110018f0000001c05000029000000000ba1001900000dd100b0009c000006870000213d0000004000b0043f000000200030008c0000005b0000413d00000000060a043300000db10060009c0000005b0000213d00000df20200004100000000002b04350000000402b000390000001d0400002900000000004204350000000002000414000000040060008c00000e1a0000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c7001300000006001d000000000206001900140000000b001d36b536b00000040f000000140b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b001900000e050000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b00000e010000c13d0000001f0740019000000e120000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001b3f0000613d0000001f01400039000000600110018f0000001c050000290000001306000029000000000ab1001900000dd100a0009c000006870000213d0000004000a0043f000000200030008c0000005b0000413d00000000070b04330000002402a00039000000000052043500000df50200004100000000002a04350000000402a000390000001d0400002900000000004204350000000002000414000000040060008c00000e5d0000613d001300000007001d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000ddd011001c7000000000206001900140000000a001d36b536b00000040f000000140a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000e480000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000e440000c13d0000001f0740019000000e550000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001b4b0000613d0000001f01400039000000600110018f0000001c0500002900000013070000290000000001a1001900000dd10010009c000006870000213d000000400010043f000000200030008c0000005b0000413d00000df10010009c000006870000213d00000000020a0433000000c003100039000000400030043f000000a0031000390000000000230435000000800210003900000000007204350000006002100039000000170300002900000000003204350000004002100039000000180300002900000000003204350000002002100039000000190300002900000000003204350000000000510435000000800200043d0000001b03000029000000000032004b0000268a0000a13d0000001a02000029000000a0022000390000000000120435000000800100043d000000000031004b0000268a0000a13d0000000103300039000000160030006c00000cbe0000413d000000400100043d0000017a0000013d0000001b09000029000000007207043400000dd10020009c0000005b0000213d000000000a120019000000200da000390000000002d4004900000dea0020009c0000005b0000213d000000a00020008c0000005b0000413d000000400b00043d00000e1800b0009c000006870000213d000000a00cb000390000004000c0043f00000000020d043300000dd10020009c0000005b0000213d000000000dd200190000001f02d00039000000000042004b000000000e00001900000deb0e00804100000deb02200197000000000f52013f000000000052004b000000000200001900000deb0200404100000deb00f0009c00000000020ec019000000000002004b0000005b0000c13d00000000ed0d043400000dd100d0009c000006870000213d0000001f02d0003900000e25022001970000003f0220003900000e25022001970000000002c2001900000dd10020009c000006870000213d000000400020043f0000000000dc04350000000002ed0019000000000042004b0000005b0000213d000000c00fb0003900000000000d004b00000ec00000613d00000000020000190000000003f200190000000006e200190000000006060433000000000063043500000020022000390000000000d2004b00000eb90000413d0000000002fd001900000000000204350000000002cb04360000004003a00039000000000c03043300000db100c0009c0000005b0000213d0000000000c204350000006002a00039000000000202043300000db10020009c0000005b0000213d00000020099000390000004003b0003900000000002304350000008002a0003900000000020204330000006003b000390000000000230435000000a002a0003900000000020204330000008003b0003900000000002304350000000000b90435000000000087004b00000e860000413d0000001b010000290000000006010433003500000001001d0000000001000415000000320110008a00010005001002180000000001000415000000310110008a0002000500100218003200000006001d00000dd10060009c0000039b0000a13d000006870000013d0000001d0200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c7000000160200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000001d0570002900000f020000613d000000000801034f0000001d09000029000000008a08043c0000000009a90436000000000059004b00000efe0000c13d000000000006004b00000f0f0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000000ff10000613d0000001f01400039000000600210018f0000001d01200029000000000021004b0000000002000039000000010200403900000dd10010009c0000001909000029000006870000213d0000000100200190000006870000c13d000000400010043f000000200030008c0000005b0000413d0000001d02000029000000000202043300000db10020009c0000005b0000213d000000000609043300000dd10060009c000006870000213d00000005046002100000003f0540003900000dd205500197000000000515001900000dd10050009c000006870000213d000000400050043f0000000005610436000000000006004b00000f400000613d0000000006000019000000400700043d00000dfd0070009c000006870000213d0000004008700039000000400080043f000000200870003900000000000804350000000000070435000000000865001900000000007804350000002006600039000000000046004b00000f330000413d000000400400043d001200000004001d00000dfe0040009c000006870000213d00000012050000290000006004500039000000400040043f0000004004500039001400000004001d000000000014043500000016010000290000000001150436001100000001001d00000000000104350000000001090433000000000001004b001a00000000001d00001c3b0000c13d00000011040000290000001a0100002900000000001404350000002002000039000000400100043d00000000022104360000001203000029000000000303043300000db103300197000000000032043500000000020404330000004003100039000000000023043500000014020000290000000002020433000000600310003900000060040000390000000000430435000000800310003900000000040204330000000000430435000000a003100039000000000004004b0000009f0000613d000000000500001900000020022000390000000006020433000000007606043400000db10660019700000000066304360000000007070433000000000076043500000040033000390000000105500039000000000045004b00000f6b0000413d0000009f0000013d0000001d01000029000001000810003900000df909000041000000000a0000190000000007000019001800000006001d001700000008001d00000f820000013d000000010aa0003900000000006a004b0000042e0000813d00000000010504330000000000a1004b0000268a0000a13d0000000501a00210000000000b81001900000000020b0433000000400c00043d00000000009c0435000000000100041400000db102200197000000040020008c00000f930000c13d0000000003000031000000200030008c0000002004000039000000000403401900000fc90000013d001c0000000b001d001d0000000a001d001a00000007001d00000dae00c0009c00000dae0300004100000000030c4019000000400330021000000dae0010009c00000dae01008041000000c001100210000000000131019f00000db3011001c7001b0000000c001d36b536b00000040f0000001b0c0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056c001900000fb10000613d000000000701034f00000000080c0019000000007907043c0000000008980436000000000058004b00000fad0000c13d0000001f0740019000000fbe0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000190500002900000df9090000410000001d0a0000290000001c0b00002900001b570000613d00000018060000290000001a0700002900000017080000290000001f01400039000000600210018f0000000001c20019000000000021004b0000000002000039000000010200403900000dd10010009c000006870000213d0000000100200190000006870000c13d000000400010043f000000200030008c0000005b0000413d00000000010c0433000000000001004b00000f7f0000613d00000000010504330000000000a1004b0000268a0000a13d000000000071004b0000268a0000a13d0000000501700210000000000181001900000000020b043300000db1022001970000000000210435000000010770003900000f7f0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000fec0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000ff80000c13d0000064b0000013d000000600d0000390000000006000019000000400700043d00000e1f0070009c000006870000213d000001a001700039000000400010043f00000180017000390000000000d10435000000e0017000390000000000d10435000000c0017000390000000000d10435000000a0017000390000000000d104350000000001d70436000001600370003900000000000304350000014003700039000000000003043500000120037000390000000000030435000001000370003900000000000304350000008003700039000000000003043500000060037000390000000000030435000000400370003900000000000304350000000000010435000000000165001900000000007104350000002006600039000000000046004b00000fff0000413d00000002010000290000000501100270000000000102001f003000000000003d000000000400001900000035050000290000000001050433000000000041004b0000268a0000a13d000000400200043d00000e1f0020009c000006870000213d00000005014002100000000001510019000400360000002d00000020011000390000000004010433000001a001200039000000400010043f00000180012000390000000000d10435000000e0012000390000000000d10435000000c0012000390000000000d10435000000a0012000390000000000d104350000000001d20436000001600320003900000000000304350000014003200039000000000003043500000120032000390000000000030435000001000320003900000000000304350000008003200039000000000003043500000060032000390000000000030435000000400220003900000000000204350000000000010435000300000004001d0000004001400039000500000001001d0000000001010433000000400900043d00000df6020000410000000000290435000000000200041400000db101100197001a00000001001d000000040010008c0000001c0100035f0000001d080000290000106f0000613d00000dae0090009c001d00000009001d00000dae010000410000000001094019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000001a0200002936b536b00000040f0000000003010019000000600330027000000dae0030019d00000dae0830019700020000000103550000000100200190000026960000613d000000600d0000390000001d0900002900000e25048001980000000002490019000010780000613d000000000501034f0000000006090019000000005305043c0000000006360436000000000026004b000010740000c13d0000001f05800190000010850000613d000000000141034f0000000303500210000000000402043300000000043401cf000000000434022f000000000101043b0000010003300089000000000131022f00000000013101cf000000000141019f000000000012043500000000030800190000001f0180003900000e250110019700000000040900190000000002910019000000000012004b00000000010000390000000101004039001400000002001d00000dd10020009c000006870000213d0000000100100190000006870000c13d0000001401000029000000400010043f00000dea0030009c0000005b0000213d000000200030008c0000005b0000413d000000000104043300000dd10010009c0000005b0000213d000000000243001900000000014100190000001f03100039000000000023004b000000000400001900000deb0400804100000deb0330019700000deb05200197000000000653013f000000000053004b000000000300001900000deb0300404100000deb0060009c000000000304c019000000000003004b0000005b0000c13d000000001301043400000dd10030009c000006870000213d00000005043002100000003f0540003900000dd205500197000000140550002900000dd10050009c000006870000213d000000400050043f00000014050000290000000003350436000600000003001d0000000003140019000000000023004b0000005b0000213d000000000031004b000010c50000813d0000001402000029000000001401043400000db10040009c0000005b0000213d00000020022000390000000000420435000000000031004b000010be0000413d00000dcf010000410000000000100443000000000100041200000004001004430000002400d00443000000000100041400000dae0010009c00000dae01008041000000c00110021000000df8011001c7000080050200003936b536b00000040f0000000100200190000026890000613d00000014020000290000000004020433000000000101043b00000db1011001970000001a0010006b000010dc0000c13d0000000003040019000000600d000039000011520000013d000000000004004b000000600d0000390000114f0000613d00000000050000190000000003000019001b00000004001d000010e70000013d0000001d050000290000000105500039000000000045004b000011500000813d00000014010000290000000001010433000000000051004b0000268a0000a13d001600000003001d00000005015002100000000601100029001c00000001001d0000000002010433000000400a00043d00000df90100004100000000001a0435000000000100041400000db102200197000000040020008c001d00000005001d000010fd0000c13d0000000003000031000000200030008c000000200400003900000000040340190000112a0000013d00000dae00a0009c00000dae0300004100000000030a4019000000400330021000000dae0010009c00000dae01008041000000c001100210000000000131019f00000db3011001c7001a0000000a001d36b536b00000040f0000001a0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000011180000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000011140000c13d0000001f07400190000011250000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001e4a0000613d0000001f01400039000000600210018f00000000040a00190000000001a20019000000000021004b0000000002000039000000010200403900000dd10010009c000006870000213d0000000100200190000006870000c13d000000400010043f000000200030008c0000005b0000413d0000000001040433000000000001004b00000016030000290000001b04000029000010e30000613d000000140100002900000000010104330000001d05000029000000000051004b0000268a0000a13d000000000031004b0000268a0000a13d000000050130021000000006011000290000001c02000029000000000202043300000db102200197000000000021043500000001033000390000000105500039000000000045004b000010e70000413d000011500000013d000000000300001900000014010000290000000000310435001600000003001d00000dd10030009c000006870000213d000000160100002900000005011002100000003f0210003900000dd202200197000000400300043d0000000002230019001500000003001d000000000032004b0000000003000039000000010300403900000dd10020009c000006870000213d0000000100300190000006870000c13d000000400020043f000000150200002900000016030000290000000002320436001300000002001d000000000003004b000000200700008a000016c40000613d0000000002000019000000400300043d00000dd50030009c000006870000213d0000022004300039000000400040043f00000200043000390000000000040435000001e0043000390000000000040435000001c0043000390000000000040435000001a00430003900000000000404350000018004300039000000000004043500000160043000390000000000040435000001400430003900000000000404350000012004300039000000000004043500000100043000390000000000040435000000e0043000390000000000040435000000c0043000390000000000040435000000a0043000390000000000040435000000800430003900000000000404350000006004300039000000000004043500000040043000390000000000040435000000200430003900000000000404350000000000030435000000130420002900000000003404350000002002200039000000000012004b0000116c0000413d000000000400001900000014010000290000000001010433000000000041004b0000268a0000a13d001700000004001d000000400100043d00000dd50010009c000006870000213d00000017020000290000000503200210001200000003001d0000000602300029000000000202043300000db1052001970000022002100039000000400020043f00000200021000390000000000020435000001e0021000390000000000020435000001c0021000390000000000020435000001a00210003900000000000204350000018002100039000000000002043500000160021000390000000000020435000001400210003900000000000204350000012002100039000000000002043500000100021000390000000000020435000000e0021000390000000000020435000000c0021000390000000000020435000000a0021000390000000000020435000000800210003900000000000204350000006002100039000000000002043500000040021000390000000000020435000000200210003900000000000204350000000000010435000000400a00043d00000dd60100004100000000001a04350000000001000414000000040050008c001a00000005001d000011d50000c13d0000000003000031000000200030008c00000020040000390000000004034019000012040000013d00000dae00a0009c00000dae0200004100000000020a4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c70000000002050019001d0000000a001d36b536b00000040f0000001d0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000011f10000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000011ed0000c13d0000001f07400190000011fe0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001d8a0000613d0000001a050000290000001f01400039000000600110018f00000000060a00190000000004a10019000000000014004b00000000020000390000000102004039001d00000004001d00000dd10040009c000006870000213d0000000100200190000006870000c13d0000001d02000029000000400020043f000000200030008c0000005b0000413d0000000002060433001100000002001d00000dd7020000410000001d0a00002900000000002a04350000000002000414000000040050008c0000124c0000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001936b536b00000040f0000001d0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000012370000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000012330000c13d0000001f07400190000012440000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001d720000613d0000001f01400039000000600110018f0000001a050000290000000001a10019001c00000001001d00000dd10010009c000006870000213d0000001c01000029000000400010043f000000200030008c0000005b0000413d0000001d010000290000000001010433001900000001001d00000db10010009c0000005b0000213d00000dd8010000410000001c0a00002900000000011a0436001b00000001001d0000000401a00039000000000051043500000000010004140000001902000029000000040020008c000012670000c13d000000400030008c00000040040000390000000004034019000012940000013d00000dae00a0009c00000dae0300004100000000030a4019000000400330021000000dae0010009c00000dae01008041000000c001100210000000000131019f00000dd9011001c736b536b00000040f0000001c0a0000290000000003010019000000600330027000000dae03300197000000400030008c00000040040000390000000004034019000000600640019000000000056a0019000012810000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b0000127d0000c13d0000001f074001900000128e0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001d960000613d0000001a050000290000001f01400039000000e00110018f0000000001a10019001d00000001001d00000dd10010009c000006870000213d0000001d01000029000000400010043f000000400030008c0000005b0000413d0000001c010000290000000002010433000000000002004b0000000001000039000000010100c039001000000002001d000000000012004b0000005b0000c13d0000001b010000290000000001010433000f00000001001d00000dda010000410000001d0a00002900000000001a04350000000001000414000000040050008c0000002004000039000012de0000613d00000dae00a0009c00000dae0200004100000000020a4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c7000000000205001936b536b00000040f0000001d0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000012cb0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000012c70000c13d0000001f07400190000012d80000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001d7e0000613d0000001a050000290000001f01400039000000600110018f0000000002a10019001c00000002001d00000dd10020009c000006870000213d0000001c02000029000000400020043f000000200030008c0000005b0000413d0000001d020000290000000002020433001800000002001d00000db10020009c0000005b0000213d00000ddb020000410000001c0a00002900000000002a043500000000020004140000001804000029000000040040008c000013240000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000180200002936b536b00000040f0000001c0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000130f0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b0000130b0000c13d0000001f074001900000131c0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001da20000613d0000001f01400039000000600110018f0000001a050000290000000004a1001900000dd10040009c000006870000213d000000400040043f000000200030008c0000005b0000413d0000001c010000290000000001010433000e00000001001d000000ff0010008c0000005b0000213d0000001901000029000000040010008c0000134c0000c13d000000000100001900000000060000190000002402400039000000000012043500000ddc02000041000000000a2404360000000402400039000000000052043500000dde0040009c000006870000213d0000004000a0043f0000000002040433000000000002004b0000000004000039000000010400c039000000000042004b0000005b0000c13d00000000021201cf000000000662019f0000000101100039000000ff0110018f000000090010008c00000000040a0019000013340000413d0000002001000039000013a20000013d00000000020000190000000006000019001c00000004001d001d00000006001d0000002401400039001b00000002001d000000000021043500000ddc0100004100000000001404350000000401400039000000000051043500000dae0040009c00000dae0100004100000000010440190000004001100210000000000200041400000dae0020009c00000dae02008041000000c002200210000000000112019f00000ddd011001c7000000190200002936b536b00000040f0000001c0b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b0019000013730000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b0000136f0000c13d0000001f07400190000000600d000039000013810000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001b630000613d0000001f01400039000000600110018f000000000ab1001900000000001a004b0000000002000039000000010200403900000dd100a0009c0000001a050000290000001d06000029000006870000213d0000000100200190000006870000c13d0000004000a0043f000000200030008c0000005b0000413d00000000020b0433000000000002004b0000000004000039000000010400c039000000000042004b0000005b0000c13d0000001b0400002900000000024201cf000000000662019f0000000102400039000000ff0220018f000000080020008c00000000040a00190000134e0000a13d00000ddf0200004100000000002a04350000000002000414000000040050008c001d00000006001d000013da0000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000000002050019001c0000000a001d36b536b00000040f0000001c0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000013c40000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000013c00000c13d0000001f07400190000013d10000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001dea0000613d0000001f01400039000000600110018f0000001a050000290000001d060000290000000002a10019001c00000002001d00000dd10020009c000006870000213d0000001c02000029000000400020043f000000200030008c0000005b0000413d00000000020a0433000000000002004b000014270000613d00000de0020000410000001c0a00002900000000002a04350000000002000414000000040050008c0000141c0000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001936b536b00000040f0000001c0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000014060000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000014020000c13d0000001f07400190000014130000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001e260000613d0000001f01400039000000600110018f0000001a050000290000001d060000290000000001a1001900000dd10010009c000006870000213d000000400010043f000000200030008c0000005b0000413d0000001c020000290000000002020433000d00000002001d000000000a010019000014290000013d000d00000000001d0000001c0a00002900000de10100004100000000001a04350000000001000414000000040050008c00000020040000390000145f0000613d00000dae00a0009c00000dae0200004100000000020a4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c70000000002050019001c0000000a001d36b536b00000040f0000001c0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000144b0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000014470000c13d0000001f07400190000014580000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001df60000613d0000001a050000290000001d060000290000001f01400039000000600110018f00000000020a00190000000004a10019001c00000004001d00000dd10040009c000006870000213d0000001c04000029000000400040043f000000200030008c0000005b0000413d0000000002020433000c00000002001d00000de2020000410000001c0a00002900000000002a04350000000002000414000000040050008c000014a30000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001936b536b00000040f0000001c0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000148d0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000014890000c13d0000001f074001900000149a0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001dae0000613d0000001f01400039000000600110018f0000001a050000290000001d060000290000000002a10019001b00000002001d00000dd10020009c000006870000213d0000001b02000029000000400020043f000000200030008c0000005b0000413d0000001c020000290000000002020433000b00000002001d00000de3020000410000001b0a00002900000000002a04350000000402a00039000000000052043500000000040004140000001902000029000000040020008c000014e70000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000dd9011001c736b536b00000040f0000001b0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000014d10000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000014cd0000c13d0000001f07400190000014de0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001e020000613d0000001f01400039000000600110018f0000001a050000290000001d060000290000000002a10019001c00000002001d00000dd10020009c000006870000213d0000001c02000029000000400020043f000000200030008c0000005b0000413d0000001b020000290000000002020433000a00000002001d00000de4020000410000001c0a00002900000000002a04350000000402a00039000000000052043500000000040004140000001902000029000000040020008c0000152b0000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000dd9011001c736b536b00000040f0000001c0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000015150000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000015110000c13d0000001f07400190000015220000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001dba0000613d0000001f01400039000000600110018f0000001a050000290000001d060000290000000002a10019001b00000002001d00000dd10020009c000006870000213d0000001b02000029000000400020043f000000200030008c0000005b0000413d0000001c020000290000000002020433001900000002001d00000de5020000410000001b0a00002900000000002a04350000000002000414000000040050008c0000156d0000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001936b536b00000040f0000001b0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000015570000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000015530000c13d0000001f07400190000015640000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001e0e0000613d0000001f01400039000000600110018f0000001a050000290000001d060000290000000002a10019001c00000002001d00000dd10020009c000006870000213d0000001c02000029000000400020043f000000200030008c0000005b0000413d0000001b020000290000000002020433000900000002001d00000de6020000410000001c0a00002900000000002a04350000000002000414000000040050008c000015af0000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001936b536b00000040f0000001c0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000015990000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000015950000c13d0000001f07400190000015a60000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001dc60000613d0000001f01400039000000600110018f0000001a050000290000001d060000290000000002a10019001b00000002001d00000dd10020009c000006870000213d0000001b02000029000000400020043f000000200030008c0000005b0000413d0000001c020000290000000002020433000800000002001d00000ddf020000410000001b0a00002900000000002a04350000000002000414000000040050008c000015f10000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001936b536b00000040f0000001b0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000015db0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000015d70000c13d0000001f07400190000015e80000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001e1a0000613d0000001f01400039000000600110018f0000001a050000290000001d060000290000000002a10019001c00000002001d00000dd10020009c000006870000213d0000001c02000029000000400020043f000000200030008c0000005b0000413d0000001b020000290000000002020433000700000002001d00000de7020000410000001c0a00002900000000002a04350000000002000414000000040050008c000016330000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001936b536b00000040f0000001c0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000161d0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000016190000c13d0000001f074001900000162a0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001dd20000613d0000001f01400039000000600110018f0000001a050000290000001d060000290000000002a10019001b00000002001d00000dd10020009c000006870000213d0000001b02000029000000400020043f000000200030008c0000005b0000413d0000001c020000290000000002020433001c00000002001d00000ddb020000410000001b0a00002900000000002a04350000000002000414000000040050008c000016750000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001936b536b00000040f0000001b0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000165f0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b0000165b0000c13d0000001f074001900000166c0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001dde0000613d0000001f01400039000000600110018f0000001a050000290000001d060000290000000001a1001900000dd10010009c000006870000213d000000400010043f000000200030008c0000005b0000413d0000001b020000290000000002020433000000ff0020008c0000005b0000213d00000dd50010009c000006870000213d0000022003100039000000400030043f000002000310003900000000006304350000000e03000029000000ff0330018f000001e0041000390000000000340435000001c0031000390000000000230435000001a0021000390000001803000029000000000032043500000180021000390000000f03000029000000000032043500000160021000390000001003000029000000000032043500000140021000390000001c030000290000000000320435000001200210003900000007030000290000000000320435000001000210003900000008030000290000000000320435000000e00210003900000009030000290000000000320435000000c00210003900000019030000290000000000320435000000a0021000390000000a03000029000000000032043500000080021000390000000b03000029000000000032043500000060021000390000000c03000029000000000032043500000040021000390000000d0300002900000000003204350000002002100039000000110300002900000000003204350000000000510435000000150200002900000000020204330000001704000029000000000042004b000000200700008a00000016030000290000268a0000a13d00000012050000290000001302500029000000000012043500000015010000290000000001010433000000000041004b0000268a0000a13d0000000104400039000000000034004b000011980000413d00000005010000290000000001010433000000400900043d00000e2002000041000000000029043500000db101100197000000040290003900000000001204350000000001000414000000040200002900000db102200197000000040020008c000016d40000c13d00000002010003670000000008000031000016e90000013d00000dae0090009c001d00000009001d00000dae030000410000000003094019000000400330021000000dae0010009c00000dae01008041000000c001100210000000000131019f00000dd9011001c736b536b00000040f0000000003010019000000600330027000000dae0030019d00000dae0830019700020000000103550000000100200190000026a40000613d000000200700008a000000600d0000390000001d0900002900000000047801700000000002490019000016f20000613d000000000501034f0000000006090019000000005305043c0000000006360436000000000026004b000016ee0000c13d0000001f05800190000016ff0000613d000000000641034f0000000303500210000000000402043300000000043401cf000000000434022f000000000506043b0000010003300089000000000535022f00000000033501cf000000000343019f0000000000320435001c000000010353001d00000008001d0000001f01800039000000000171016f00000000030900190000000002910019000000000012004b0000000004000039000000010400403900000dd10020009c000006870000213d0000000100400190000006870000c13d000000400020043f0000001d0100002900000dea0010009c0000005b0000213d0000001d01000029000000200010008c0000005b0000413d000000000503043300000dd10050009c0000005b0000213d0000001d043000290000000005350019000000000654004900000dea0060009c0000005b0000213d000000600060008c0000005b0000413d00000dfe0020009c000006870000213d0000006006200039000000400060043f000000008705043400000dd10070009c0000005b0000213d00000000095700190000001f01900039000000000041004b000000000300001900000deb0300804100000deb0110019700000deb07400197000000000a71013f000000000071004b000000000100001900000deb0100404100000deb00a0009c000000000103c019000000000001004b0000005b0000c13d00000000a909043400000dd10090009c000006870000213d0000001f0190003900000e25011001970000003f0110003900000e2501100197000000000b61001900000dd100b0009c000006870000213d0000004000b0043f00000000009604350000000001a90019000000000041004b0000005b0000213d000000800b200039000000000009004b0000174d0000613d000000000c0000190000000001bc00190000000003ac001900000000030304330000000000310435000000200cc0003900000000009c004b000017460000413d0000000001b9001900000000000104350000000006620436000000000808043300000dd10080009c0000005b0000213d00000000085800190000001f01800039000000000041004b000000000300001900000deb0300804100000deb01100197000000000971013f000000000071004b000000000100001900000deb0100404100000deb0090009c000000000103c019000000000001004b0000005b0000c13d000000009808043400000dd10080009c000006870000213d0000001f0180003900000e25011001970000003f0110003900000e2501100197000000400a00043d000000000b1a00190000000000ab004b000000000c000039000000010c00403900000dd100b0009c000006870000213d0000000100c00190000006870000c13d0000004000b0043f000000000b8a04360000000001980019000000000041004b0000005b0000213d000000000008004b000017800000613d000000000c0000190000000001bc001900000000039c001900000000030304330000000000310435000000200cc0003900000000008c004b000017790000413d00000000018b001900000000000104350000000000a604350000004001500039000000000801043300000dd10080009c0000005b0000213d00000000055800190000001f01500039000000000041004b000000000300001900000deb0300804100000deb01100197000000000871013f000000000071004b000000000100001900000deb0100404100000deb0080009c000000000103c019000000000001004b0000005b0000c13d000000007505043400000dd10050009c000006870000213d0000001f0150003900000e25011001970000003f0110003900000e2501100197000000400300043d0000000008130019001800000003001d000000000038004b0000000009000039000000010900403900000dd10080009c000006870000213d0000000100900190000006870000c13d000000400080043f000000180100002900000000085104360000000001750019000000000041004b0000005b0000213d000000000005004b000017b60000613d000000000400001900000000018400190000000003740019000000000303043300000000003104350000002004400039000000000054004b000017af0000413d000000000158001900000000000104350000004001200039000000180300002900000000003104350000000001020433001400000001001d0000000001060433001100000001001d000000030200002900000080012000390000000001010433001200000001001d00000060012000390000000001010433001300000001001d00000020012000390000000001010433001600000001001d0000000001020433001700000001001d00000005010000290000000001010433000000400a00043d00000e1b0200004100000000002a0435000000000300041400000db102100197000000040020008c0000001d01000029001b00000002001d000017da0000c13d000000200010008c00000020040000390000000004014019000018090000013d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0030009c00000dae03008041000000c003300210000000000113019f00000db3011001c7001a0000000a001d36b536b00000040f0000001a0a0000290000000003010019000000600330027000000dae09300197000000200090008c00000020040000390000000004094019000000200640019000000000056a0019000017f50000613d000000000701034f00000000080a0019000000007307043c0000000008380436000000000058004b000017f10000c13d0000001f07400190000018020000613d000000000861034f0000000303700210000000000605043300000000063601cf000000000636022f000000000708043b0000010003300089000000000737022f00000000033701cf000000000363019f0000000000350435000000000009001f001c00000001035300020000000103550000000100200190000000600d000039000026c00000613d001d00000009001d0000001f01400039000000600310018f00000000020a00190000000001a30019000000000031004b00000000040000390000000104004039001a00000001001d00000dd10010009c000006870000213d0000000100400190000006870000c13d0000001a01000029000000400010043f0000001d01000029000000200010008c0000005b0000413d0000000001020433001000000001001d00000db10010009c0000005b0000213d00000e21010000410000001a0a00002900000000001a043500000000040004140000001b02000029000000040020008c000018550000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000db3011001c736b536b00000040f0000001a0a0000290000000003010019000000600330027000000dae09300197000000200090008c00000020040000390000000004094019000000200640019000000000056a00190000183f0000613d000000000701034f00000000080a0019000000007307043c0000000008380436000000000058004b0000183b0000c13d0000001f074001900000184c0000613d000000000861034f0000000303700210000000000605043300000000063601cf000000000636022f000000000708043b0000010003300089000000000737022f00000000033701cf000000000363019f0000000000350435001d00000009001d000000000009001f001c00000001035300020000000103550000000100200190000000600d000039000026d90000613d0000001f01400039000000600310018f0000000001a30019001900000001001d00000dd10010009c000006870000213d0000001901000029000000400010043f0000001d01000029000000200010008c0000005b0000413d0000001a010000290000000001010433000f00000001001d00000e2201000041000000190a00002900000000001a043500000000040004140000001b02000029000000040020008c000018980000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000db3011001c736b536b00000040f000000190a0000290000000003010019000000600330027000000dae09300197000000200090008c00000020040000390000000004094019000000200640019000000000056a0019000018820000613d000000000701034f00000000080a0019000000007307043c0000000008380436000000000058004b0000187e0000c13d0000001f074001900000188f0000613d000000000861034f0000000303700210000000000605043300000000063601cf000000000636022f000000000708043b0000010003300089000000000737022f00000000033701cf000000000363019f0000000000350435001d00000009001d000000000009001f001c00000001035300020000000103550000000100200190000000600d000039000026e60000613d0000001f01400039000000600310018f0000000001a30019001a00000001001d00000dd10010009c000006870000213d0000001a01000029000000400010043f0000001d01000029000000200010008c0000005b0000413d00000019010000290000000001010433001900000001001d00000e23010000410000001a0a00002900000000001a043500000000040004140000001b02000029000000040020008c000018db0000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000db3011001c736b536b00000040f0000001a0a0000290000000003010019000000600330027000000dae09300197000000200090008c00000020040000390000000004094019000000200640019000000000056a0019000018c50000613d000000000701034f00000000080a0019000000007307043c0000000008380436000000000058004b000018c10000c13d0000001f07400190000018d20000613d000000000861034f0000000303700210000000000605043300000000063601cf000000000636022f000000000708043b0000010003300089000000000737022f00000000033701cf000000000363019f0000000000350435001d00000009001d000000000009001f001c00000001035300020000000103550000000100200190000000600d000039000026f30000613d0000001f01400039000000600310018f0000000004a3001900000dd10040009c000006870000213d000000400040043f0000001d01000029000000200010008c0000005b0000413d00000e1f0040009c000006870000213d0000001a010000290000000001010433000001a002400039000000400020043f0000018002400039000000150300002900000000003204350000016002400039000000000012043500000140014000390000001902000029000000000021043500000120014000390000000f020000290000000000210435000001000140003900000010020000290000000000210435000000e00140003900000018020000290000000000210435000000c00140003900000011020000290000000000210435000000a0014000390000001402000029000000000021043500000080014000390000001202000029000000000021043500000060014000390000001302000029000000000021043500000040014000390000001b020000290000000000210435000000160100002900000db101100197000000200240003900000000001204350000001701000029000000000014043500000002010000290000000501100270000000000201003100000000010204330000003005000029000000000051004b0000268a0000a13d00000005015002100000000001120019000000200110003900000000004104350000000001020433000000000051004b0000268a0000a13d003000010050003d0000000104500039000000010100002900000005011002700000000001010031000000000014004b000010260000413d000003ae0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000192b0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000019370000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000019430000c13d0000064b0000013d0000001d0200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c7000000160200002936b536b00000040f0000000003010019000000600330027000000dae0030019d00000dae033001970002000000010355000000010020019000001b030000613d00000e25043001980000001f0530018f0000001d02400029000019640000613d000000000601034f0000001d07000029000000006806043c0000000007870436000000000027004b000019600000c13d000000000005004b000019710000613d000000000141034f0000000304500210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001204350000001f0130003900000e25011001970000001d02100029000000000012004b00000000010000390000000101004039001c00000002001d00000dd10020009c000006870000213d0000000100100190000006870000c13d0000001c01000029000000400010043f00000dea0030009c0000005b0000213d000000200030008c0000005b0000413d0000001d01000029000000000101043300000dd10010009c0000005b0000213d0000001d053000290000001d011000290000001f02100039000000000052004b000000000300001900000deb0300804100000deb0220019700000deb04500197000000000642013f000000000042004b000000000200001900000deb0200404100000deb0060009c000000000203c019000000000002004b0000005b0000c13d000000003201043400000dd10020009c000006870000213d00000005012002100000003f0410003900000dd2044001970000001c0640002900000dd10060009c000006870000213d000000400060043f0000001c0600002900000000002604350000000006310019000000000056004b0000005b0000213d000000000063004b00001d0c0000813d0000001c01000029000000003203043400000db10020009c0000005b0000213d00000020011000390000000000210435000000000063004b000019a80000413d0000001c010000290000000002010433002600000001001d00000dd10020009c000006870000213d0000000001000415000000280110008a000800050010021800000005012002100000003f0310003900000dd20430019700001d100000013d0000000007000019000019c00000013d0000000107700039000000000037004b000003b80000813d0000000008150049000000400880008a00000000048404360000002002200039000000000802043300000000c9080434000001a006000039000000000b650436000001a00a50003900000000d909043400000000009a0435000001c00a500039000000000009004b000019d60000613d000000000e000019000000000fae00190000000006ed0019000000000606043300000000006f0435000000200ee0003900000000009e004b000019cf0000413d0000000006a90019000000000006043500000000060c043300000db10660019700000000006b04350000004006800039000000000606043300000db106600197000000400b50003900000000006b043500000060068000390000000006060433000000600b50003900000000006b043500000080068000390000000006060433000000800b50003900000000006b04350000001f0690003900000e25066001970000000006a600190000000009560049000000a00a500039000000a00b800039000000000b0b043300000000009a043500000000ba0b04340000000009a6043600000000000a004b000019fc0000613d000000000c00001900000000069c0019000000000dcb0019000000000d0d04330000000000d60435000000200cc000390000000000ac004b000019f50000413d00000000069a001900000000000604350000001f06a0003900000e25066001970000000006960019000000c0098000390000000009090433000000000a560049000000c00b5000390000000000ab043500000000ba0904340000000009a6043600000000000a004b00001a120000613d000000000c00001900000000069c0019000000000dcb0019000000000d0d04330000000000d60435000000200cc000390000000000ac004b00001a0b0000413d00000000069a001900000000000604350000001f06a0003900000e25066001970000000006960019000000e0098000390000000009090433000000000a560049000000e00b5000390000000000ab043500000000ba0904340000000009a6043600000000000a004b00001a280000613d000000000c00001900000000069c0019000000000dcb0019000000000d0d04330000000000d60435000000200cc000390000000000ac004b00001a210000413d00000000069a001900000000000604350000010006800039000000000606043300000db106600197000001000b50003900000000006b043500000120068000390000000006060433000001200b50003900000000006b043500000140068000390000000006060433000001400b50003900000000006b043500000160068000390000000006060433000001600b50003900000000006b04350000001f06a0003900000e250660019700000000069600190000000009560049000001800550003900000180088000390000000008080433000000000095043500000000090804330000000005960436000000000009004b000019bd0000613d000000000a0000190000002008800039000000000b08043300000000c60b043400000db1066001970000000006650436000000000c0c04330000000000c604350000004006b000390000000006060433000000400c50003900000000006c04350000006006b000390000000006060433000000600c50003900000000006c04350000008006b000390000000006060433000000800c50003900000000006c0435000000a006b000390000000006060433000000a00c50003900000000006c0435000000c006b000390000000006060433000000c00c50003900000000006c0435000000e006b000390000000006060433000000e00c50003900000000006c04350000010006b000390000000006060433000001000c50003900000000006c04350000012006b000390000000006060433000001200c50003900000000006c04350000014006b000390000000006060433000001400c50003900000000006c04350000016006b000390000000006060433000000000006004b0000000006000039000000010600c039000001600c50003900000000006c04350000018006b000390000000006060433000001800c50003900000000006c0435000001a006b00039000000000606043300000db106600197000001a00c50003900000000006c0435000001c006b000390000000006060433000001c00c50003900000000006c0435000001e006b000390000000006060433000001e00c50003900000000006c04350000020006b000390000000006060433000002000b50003900000000006b04350000022005500039000000010aa0003900000000009a004b00001a480000413d000019bd0000013d0000001c01000029000000a00710003900000df90800004100000000090000190000000006000019001800000005001d001700000007001d00001a9f0000013d0000000109900039000000000059004b000005e10000813d0000001d010000290000000001010433000000000091004b0000268a0000a13d0000000501900210000000000a71001900000000020a0433000000400b00043d00000000008b0435000000000100041400000db102200197000000040020008c00001ab10000c13d0000000003000031000000200030008c0000002004000039000000000403401900001ae60000013d001b0000000a001d001c00000009001d001900000006001d00000dae00b0009c00000dae0300004100000000030b4019000000400330021000000dae0010009c00000dae01008041000000c001100210000000000131019f00000db3011001c7001a0000000b001d36b536b00000040f0000001a0b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b001900001acf0000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b00001acb0000c13d0000001f0740019000001adc0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001c090000290000001b0a00002900001c230000613d00000018050000290000001906000029000000170700002900000df9080000410000001f01400039000000600210018f0000000001b20019000000000021004b0000000002000039000000010200403900000dd10010009c000006870000213d0000000100200190000006870000c13d000000400010043f000000200030008c0000005b0000413d00000000010b0433000000000001004b00001a9c0000613d0000001d010000290000000001010433000000000091004b0000268a0000a13d000000000061004b0000268a0000a13d0000000501600210000000000171001900000000020a043300000db1022001970000000000210435000000010660003900001a9c0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b0a0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b160000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b220000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b2e0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b3a0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b460000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b520000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b5e0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b6a0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b760000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b820000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b8e0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b9a0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001ba60000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001bb20000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001bbe0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001bca0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001bd60000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001be20000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001bee0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001bfa0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001c060000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001c120000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001c1e0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001c2a0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001c360000c13d0000064b0000013d00130db10020019b001b00000000001d001a00000000001d000000400100043d001c00000001001d00000dfd0010009c000006870000213d0000001c020000290000004001200039000000400010043f0000000001020436001800000001001d000000000001043500000000010904330000001b02000029000000000021004b0000268a0000a13d0000000501200210001600200010003d0000001605900029000000000105043300000db1011001970000001c0400002900000000001404350000000001090433000000000021004b0000268a0000a13d0000000002050433000000400a00043d00000e1c0100004100000000001a0435000000000100041400000db102200197000000040020008c001700000005001d00001c630000c13d000000200030008c0000002004000039000000000403401900001c900000013d00000dae00a0009c00000dae0300004100000000030a4019000000400330021000000dae0010009c00000dae01008041000000c001100210000000000131019f00000db3011001c7001d0000000a001d36b536b00000040f0000001d0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900001c7e0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00001c7a0000c13d0000001f0740019000001c8b0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000190900002900001e320000613d0000001f01400039000000600110018f00000000060a00190000000005a10019000000000015004b00000000020000390000000102004039001d00000005001d00000dd10050009c000006870000213d0000000100200190000006870000c13d0000001d02000029000000400020043f000000200040008c0000005b0000413d00000000020904330000001b0020006c00000017020000290000268a0000a13d0000000004060433001500000004001d000000000202043300000e1d040000410000001d050000290000000000450435000000040450003900000db102200197000000000024043500000000040004140000001302000029000000040020008c00001cb60000c13d000000000115001900000dd10010009c000006870000213d000000400010043f00001cea0000013d00000dae0040009c00000dae04008041000000c00140021000000dae0050009c00000dae0300004100000000030540190000004003300210000000000113019f00000dd9011001c736b536b00000040f0000001d0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900001cd00000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00001ccc0000c13d0000001f0740019000001cdd0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000190900002900001e3e0000613d0000001f01400039000000600110018f0000000001a1001900000dd10010009c000006870000213d000000400010043f000000200030008c0000005b0000413d0000001d010000290000000002010433000000150400002900000000014200a9000000000004004b0000001b0500002900001cf40000613d00000000044100d9000000000024004b000026900000c13d00000e090110012a00000018020000290000000000120435000000140100002900000000010104330000000002010433000000000052004b0000268a0000a13d00000016021000290000001c0400002900000000004204350000000001010433000000000051004b0000268a0000a13d000000180100002900000000010104330000001a0010002a000026900000413d001a001a0010002d001b00010050003d00000000010904330000001b0010006b00001c3e0000413d00000f520000013d0026001c0000002d0000000003000415000000250330008a0008000500300218000000400500043d0000000003450019001600000005001d000000000053004b0000000004000039000000010400403900000dd10030009c000006870000213d0000000100400190000006870000c13d000000400030043f00000016030000290000000003230436000000000002004b00001d320000613d00000000020000190000006006000039000000400400043d00000dd30040009c000006870000213d0000008005400039000000400050043f0000006005400039000000000065043500000040054000390000000000050435000000200540003900000000000504350000000000040435000000000523001900000000004504350000002002200039000000000012004b00001d210000413d00000008010000290000000501100270000000160100002f002700000000003d0000001c010000290000000001010433000000000001004b00001e560000c13d000000400100043d00000020020000390000000002210436000000160300002900000000030304330000000000320435000000400410003900000005023002100000000002420019000000000003004b000002390000613d00000080050000390000000006000019000000160c00002900001d4c0000013d0000000106600039000000000036004b000002390000813d0000000007120049000000400770008a0000000004740436000000200cc0003900000000070c0433000000009807043400000db1088001970000000008820436000000000909043300000db109900197000000000098043500000040087000390000000008080433000000400920003900000000008904350000006007700039000000000707043300000060082000390000000000580435000000800920003900000000080704330000000000890435000000a002200039000000000008004b00001d490000613d00000000090000190000002007700039000000000a07043300000000ba0a043400000db10aa00197000000000aa20436000000000b0b04330000000000ba043500000040022000390000000109900039000000000089004b00001d660000413d00001d490000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001d790000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001d850000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001d910000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001d9d0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001da90000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001db50000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001dc10000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001dcd0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001dd90000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001de50000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001df10000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001dfd0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e090000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e150000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e210000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e2d0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e390000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e450000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e510000c13d0000064b0000013d001d00000000001d000000400100043d001a00000001001d00000dd30010009c000006870000213d0000001a020000290000008001200039000000400010043f00000060032000390000006001000039001400000003001d0000000000130435000000400120003900000000000104350000002001200039001500000001001d00000000000104350000000000020435002400000002001d0000001c0100002900000000010104330000001d0010006c0000268a0000a13d0000001d0300002900000005013002100000001c0200002900000000011200190000002001100039001900000001001d000000000101043300000db1011001970000001a0400002900000000001404350000000001020433000000000031004b0000268a0000a13d000000190100002900000000020104330000002a01000029001700000001001d000000000301043300000dfb01000041001b00000003001d0000000000130435001800290000002d000000000100041400000db102200197000000040020008c00001e8c0000c13d0000000003000031000000200030008c0000002004000039000000000403401900001eba0000013d0000001b0300002900000dae0030009c00000dae030080410000004003300210000000180400002900000dae0040009c00000dae040080410000006004400210000000000334019f00000dae0010009c00000dae01008041000000c001100210000000000113019f36b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001b0560002900001ea90000613d000000000701034f0000001b08000029000000007907043c0000000008980436000000000058004b00001ea50000c13d0000001f0740019000001eb60000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027fa0000613d0000001f01400039000000600110018f0000001b02100029000000000012004b0000000004000039000000010400403900000dd10020009c000006870000213d0000000100400190000006870000c13d000000400020043f000000200030008c0000005b0000413d0000001b02000029000000000202043300000db10020009c0000005b0000213d0000002c0220017f000000150400002900000000002404350000001c0200002900000000020204330000001d0020006c0000268a0000a13d000000190200002900000000020204330000001704000029000000000504043300000dfc040000410000000000450435001b00000005001d000000180450002900000db1050000410000002d0550017f001500000005001d0000000000540435000000000400041400000db102200197000000040020008c00001f130000613d0000001b0100002900000dae0010009c00000dae0100804100000040011002100000001803000029000000200330003900000dae0030009c00000dae030080410000006003300210000000000131019f00000dae0040009c00000dae04008041000000c003400210000000000113019f36b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001b0560002900001f000000613d000000000701034f0000001b08000029000000007907043c0000000008980436000000000058004b00001efc0000c13d0000001f0740019000001f0d0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000028060000613d0000001f01400039000000600110018f0000001b02100029000000000012004b0000000001000039000000010100403900000dd10020009c000006870000213d0000000100100190000006870000c13d000000400020043f000000200030008c0000005b0000413d00000017020000290000001a012000290000001b02000029000000000202043300000000002104350000001c0100002900000000010104330000001d0010006c0000268a0000a13d0000002b01000029001b00000001001d0000000012010434000d00000001001d00000dd10020009c000006870000213d00000005012002100000003f0310003900000dd203300197000000400400043d0000000003340019000f00000004001d000000000043004b0000000004000039000000010400403900000dd10030009c000006870000213d0000000100400190000006870000c13d00000019040000290000000004040433001c00000004001d000000400030043f0000000f030000290000000003230436000e00000003001d000000000002004b00001f510000613d0000000002000019000000400300043d00000dfd0030009c000006870000213d0000004004300039000000400040043f0000002004300039000000000004043500000000000304350000000e0420002900000000003404350000002002200039000000000012004b00001f440000413d00000dcf0100004100000000001004430000000001000412000000040010044300000020010000390000002400100443000000000100041400000dae0010009c00000dae01008041000000c00110021000000df8011001c7000080050200003936b536b00000040f0000000100200190000026890000613d0000001b020000290000000002020433000000000002004b0000266e0000613d0000001c02000029001c0db10020019b000000000101043b000900000001001d001d00000000001d000000400100043d001900000001001d00000dfe0010009c000006870000213d00000019020000290000006001200039000000400010043f0000004001200039001100000001001d00000000000104350000000001020436001300000001001d0000000000010435000000400100043d001600000001001d00000dfe0010009c000006870000213d00000016020000290000006001200039000000400010043f0000004001200039001000000001001d00000000000104350000000001020436001200000001001d00000000000104350000001b010000290000000001010433000000090000006b0000001d02000029001400050020021800001fa00000613d0000001d0010006c0000268a0000a13d00000014020000290000000d01200029001700000001001d0000000001010433000000400300043d00000dff020000410000000002230436001800000002001d00000db101100197001a00000003001d0000000402300039000000000012043500000000010004140000001c02000029000000040020008c00001fb70000c13d0000000003000031000000600030008c0000006004000039000000000403401900001fe20000013d0000001d0010006c0000268a0000a13d00000014020000290000000d01200029001700000001001d0000000001010433000000400300043d00000e02020000410000000002230436001800000002001d00000db101100197001a00000003001d0000000402300039000000000012043500000000010004140000001c02000029000000040020008c000020520000c13d0000000003000031000000600030008c000000600400003900000000040340190000207d0000013d0000001a0200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000dd9011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000600030008c0000006004000039000000000403401900000060064001900000001a0560002900001fd10000613d000000000701034f0000001a08000029000000007907043c0000000008980436000000000058004b00001fcd0000c13d0000001f0740019000001fde0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027820000613d0000001f01400039000000e00110018f0000001a02100029000000000012004b0000000004000039000000010400403900000dd10020009c000006870000213d0000000100400190000006870000c13d000000400020043f000000600030008c0000005b0000413d0000001a02000029000000000202043300000e000020009c0000005b0000213d000000180400002900000000040404330000001a05000029000000400550003900000000050504330000001106000029000000000056043500000013050000290000000000450435000000190400002900000000002404350000001b0200002900000000020204330000001d0020006c0000268a0000a13d00000017020000290000000002020433000000400500043d00000e01040000410000000004450436001800000004001d00000db102200197001a00000005001d0000000404500039000000000024043500000000020004140000001c04000029000000040040008c0000203d0000613d0000001a0100002900000dae0010009c00000dae01008041000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000600030008c0000006004000039000000000403401900000060064001900000001a056000290000202a0000613d000000000701034f0000001a08000029000000007907043c0000000008980436000000000058004b000020260000c13d0000001f07400190000020370000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000278e0000613d0000001f01400039000000e00110018f0000001a02100029000000000012004b0000000001000039000000010100403900000dd10020009c000006870000213d0000000100100190000006870000c13d000000400020043f000000600030008c0000005b0000413d0000001a01000029000000000101043300000e000010009c0000005b0000213d0000001a020000290000004002200039000000000402043300000018020000290000000002020433000020f40000013d0000001a0200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000dd9011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000600030008c0000006004000039000000000403401900000060064001900000001a056000290000206c0000613d000000000701034f0000001a08000029000000007907043c0000000008980436000000000058004b000020680000c13d0000001f07400190000020790000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000279a0000613d0000001f01400039000000e00110018f0000001a02100029000000000012004b0000000004000039000000010400403900000dd10020009c000006870000213d0000000100400190000006870000c13d000000400020043f000000600030008c0000005b0000413d0000001a02000029000000000202043300000e000020009c0000005b0000213d0000001804000029000000000404043300000dae0040009c0000005b0000213d0000001a050000290000004005500039000000000505043300000dae0050009c0000005b0000213d0000001106000029000000000056043500000013050000290000000000450435000000190400002900000000002404350000001b0200002900000000020204330000001d0020006c0000268a0000a13d00000017020000290000000002020433000000400500043d00000e03040000410000000004450436001800000004001d00000db102200197001a00000005001d0000000404500039000000000024043500000000020004140000001c04000029000000040040008c000020dc0000613d0000001a0100002900000dae0010009c00000dae01008041000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000600030008c0000006004000039000000000403401900000060064001900000001a05600029000020c90000613d000000000701034f0000001a08000029000000007907043c0000000008980436000000000058004b000020c50000c13d0000001f07400190000020d60000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027a60000613d0000001f01400039000000e00110018f0000001a02100029000000000012004b0000000001000039000000010100403900000dd10020009c000006870000213d0000000100100190000006870000c13d000000400020043f000000600030008c0000005b0000413d0000001a01000029000000000101043300000e000010009c0000005b0000213d0000001802000029000000000202043300000dae0020009c0000005b0000213d0000001a040000290000004004400039000000000404043300000dae0040009c0000005b0000213d0000001005000029000000000045043500000012040000290000000000240435000000160200002900000000001204350000001b0100002900000000010104330000001d0010006c0000268a0000a13d00000014020000290000000d01200029001a00000001001d0000000002010433000000400400043d00000e0401000041001700000004001d0000000000140435000000000100041400000db102200197000000040020008c0000002004000039000021350000613d000000170300002900000dae0030009c00000dae03008041000000400330021000000dae0010009c00000dae01008041000000c001100210000000000131019f00000db3011001c736b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001705600029000021240000613d000000000701034f0000001708000029000000007907043c0000000008980436000000000058004b000021200000c13d0000001f07400190000021310000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000272e0000613d0000001f01400039000000600110018f0000001704100029000000000014004b00000000020000390000000102004039001800000004001d00000dd10040009c000006870000213d0000000100200190000006870000c13d0000001802000029000000400020043f000000200030008c0000005b0000413d000000180200002900000dde0020009c000006870000213d0000001702000029000000000202043300000018050000290000002004500039000000400040043f00000000002504350000001b0200002900000000020204330000001d0020006c0000268a0000a13d0000001a020000290000000002020433000000400500043d00000e0504000041000000000045043500000db104200197001700000005001d0000000402500039000c00000004001d000000000042043500000000020004140000001c04000029000000040040008c0000218c0000613d000000170100002900000dae0010009c00000dae01008041000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001705600029000021790000613d000000000701034f0000001708000029000000007907043c0000000008980436000000000058004b000021750000c13d0000001f07400190000021860000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000273a0000613d0000001f01400039000000600110018f0000001702100029000000000012004b0000000001000039000000010100403900000dd10020009c000006870000213d0000000100100190000006870000c13d000000400020043f000000200030008c0000005b0000413d00000017010000290000000001010433001700000001001d00000dcf0100004100000000001004430000000001000412000000040010044300000040010000390000002400100443000000000100041400000dae0010009c00000dae01008041000000c00110021000000df8011001c7000080050200003936b536b00000040f0000000100200190000026890000613d000000000101043b000000010010008c000021b20000613d000000020010008c000027150000c13d00000e080100004100000000001004430000000001000414000021b50000013d00000e06010000410000000000100443000000000100041400000dae0010009c00000dae01008041000000c00110021000000e07011001c70000800b0200003936b536b00000040f0000000100200190000026890000613d00000011020000290000000004020433000000000101043b000000000041004b00000000020000390000000102002039000000000004004b0000000003000039000000010300c0390000000000230170000000000401601900000013010000290000000001010433001100000004001d000a000000140053000026900000413d0000226a0000613d000000170000006b000022670000613d000000400200043d00000de501000041000b00000002001d000000000012043500000000010004140000000c02000029000000040020008c000021dd0000c13d0000000003000031000000200030008c00000020040000390000000004034019000022080000013d0000000b0200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c70000000c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000000b05600029000021f70000613d000000000701034f0000000b08000029000000007907043c0000000008980436000000000058004b000021f30000c13d0000001f07400190000022040000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027ca0000613d0000001f01400039000000600210018f0000000b01200029000000000021004b0000000002000039000000010200403900000dd10010009c000006870000213d0000000100200190000006870000c13d000000400010043f000000200030008c0000005b0000413d0000000b02000029000000000302043300000e09023000d1000000000003004b0000221d0000613d00000000033200d900000e090030009c000026900000c13d00000018030000290000000003030433000000000003004b0000270f0000613d0000000a0500002900000017045000b900000000055400d9000000170050006c000026900000c13d000000000023004b0000222c0000a13d00000dde0010009c00000000020000190000223c0000a13d000006870000013d00000dde0010009c000006870000213d0000002005100039000000400050043f000000000001043500000e0a054000d1000000000004004b000022370000613d00000000014500d900000e0a0010009c000026900000c13d000000400100043d00000dde0010009c000006870000213d00000000023200d900000000022500d90000002003100039000000400030043f0000000000210435000000400200043d00000dde0020009c000006870000213d000000190300002900000000030304330000002004200039000000400040043f00000e00033001970000000000320435000000400300043d00000dde0030009c000006870000213d0000002004300039000000400040043f000000000003043500000000020204330000000001010433000000000021001a000026900000413d000000400300043d00000dde0030009c000006870000213d00000000022100190000002001300039000000400010043f0000000000230435000000400100043d00000dfd0010009c000006870000213d0000004003100039000000400030043f000000200310003900000e0b0400004100000000004304350000001303000039000000000031043500000e0c0020009c0000271b0000813d000000190100002900000000002104350000001301000029000000110200002900000000002104350000001b0100002900000000010104330000001d0010006c0000268a0000a13d0000001a010000290000000001010433000000400300043d00000e0e02000041000000000023043500000db102100197001700000003001d0000000401300039001100000002001d000000000021043500000000010004140000001c02000029000000040020008c000022810000c13d0000000003000031000000200030008c00000020040000390000000004034019000022ac0000013d000000170200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000dd9011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000017056000290000229b0000613d000000000701034f0000001708000029000000007907043c0000000008980436000000000058004b000022970000c13d0000001f07400190000022a80000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027460000613d0000001f01400039000000600210018f0000001701200029000000000021004b0000000002000039000000010200403900000dd10010009c000006870000213d0000000100200190000006870000c13d000000400010043f000000200030008c0000005b0000413d00000017010000290000000001010433001700000001001d00000dcf0100004100000000001004430000000001000412000000040010044300000040010000390000002400100443000000000100041400000dae0010009c00000dae01008041000000c00110021000000df8011001c7000080050200003936b536b00000040f0000000100200190000026890000613d000000000101043b000000010010008c000022d40000613d000000020010008c000027150000c13d00000e080100004100000000001004430000000001000414000022d70000013d00000e06010000410000000000100443000000000100041400000dae0010009c00000dae01008041000000c00110021000000e07011001c70000800b0200003936b536b00000040f0000000100200190000026890000613d00000010020000290000000004020433000000000101043b000000000041004b00000000020000390000000102002039000000000004004b0000000003000039000000010300c0390000000000230170000000000401601900000012010000290000000001010433001300000004001d000c000000140053000026900000413d000023810000613d000000170000006b0000237e0000613d000000400200043d00000ddf01000041001000000002001d000000000012043500000000010004140000001102000029000000040020008c000022ff0000c13d0000000003000031000000200030008c000000200400003900000000040340190000232a0000013d000000100200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c7000000110200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001005600029000023190000613d000000000701034f0000001008000029000000007907043c0000000008980436000000000058004b000023150000c13d0000001f07400190000023260000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027d60000613d0000001f01400039000000600210018f0000001001200029000000000021004b0000000002000039000000010200403900000dd10010009c000006870000213d0000000100200190000006870000c13d000000400010043f000000200030008c0000005b0000413d0000000c0200002900000017032000b900000000022300d9000000170020006c000026900000c13d00000010020000290000000002020433000000000002004b000023500000613d00000dde0010009c000006870000213d0000002004100039000000400040043f000000000001043500000e0a043000d1000000000003004b0000234b0000613d00000000013400d900000e0a0010009c000026900000c13d000000400100043d00000dde0010009c000006870000213d00000000022400d9000023530000013d00000dde0010009c0000000002000019000006870000213d0000002003100039000000400030043f0000000000210435000000400200043d00000dde0020009c000006870000213d000000160300002900000000030304330000002004200039000000400040043f00000e00033001970000000000320435000000400300043d00000dde0030009c000006870000213d0000002004300039000000400040043f000000000003043500000000020204330000000001010433000000000021001a000026900000413d000000400300043d00000dde0030009c000006870000213d00000000022100190000002001300039000000400010043f0000000000230435000000400100043d00000dfd0010009c000006870000213d0000004003100039000000400030043f000000200310003900000e0b0400004100000000004304350000001303000039000000000031043500000e0c0020009c0000271b0000813d000000160100002900000000002104350000001201000029000000130200002900000000002104350000001b0100002900000000010104330000001d0010006c0000268a0000a13d000000400100043d001300000001001d00000dde0010009c000006870000213d0000001a01000029000000000101043300000db1031001970000001901000029000000000101043300000013040000290000002002400039000000400020043f00000e00011001970000000000140435000000400400043d00000024014000390000001502000029000000000021043500000e0f010000410000000000140435001700000004001d0000000401400039001200000003001d000000000031043500000000010004140000001c02000029000000040020008c000023a60000c13d0000000003000031000000200030008c00000020040000390000000004034019000023d10000013d000000170200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000ddd011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001705600029000023c00000613d000000000701034f0000001708000029000000007907043c0000000008980436000000000058004b000023bc0000c13d0000001f07400190000023cd0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027520000613d0000001f01400039000000600110018f0000001704100029000000000014004b00000000020000390000000102004039001900000004001d00000dd10040009c000006870000213d0000000100200190000006870000c13d0000001902000029000000400020043f000000200030008c0000005b0000413d000000190200002900000dde0020009c000006870000213d0000001702000029000000000202043300000019050000290000002004500039000000400040043f0000000000250435000000400400043d001700000004001d000000000002004b0000247b0000c13d00000013020000290000000002020433001000000002001d00000e10020000410000001704000029000000000024043500000000020004140000001c04000029000000040040008c000024240000613d000000170100002900000dae0010009c00000dae01008041000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001705600029000024110000613d000000000701034f0000001708000029000000007907043c0000000008980436000000000058004b0000240d0000c13d0000001f074001900000241e0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027b20000613d0000001f01400039000000600110018f0000001704100029000000000014004b00000000020000390000000102004039001100000004001d00000dd10040009c000006870000213d0000000100200190000006870000c13d0000001102000029000000400020043f000000200030008c0000005b0000413d0000001702000029000000000202043300000e000020009c0000005b0000213d000000100020006b000024390000813d00000011010000290000247a0000013d00000e10020000410000001104000029000000000024043500000000020004140000001c04000029000000040040008c0000246d0000613d000000110100002900000dae0010009c00000dae01008041000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000011056000290000245a0000613d000000000701034f0000001108000029000000007907043c0000000008980436000000000058004b000024560000c13d0000001f07400190000024670000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027e20000613d0000001f01400039000000600110018f000000110110002900000dd10010009c000006870000213d000000400010043f000000200030008c0000005b0000413d0000001101000029000000000101043300000e000010009c0000005b0000213d00000019020000290000000000120435000000400100043d001700000001001d000000170100002900000dde0010009c000006870000213d00000017020000290000002001200039000000400010043f00000000000204350000001901000029000000000101043300000013020000290000000002020433000000000112004b000026900000413d000000400200043d001300000002001d00000dde0020009c000006870000213d00000013040000290000002002400039000000400020043f0000000000140435000000400200043d00000e11010000410000000000120435001700000002001d00000004012000390000001502000029000000000021043500000000010004140000001202000029000000040020008c0000002004000039000024c70000613d000000170200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000dd9011001c7000000120200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001705600029000024b60000613d000000000701034f0000001708000029000000007907043c0000000008980436000000000058004b000024b20000c13d0000001f07400190000024c30000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000275e0000613d0000001f01400039000000600110018f0000001702100029000000000012004b00000000010000390000000101004039001900000002001d00000dd10020009c000006870000213d0000000100100190000006870000c13d0000001901000029000000400010043f000000200030008c0000005b0000413d0000001701000029000000000201043300000e09012000d1000000000002004b000024de0000613d00000000022100d900000e090020009c000026900000c13d00000018020000290000000002020433000000000002004b0000270f0000613d0000001304000029000000000404043300000000052100d900130000005400ad000000000012004b000024eb0000213d00000013015000f9000000000041004b000026900000c13d0000001b0100002900000000010104330000001d0010006c0000268a0000a13d000000190100002900000dde0010009c000006870000213d0000001a01000029000000000101043300000db1051001970000001601000029000000000101043300000019040000290000002002400039000000400020043f00000e00011001970000000000140435000000400400043d00000024014000390000001502000029000000000021043500000e12010000410000000000140435001700000004001d0000000401400039001600000005001d000000000051043500000000010004140000001c02000029000000040020008c0000002004000039000025360000613d000000170200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000ddd011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001705600029000025250000613d000000000701034f0000001708000029000000007907043c0000000008980436000000000058004b000025210000c13d0000001f07400190000025320000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000276a0000613d0000001f01400039000000600110018f0000001704100029000000000014004b00000000020000390000000102004039001800000004001d00000dd10040009c000006870000213d0000000100200190000006870000c13d0000001802000029000000400020043f000000200030008c0000005b0000413d000000180200002900000dde0020009c000006870000213d0000001702000029000000000202043300000018050000290000002004500039000000400040043f0000000000250435000000400400043d001700000004001d000000000002004b000025e00000c13d00000019020000290000000002020433001100000002001d00000e10020000410000001704000029000000000024043500000000020004140000001c04000029000000040040008c000025890000613d000000170100002900000dae0010009c00000dae01008041000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001705600029000025760000613d000000000701034f0000001708000029000000007907043c0000000008980436000000000058004b000025720000c13d0000001f07400190000025830000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027be0000613d0000001f01400039000000600110018f0000001704100029000000000014004b00000000020000390000000102004039001200000004001d00000dd10040009c000006870000213d0000000100200190000006870000c13d0000001202000029000000400020043f000000200030008c0000005b0000413d0000001702000029000000000202043300000e000020009c0000005b0000213d000000110020006b0000259e0000813d0000001201000029000025df0000013d00000e10020000410000001204000029000000000024043500000000020004140000001c04000029000000040040008c000025d20000613d000000120100002900000dae0010009c00000dae01008041000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001205600029000025bf0000613d000000000701034f0000001208000029000000007907043c0000000008980436000000000058004b000025bb0000c13d0000001f07400190000025cc0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027ee0000613d0000001f01400039000000600110018f000000120110002900000dd10010009c000006870000213d000000400010043f000000200030008c0000005b0000413d0000001201000029000000000101043300000e000010009c0000005b0000213d00000018020000290000000000120435000000400100043d001700000001001d000000170100002900000dde0010009c000006870000213d00000017020000290000002001200039000000400010043f00000000000204350000001801000029000000000101043300000019020000290000000002020433000000000112004b000026900000413d000000400200043d001800000002001d00000dde0020009c000006870000213d00000018040000290000002002400039000000400020043f0000000000140435000000400200043d00000df2010000410000000000120435001900000002001d00000004012000390000001502000029000000000021043500000000010004140000001602000029000000040020008c00000020040000390000262c0000613d000000190200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000dd9011001c7000000160200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000019056000290000261b0000613d000000000701034f0000001908000029000000007907043c0000000008980436000000000058004b000026170000c13d0000001f07400190000026280000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027760000613d0000001f01400039000000600210018f0000001901200029000000000021004b0000000002000039000000010200403900000dd10010009c000006870000213d0000000100200190000006870000c13d000000400010043f000000200030008c0000005b0000413d000000180200002900000000030204330000001902000029000000000402043300000000024300a9000000000004004b000026430000613d00000000044200d9000000000034004b000026900000c13d00000dfd0010009c000006870000213d0000004003100039000000400030043f000000000301043600000000000304350000001b0400002900000000040404330000001d0040006c0000268a0000a13d000000130400002900000e0a0440012a00000e0a0220012a0000001a05000029000000000505043300000db1055001970000000000510435000000000242001900000000002304350000000f0200002900000000020204330000001d0020006c0000268a0000a13d00000014030000290000000e0230002900000000001204350000000f0100002900000000010104330000001d0010006c0000268a0000a13d0000001d02000029001d00010020003d0000001b0100002900000000010104330000001d0010006b00001f690000413d001d00270000002d0000002401000029001a00000001001d001400600010003d0000000801000029000000050110027000160000000100350000000f0100002900000014020000290000000000120435000000160100002900000000010104330000001d0010006c0000268a0000a13d0000001d0300002900000005013002100000001602000029000000000112001900000020011000390000001a0400002900000000004104350000000001020433000000000031004b0000268a0000a13d0000001d02000029002700010020003d00000001022000390000002601000029001c00000001001d0000000001010433001d00000002001d000000000012004b00001e570000413d00001d3a0000013d000000000001042f00000e1301000041000000000010043f0000003201000039000000040010043f00000dd901000041000036b70001043000000e1301000041000000000010043f0000001101000039000000040010043f00000dd901000041000036b700010430000000000301034f0000001f0580018f000000000908001900000db006800198000000400200043d0000000004620019000026b10000613d000000000703034f0000000008020019000000007107043c0000000008180436000000000048004b0000269f0000c13d000026b10000013d000000000301034f0000001f0580018f000000000908001900000db006800198000000400200043d0000000004620019000026b10000613d000000000703034f0000000008020019000000007107043c0000000008180436000000000048004b000026ad0000c13d000000000005004b000026be0000613d000000000163034f0000000303500210000000000504043300000000053501cf000000000535022f000000000101043b0000010003300089000000000131022f00000000013101cf000000000151019f00000000001404350000006001900210000006590000013d0000001f0590018f000000000a09001900000db006900198000000400200043d0000000004620019000026cc0000613d0000001c0700035f0000000008020019000000007107043c0000000008180436000000000048004b000026c80000c13d000000000005004b000005460000613d0000001c0160035f0000000303500210000000000504043300000000053501cf000000000535022f000000000101043b0000010003300089000000000131022f00000000013101cf000000000151019f000005450000013d0000001d010000290000001f0510018f00000db006100198000000400200043d0000000004620019000026ff0000613d0000001c0700035f0000000008020019000000007107043c0000000008180436000000000048004b000026e10000c13d000026ff0000013d0000001d010000290000001f0510018f00000db006100198000000400200043d0000000004620019000026ff0000613d0000001c0700035f0000000008020019000000007107043c0000000008180436000000000048004b000026ee0000c13d000026ff0000013d0000001d010000290000001f0510018f00000db006100198000000400200043d0000000004620019000026ff0000613d0000001c0700035f0000000008020019000000007107043c0000000008180436000000000048004b000026fb0000c13d000000000005004b0000270c0000613d0000001c0160035f0000000303500210000000000504043300000000053501cf000000000535022f000000000101043b0000010003300089000000000131022f00000000013101cf000000000151019f00000000001404350000001d010000290000006001100210000006590000013d00000e1301000041000000000010043f0000001201000039000000040010043f00000dd901000041000036b70001043000000e1301000041000000000010043f0000005101000039000000040010043f00000dd901000041000036b700010430000000400400043d001d00000004001d00000e0d020000410000000000240435000000040240003900000020030000390000000000320435000000240240003936b528120000040f0000001d02000029000000000121004900000dae0010009c00000dae0100804100000dae0020009c00000dae0200804100000060011002100000004002200210000000000121019f000036b7000104300000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027350000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027410000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000274d0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027590000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027650000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027710000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000277d0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027890000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027950000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027a10000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027ad0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027b90000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027c50000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027d10000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027dd0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027e90000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027f50000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000028010000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000280d0000c13d0000064b0000013d00000000430104340000000001320436000000000003004b0000281e0000613d000000000200001900000000051200190000000006240019000000000606043300000000006504350000002002200039000000000032004b000028170000413d000000000213001900000000000204350000001f0230003900000e25022001970000000001210019000000000001042d000000004301043400000db103300197000000000332043600000000040404330000000000430435000000400310003900000000030304330000004004200039000000000034043500000060031000390000000003030433000000600420003900000000003404350000008003100039000000000303043300000080042000390000000000340435000000a0031000390000000003030433000000a0042000390000000000340435000000c0031000390000000003030433000000c0042000390000000000340435000000e0031000390000000003030433000000e004200039000000000034043500000100031000390000000003030433000001000420003900000000003404350000012003100039000000000303043300000120042000390000000000340435000001400310003900000000030304330000014004200039000000000034043500000160031000390000000003030433000000000003004b0000000003000039000000010300c039000001600420003900000000003404350000018003100039000000000303043300000180042000390000000000340435000001a003100039000000000303043300000db103300197000001a0042000390000000000340435000001c0031000390000000003030433000001c0042000390000000000340435000001e0031000390000000003030433000001e00420003900000000003404350000020002200039000002000110003900000000010104330000000000120435000000000001042d000000200300003900000000033104360000000064020434000001a0050000390000000000530435000001c00510003900000000740404340000000000450435000001e005100039000000000004004b0000287d0000613d00000000080000190000000009580019000000000a870019000000000a0a04330000000000a904350000002008800039000000000048004b000028760000413d00000000075400190000000000070435000000000606043300000db106600197000000400710003900000000006704350000004006200039000000000606043300000db10660019700000060071000390000000000670435000000600620003900000000060604330000008007100039000000000067043500000080062000390000000006060433000000a00710003900000000006704350000001f0640003900000e250660019700000000055600190000000006350049000000c007100039000000a0082000390000000008080433000000000067043500000000760804340000000005650436000000000006004b000028a40000613d00000000080000190000000009580019000000000a870019000000000a0a04330000000000a904350000002008800039000000000068004b0000289d0000413d000000000756001900000000000704350000001f0660003900000e250660019700000000055600190000000006350049000000c0072000390000000007070433000000e008100039000000000068043500000000760704340000000005650436000000000006004b000028ba0000613d00000000080000190000000009580019000000000a870019000000000a0a04330000000000a904350000002008800039000000000068004b000028b30000413d000000000756001900000000000704350000001f0660003900000e250660019700000000055600190000000006350049000000e00720003900000000070704330000010008100039000000000068043500000000760704340000000005650436000000000006004b000028d00000613d00000000080000190000000009580019000000000a870019000000000a0a04330000000000a904350000002008800039000000000068004b000028c90000413d000000000756001900000000000704350000010007200039000000000707043300000db107700197000001200810003900000000007804350000012007200039000000000707043300000140081000390000000000780435000001400720003900000000070704330000016008100039000000000078043500000160072000390000000007070433000001800810003900000000007804350000001f0660003900000e250460019700000000045400190000000003340049000001a00110003900000180022000390000000002020433000000000031043500000000030204330000000001340436000000000003004b0000293b0000613d000000000400001900000020022000390000000005020433000000007605043400000db106600197000000000661043600000000070704330000000000760435000000400650003900000000060604330000004007100039000000000067043500000060065000390000000006060433000000600710003900000000006704350000008006500039000000000606043300000080071000390000000000670435000000a0065000390000000006060433000000a0071000390000000000670435000000c0065000390000000006060433000000c0071000390000000000670435000000e0065000390000000006060433000000e007100039000000000067043500000100065000390000000006060433000001000710003900000000006704350000012006500039000000000606043300000120071000390000000000670435000001400650003900000000060604330000014007100039000000000067043500000160065000390000000006060433000000000006004b0000000006000039000000010600c039000001600710003900000000006704350000018006500039000000000606043300000180071000390000000000670435000001a006500039000000000606043300000db106600197000001a0071000390000000000670435000001c0065000390000000006060433000001c0071000390000000000670435000001e0065000390000000006060433000001e0071000390000000000670435000002000550003900000000050504330000020006100039000000000056043500000220011000390000000104400039000000000034004b000028f00000413d000000000001042d000000003101043400000db101100197000000000112043600000000020304330000000000210435000000000001042d000000004301043400000db103300197000000000332043600000000040404330000000000430435000000400310003900000000030304330000004004200039000000000034043500000060031000390000000003030433000000600420003900000000003404350000008003100039000000000303043300000080042000390000000000340435000000a002200039000000a00110003900000000010104330000000000120435000000000001042d000d000000000002000600000002001d000400000001001d000000400100043d00000e260010009c00002d0d0000813d000001a002100039000000400020043f000001800210003900000060090000390000000000920435000000e0021000390000000000920435000000c0021000390000000000920435000000a0021000390000000000920435000000000291043600000160031000390000000000030435000001400310003900000000000304350000012003100039000000000003043500000100031000390000000000030435000000800310003900000000000304350000006003100039000000000003043500000040011000390000000000010435000000000002043500000006010000290000004001100039000500000001001d0000000002010433000000400a00043d00000df60100004100000000001a0435000000000100041400000db102200197000000040020008c000d00000002001d000029880000c13d000000020100036700000000030000310000299c0000013d00000dae00a0009c000c0000000a001d00000dae0300004100000000030a4019000000400330021000000dae0010009c00000dae01008041000000c001100210000000000131019f00000db3011001c736b536b00000040f0000000003010019000000600330027000000dae0030019d00000dae033001970002000000010355000000010020019000002d340000613d00000060090000390000000c0a00002900000e25043001980000001f0530018f00000000024a0019000029a60000613d000000000601034f00000000070a0019000000006806043c0000000007870436000000000027004b000029a20000c13d000000000005004b000029b30000613d000000000141034f0000000304500210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001204350000001f0130003900000e25011001970000000002a10019000000000012004b00000000010000390000000101004039000c00000002001d00000dd10020009c00002d0d0000213d000000010010019000002d0d0000c13d0000000c01000029000000400010043f00000dea0030009c00002d130000213d0000001f0030008c00002d130000a13d00000000010a043300000dd10010009c00002d130000213d0000000002a300190000000001a100190000001f03100039000000000023004b000000000400001900000deb0400804100000deb0330019700000deb05200197000000000653013f000000000053004b000000000300001900000deb0300404100000deb0060009c000000000304c019000000000003004b00002d130000c13d000000001301043400000dd10030009c00002d0d0000213d00000005043002100000003f0540003900000dd2055001970000000c0550002900000dd10050009c00002d0d0000213d000000400050043f0000000c050000290000000003350436000900000003001d0000000003140019000000000023004b00002d130000213d000000000031004b000029f10000813d0000000c02000029000000001401043400000db10040009c00002d130000213d00000020022000390000000000420435000000000031004b000029ea0000413d00000dcf010000410000000000100443000000000100041200000004001004430000002400900443000000000100041400000dae0010009c00000dae01008041000000c00110021000000df8011001c7000080050200003936b536b00000040f000000010020019000002d330000613d0000000c020000290000000006020433000000000101043b00000db1011001970000000d0010006b00002a070000c13d000000000506001900002a7c0000013d000000000006004b00002a790000613d00000df90700004100000000080000190000000005000019000700000006001d00002a170000013d00000005015002100000000901100029000000000209043300000db102200197000000000021043500000001055000390000000108800039000000000068004b00002a7a0000813d0000000c010000290000000001010433000000000081004b00002a730000a13d000000050180021000000009091000290000000002090433000000400a00043d00000000007a0435000000000100041400000db102200197000000040020008c00002a290000c13d0000000003000031000000200030008c0000002004000039000000000403401900002a5d0000013d000d00000009001d000a00000008001d000800000005001d00000dae00a0009c00000dae0300004100000000030a4019000000400330021000000dae0010009c00000dae01008041000000c001100210000000000131019f00000db3011001c7000b0000000a001d36b536b00000040f0000000b0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900002a470000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00002a430000c13d0000001f0740019000002a540000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000000d0900002900002d150000613d0000000805000029000000070600002900000df9070000410000000a080000290000001f01400039000000600210018f0000000001a20019000000000021004b0000000002000039000000010200403900000dd10010009c00002d0d0000213d000000010020019000002d0d0000c13d000000400010043f000000200030008c00002d130000413d00000000010a0433000000000001004b00002a140000613d0000000c010000290000000001010433000000000081004b00002a730000a13d000000000051004b00002a0e0000213d00000e1301000041000000000010043f0000003201000039000000040010043f00000dd901000041000036b70001043000000000050000190000000c01000029000000000051043500000dd10050009c00002d0d0000213d00000005015002100000003f0210003900000dd202200197000000400300043d0000000002230019000d00000003001d000000000032004b0000000003000039000000010300403900000dd10020009c00002d0d0000213d000000010030019000002d0d0000c13d000000400020043f0000000d020000290000000006520436000000000005004b00002ada0000613d0000000002000019000000400300043d00000dd50030009c00002d0d0000213d0000022004300039000000400040043f00000200043000390000000000040435000001e0043000390000000000040435000001c0043000390000000000040435000001a00430003900000000000404350000018004300039000000000004043500000160043000390000000000040435000001400430003900000000000404350000012004300039000000000004043500000100043000390000000000040435000000e0043000390000000000040435000000c0043000390000000000040435000000a0043000390000000000040435000000800430003900000000000404350000006004300039000000000004043500000040043000390000000000040435000000200430003900000000000404350000000000030435000000000462001900000000003404350000002002200039000000000012004b00002a910000413d0000000003000019000800000005001d000700000006001d0000000c010000290000000001010433000000000031004b00002a730000a13d0000000502300210000a00000002001d0000000901200029000000000101043300000db101100197000b00000003001d36b52e930000040f0000000b03000029000000070600002900000008050000290000000d020000290000000002020433000000000032004b00002a730000a13d0000000a0260002900000000001204350000000d010000290000000001010433000000000031004b00002a730000a13d0000000103300039000000000053004b00002abf0000413d00000005010000290000000001010433000000400900043d00000e2002000041000000000029043500000db101100197000000040290003900000000001204350000000001000414000000040200002900000db102200197000000040020008c00002aea0000c13d0000000201000367000000000300003100002afd0000013d00000dae0090009c000c00000009001d00000dae030000410000000003094019000000400330021000000dae0010009c00000dae01008041000000c001100210000000000131019f00000dd9011001c736b536b00000040f0000000003010019000000600330027000000dae0030019d00000dae033001970002000000010355000000010020019000002d400000613d0000000c0900002900000e25043001980000001f0530018f000000000249001900002b070000613d000000000601034f0000000007090019000000006806043c0000000007870436000000000027004b00002b030000c13d000000000005004b00002b140000613d000000000141034f0000000304500210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001204350000001f0130003900000e25021001970000000001920019000000000021004b0000000002000039000000010200403900000dd10010009c00002d0d0000213d000000010020019000002d0d0000c13d000000400010043f00000dea0030009c00002d130000213d000000200030008c00002d130000413d000000000409043300000dd10040009c00002d130000213d00000000029300190000000004940019000000000542004900000dea0050009c00002d130000213d000000600050008c00002d130000413d00000dfe0010009c00002d0d0000213d0000006005100039000000400050043f000000007604043400000dd10060009c00002d130000213d00000000084600190000001f06800039000000000026004b000000000900001900000deb0900804100000deb0a60019700000deb06200197000000000b6a013f00000000006a004b000000000a00001900000deb0a00404100000deb00b0009c000000000a09c01900000000000a004b00002d130000c13d000000009808043400000dd10080009c00002d0d0000213d0000001f0a80003900000e250aa001970000003f0aa0003900000e250aa00197000000000a5a001900000dd100a0009c00002d0d0000213d0000004000a0043f0000000000850435000000000a98001900000000002a004b00002d130000213d000000800a100039000000000008004b00002b5d0000613d000000000b000019000000000cab0019000000000d9b0019000000000d0d04330000000000dc0435000000200bb0003900000000008b004b00002b560000413d0000000008a8001900000000000804350000000005510436000000000707043300000dd10070009c00002d130000213d00000000074700190000001f08700039000000000028004b000000000900001900000deb0900804100000deb08800197000000000a68013f000000000068004b000000000800001900000deb0800404100000deb00a0009c000000000809c019000000000008004b00002d130000c13d000000008707043400000dd10070009c00002d0d0000213d0000001f0970003900000e25099001970000003f0990003900000e250a900197000000400900043d000000000aa9001900000000009a004b000000000b000039000000010b00403900000dd100a0009c00002d0d0000213d0000000100b0019000002d0d0000c13d0000004000a0043f000000000a790436000000000b87001900000000002b004b00002d130000213d000000000007004b00002b900000613d000000000b000019000000000cab0019000000000d8b0019000000000d0d04330000000000dc0435000000200bb0003900000000007b004b00002b890000413d00000000077a0019000000000007043500000000009504350000004007400039000000000707043300000dd10070009c00002d130000213d00000000044700190000001f07400039000000000027004b000000000800001900000deb0800804100000deb07700197000000000967013f000000000067004b000000000600001900000deb0600404100000deb0090009c000000000608c019000000000006004b00002d130000c13d000000006404043400000dd10040009c00002d0d0000213d0000001f0740003900000e25077001970000003f0770003900000e2507700197000000400a00043d00000000077a00190000000000a7004b0000000008000039000000010800403900000dd10070009c00002d0d0000213d000000010080019000002d0d0000c13d000000400070043f00000000074a04360000000008640019000000000028004b00002d130000213d000000000004004b00002bc40000613d000000000200001900000000087200190000000009620019000000000909043300000000009804350000002002200039000000000042004b00002bbd0000413d0000000002470019000000000002043500000040021000390000000000a204350000000001010433000800000001001d0000000001050433000300000001001d000000060200002900000080012000390000000001010433000400000001001d00000060012000390000000001010433000700000001001d00000020012000390000000001010433000900000001001d0000000001020433000a00000001001d00000005010000290000000002010433000000400c00043d00000e1b0100004100000000001c0435000000000100041400000db105200197000000040050008c000c0000000a001d000b00000005001d00002be70000c13d000000200030008c0000002004000039000000000403401900002c170000013d00000dae00c0009c00000dae0200004100000000020c4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c7000000000205001900060000000c001d36b536b00000040f000000060c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c001900002c040000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b00002c000000c13d000000000006004b00002c110000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000000c0a00002900002d4c0000613d0000000b050000290000001f01400039000000600110018f000000000bc1001900000000001b004b0000000002000039000000010200403900000dd100b0009c00002d0d0000213d000000010020019000002d0d0000c13d0000004000b0043f000000200030008c00002d130000413d00000000020c0433000600000002001d00000db10020009c00002d130000213d00000e210200004100000000002b04350000000002000414000000040050008c00002c5f0000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900050000000b001d36b536b00000040f000000050b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900002c4a0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00002c460000c13d000000000006004b00002c570000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000000c0a00002900002d580000613d0000001f01400039000000600110018f0000000b05000029000000000cb1001900000dd100c0009c00002d0d0000213d0000004000c0043f000000200030008c00002d130000413d00000000020b0433000500000002001d00000e220200004100000000002c04350000000002000414000000040050008c00002c9e0000613d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900020000000c001d36b536b00000040f000000020c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c001900002c890000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b00002c850000c13d000000000006004b00002c960000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000000c0a00002900002d640000613d0000001f01400039000000600110018f0000000b05000029000000000bc1001900000dd100b0009c00002d0d0000213d0000004000b0043f000000200030008c00002d130000413d00000000060c043300000e230200004100000000002b04350000000002000414000000040050008c00002cde0000613d000100000006001d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900020000000b001d36b536b00000040f000000020b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900002cc80000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00002cc40000c13d000000000006004b00002cd50000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000000c0a00002900002d700000613d0000001f01400039000000600110018f0000000b0500002900000001060000290000000001b1001900000dd10010009c00002d0d0000213d000000400010043f000000200030008c00002d130000413d00000e1f0010009c00002d0d0000213d00000000020b0433000001a003100039000000400030043f00000180031000390000000d0400002900000000004304350000016003100039000000000023043500000140021000390000000000620435000001200210003900000005030000290000000000320435000001000210003900000006030000290000000000320435000000e0021000390000000000a20435000000c00210003900000003030000290000000000320435000000a0021000390000000803000029000000000032043500000080021000390000000403000029000000000032043500000060021000390000000703000029000000000032043500000040021000390000000000520435000000090200002900000db102200197000000200310003900000000002304350000000a020000290000000000210435000000000001042d00000e1301000041000000000010043f0000004101000039000000040010043f00000dd901000041000036b7000104300000000001000019000036b7000104300000001f0530018f00000db006300198000000400200043d000000000462001900002d200000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d1c0000c13d000000000005004b00002d2d0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000dae0020009c00000dae020080410000004002200210000000000112019f000036b700010430000000000001042f0000001f0530018f00000db006300198000000400200043d000000000462001900002d200000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d3b0000c13d00002d200000013d0000001f0530018f00000db006300198000000400200043d000000000462001900002d200000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d470000c13d00002d200000013d0000001f0530018f00000db006300198000000400200043d000000000462001900002d200000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d530000c13d00002d200000013d0000001f0530018f00000db006300198000000400200043d000000000462001900002d200000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d5f0000c13d00002d200000013d0000001f0530018f00000db006300198000000400200043d000000000462001900002d200000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d6b0000c13d00002d200000013d0000001f0530018f00000db006300198000000400200043d000000000462001900002d200000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d770000c13d00002d200000013d0002000000000002000000400200043d00000e270020009c00002e570000813d0000004003200039000000400030043f00000020032000390000000000030435000000000002043500000dd702000041000000400c00043d00000000002c0435000000000200041400000db105100197000000040050008c000200000005001d00002d920000c13d0000000003000031000000200030008c0000002004000039000000000403401900002dc10000013d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900010000000c001d36b536b00000040f000000010c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c001900002daf0000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b00002dab0000c13d000000000006004b00002dbc0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002e5d0000613d00000002050000290000001f01400039000000600110018f000000000bc1001900000000001b004b0000000002000039000000010200403900000dd100b0009c00002e570000213d000000010020019000002e570000c13d0000004000b0043f0000001f0030008c00002e550000a13d00000000020c043300000db10020009c00002e550000213d00000e1b0400004100000000004b04350000000004000414000000040020008c00002e060000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000db3011001c700010000000b001d36b536b00000040f000000010b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900002df20000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00002dee0000c13d000000000006004b00002dff0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002e690000613d0000001f01400039000000600110018f0000000205000029000000000cb1001900000dd100c0009c00002e570000213d0000004000c0043f000000200030008c00002e550000413d00000000020b043300000db10020009c00002e550000213d00000e1d0400004100000000004c04350000000404c0003900000000005404350000000004000414000000040020008c00002e460000613d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000dd9011001c700010000000c001d36b536b00000040f000000010c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c001900002e320000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b00002e2e0000c13d000000000006004b00002e3f0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002e750000613d0000001f01400039000000600110018f00000002050000290000000001c1001900000dd10010009c00002e570000213d000000400010043f000000200030008c00002e550000413d00000dfd0010009c00002e570000213d00000000020c04330000004003100039000000400030043f000000200310003900000000002304350000000000510435000000000001042d0000000001000019000036b70001043000000e1301000041000000000010043f0000004101000039000000040010043f00000dd901000041000036b7000104300000001f0530018f00000db006300198000000400200043d000000000462001900002e800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002e640000c13d00002e800000013d0000001f0530018f00000db006300198000000400200043d000000000462001900002e800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002e700000c13d00002e800000013d0000001f0530018f00000db006300198000000400200043d000000000462001900002e800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002e7c0000c13d000000000005004b00002e8d0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000dae0020009c00000dae020080410000004002200210000000000112019f000036b7000104300011000000000002000000400200043d00000e280020009c000033720000813d0000022003200039000000400030043f00000200032000390000000000030435000001e0032000390000000000030435000001c0032000390000000000030435000001a00320003900000000000304350000018003200039000000000003043500000160032000390000000000030435000001400320003900000000000304350000012003200039000000000003043500000100032000390000000000030435000000e0032000390000000000030435000000c0032000390000000000030435000000a003200039000000000003043500000080032000390000000000030435000000600320003900000000000304350000004003200039000000000003043500000020032000390000000000030435000000000002043500000dd602000041000000400b00043d00000000002b0435000000000200041400000db105100197000000040050008c000e00000005001d00002ec70000c13d0000000003000031000000200030008c0000002004000039000000000403401900002ef60000013d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900110000000b001d36b536b00000040f000000110b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900002ee40000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00002ee00000c13d000000000006004b00002ef10000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000033960000613d0000000e050000290000001f01400039000000600110018f000000000cb1001900000000001c004b0000000002000039000000010200403900000dd100c0009c000033720000213d0000000100200190000033720000c13d0000004000c0043f0000001f0030008c000033700000a13d00000000020b0433000b00000002001d00000dd70200004100000000002c04350000000002000414000000040050008c00002f3b0000613d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900110000000c001d36b536b00000040f000000110c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c001900002f270000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b00002f230000c13d000000000006004b00002f340000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000033a20000613d0000001f01400039000000600110018f0000000e05000029000000000bc1001900000dd100b0009c000033720000213d0000004000b0043f000000200030008c000033700000413d00000000070c043300000db10070009c000033700000213d00000dd80100004100000000061b04360000000401b0003900000000005104350000000001000414000000040070008c000d00000007001d00002f500000c13d000000400030008c0000004004000039000000000403401900002f820000013d001000000006001d00000dae00b0009c00000dae0200004100000000020b4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000dd9011001c7000000000207001900110000000b001d36b536b00000040f000000110b0000290000000003010019000000600330027000000dae03300197000000400030008c000000400400003900000000040340190000001f0640018f000000600740019000000000057b001900002f6e0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00002f6a0000c13d000000000006004b00002f7b0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000033ae0000613d0000000e050000290000000d0700002900000010060000290000001f01400039000000e00110018f000000000cb1001900000dd100c0009c000033720000213d0000004000c0043f000000400030008c000033700000413d00000000020b0433000000000002004b0000000001000039000000010100c039000a00000002001d000000000012004b000033700000c13d0000000001060433000900000001001d00000dda0100004100000000001c04350000000001000414000000040050008c00002f9a0000c13d000000200400003900002fca0000013d00000dae00c0009c00000dae0200004100000000020c4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c7000000000205001900110000000c001d36b536b00000040f000000110c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c001900002fb70000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b00002fb30000c13d000000000006004b00002fc40000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000033ba0000613d0000000e050000290000000d070000290000001f01400039000000600110018f000000000bc1001900000dd100b0009c000033720000213d0000004000b0043f000000200030008c000033700000413d00000000020c0433000c00000002001d00000db10020009c000033700000213d00000ddb0200004100000000002b043500000000020004140000000c04000029000000040040008c0000300e0000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000000c0200002900110000000b001d36b536b00000040f000000110b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900002ff90000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00002ff50000c13d000000000006004b000030060000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000033c60000613d0000001f01400039000000600110018f0000000e050000290000000d07000029000000000ab1001900000dd100a0009c000033720000213d0000004000a0043f000000200030008c000033700000413d00000000010b0433000800000001001d000000ff0010008c000033700000213d00000ddc080000410000002009000039000000000b00001900000000060000190000002401a000390000000000b1043500000000008a04350000000401a0003900000000005104350000000001000414000000040070008c00000000040900190000305a0000613d000f0000000b001d001100000006001d00000dae00a0009c00000dae0200004100000000020a4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000ddd011001c7000000000207001900100000000a001d36b536b00000040f000000100a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000030430000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b0000303f0000c13d0000001f07400190000030500000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000000020090000390000000f0b000029000033780000613d0000000e0500002900000011060000290000000d0700002900000ddc080000410000001f01400039000000600110018f000000000ca1001900000000001c004b0000000002000039000000010200403900000dd100c0009c000033720000213d0000000100200190000033720000c13d0000004000c0043f000000200030008c000033700000413d00000000020a0433000000000002004b0000000004000039000000010400c039000000000042004b000033700000c13d0000000002b201cf000000000626019f0000000102b00039000000ff0b20018f0000000800b0008c000000000a0c00190000301c0000a13d00000ddf0200004100000000002c04350000000002000414000000040050008c000030ad0000613d001100000006001d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900100000000c001d36b536b00000040f000000100c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000030970000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000030930000c13d000000000006004b000030a40000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000033d20000613d0000001f01400039000000600110018f0000000e0500002900000011060000290000000d07000029000000000bc1001900000dd100b0009c000033720000213d0000004000b0043f000000200030008c000033700000413d00000000020c0433000000000002004b001100000006001d000030f80000613d00000de00200004100000000002b04350000000002000414000000040050008c000030ef0000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000000002050019000f0000000b001d36b536b00000040f0000000f0b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000030d90000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000030d50000c13d000000000006004b000030e60000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000344a0000613d0000001f01400039000000600110018f0000000e0500002900000011060000290000000d070000290000000001b1001900000dd10010009c000033720000213d000000400010043f000000200030008c000033700000413d00000000020b0433000000000b010019000030f90000013d000000000200001900000de10100004100000000001b04350000000001000414000000040050008c001000000002001d000031010000c13d0000002004000039000031320000013d00000dae00b0009c00000dae0200004100000000020b4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c70000000002050019000f0000000b001d36b536b00000040f0000000f0b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b00190000311e0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000311a0000c13d000000000006004b0000312b0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000033de0000613d0000000e0500002900000011060000290000000d070000290000001f01400039000000600110018f000000000cb1001900000dd100c0009c000033720000213d0000004000c0043f000000200030008c000033700000413d00000000020b0433000f00000002001d00000de20200004100000000002c04350000000002000414000000040050008c000031740000613d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900070000000c001d36b536b00000040f000000070c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c00190000315e0000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b0000315a0000c13d000000000006004b0000316b0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000033ea0000613d0000001f01400039000000600110018f0000000e0500002900000011060000290000000d07000029000000000bc1001900000dd100b0009c000033720000213d0000004000b0043f000000200030008c000033700000413d00000000020c0433000700000002001d00000de30200004100000000002b04350000000402b0003900000000005204350000000002000414000000040070008c000031b60000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c7000000000207001900060000000b001d36b536b00000040f000000060b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000031a00000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000319c0000c13d000000000006004b000031ad0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000033f60000613d0000001f01400039000000600110018f0000000e0500002900000011060000290000000d07000029000000000cb1001900000dd100c0009c000033720000213d0000004000c0043f000000200030008c000033700000413d00000000020b0433000d00000002001d00000de40200004100000000002c04350000000402c0003900000000005204350000000002000414000000040070008c000031f70000613d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c7000000000207001900060000000c001d36b536b00000040f000000060c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000031e20000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000031de0000c13d000000000006004b000031ef0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000034020000613d0000001f01400039000000600110018f0000000e050000290000001106000029000000000bc1001900000dd100b0009c000033720000213d0000004000b0043f000000200030008c000033700000413d00000000020c0433000600000002001d00000de50200004100000000002b04350000000002000414000000040050008c000032360000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900050000000b001d36b536b00000040f000000050b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000032210000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000321d0000c13d000000000006004b0000322e0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000340e0000613d0000001f01400039000000600110018f0000000e050000290000001106000029000000000cb1001900000dd100c0009c000033720000213d0000004000c0043f000000200030008c000033700000413d00000000020b0433000500000002001d00000de60200004100000000002c04350000000002000414000000040050008c000032750000613d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900040000000c001d36b536b00000040f000000040c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000032600000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b0000325c0000c13d000000000006004b0000326d0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000341a0000613d0000001f01400039000000600110018f0000000e050000290000001106000029000000000bc1001900000dd100b0009c000033720000213d0000004000b0043f000000200030008c000033700000413d00000000020c0433000400000002001d00000ddf0200004100000000002b04350000000002000414000000040050008c000032b40000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900030000000b001d36b536b00000040f000000030b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b00190000329f0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000329b0000c13d000000000006004b000032ac0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000034260000613d0000001f01400039000000600110018f0000000e050000290000001106000029000000000cb1001900000dd100c0009c000033720000213d0000004000c0043f000000200030008c000033700000413d00000000020b0433000300000002001d00000de70200004100000000002c04350000000002000414000000040050008c000032f30000613d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900020000000c001d36b536b00000040f000000020c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000032de0000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000032da0000c13d000000000006004b000032eb0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000034320000613d0000001f01400039000000600110018f0000000e050000290000001106000029000000000bc1001900000dd100b0009c000033720000213d0000004000b0043f000000200030008c000033700000413d00000000070c043300000ddb0200004100000000002b04350000000002000414000000040050008c000033330000613d000100000007001d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900020000000b001d36b536b00000040f000000020b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b00190000331d0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000033190000c13d000000000006004b0000332a0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000343e0000613d0000001f01400039000000600110018f0000000e05000029000000110600002900000001070000290000000001b1001900000dd10010009c000033720000213d000000400010043f000000200030008c000033700000413d00000000020b0433000000ff0020008c000033700000213d00000dd50010009c000033720000213d0000022003100039000000400030043f000002000310003900000000006304350000000803000029000000ff0330018f000001e0041000390000000000340435000001c0031000390000000000230435000001a0021000390000000c03000029000000000032043500000180021000390000000903000029000000000032043500000160021000390000000a03000029000000000032043500000140021000390000000000720435000001200210003900000003030000290000000000320435000001000210003900000004030000290000000000320435000000e00210003900000005030000290000000000320435000000c00210003900000006030000290000000000320435000000a0021000390000000d03000029000000000032043500000080021000390000000703000029000000000032043500000060021000390000000f03000029000000000032043500000040021000390000001003000029000000000032043500000020021000390000000b0300002900000000003204350000000000510435000000000001042d0000000001000019000036b70001043000000e1301000041000000000010043f0000004101000039000000040010043f00000dd901000041000036b7000104300000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000337f0000c13d000000000005004b000033900000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000dae0020009c00000dae020080410000004002200210000000000112019f000036b7000104300000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000339d0000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000033a90000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000033b50000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000033c10000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000033cd0000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000033d90000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000033e50000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000033f10000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000033fd0000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000034090000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000034150000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000034210000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000342d0000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000034390000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000034450000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000034510000c13d000033830000013d0007000000000002000000400300043d00000e290030009c0000360e0000813d000000c004300039000000400040043f000000a004300039000000000004043500000080043000390000000000040435000000600430003900000000000404350000004004300039000000000004043500000020043000390000000000040435000000000003043500000df203000041000000400c00043d00000000003c043500000db1032001970000000402c00039000700000003001d0000000000320435000000000200041400000db105100197000000040050008c000600000005001d000034780000c13d0000000003000031000000200030008c00000020040000390000000004034019000034a70000013d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c7000000000205001900050000000c001d36b536b00000040f000000050c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000034950000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000034910000c13d000000000006004b000034a20000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000036160000613d00000006050000290000001f01400039000000600110018f000000000bc1001900000000001b004b0000000002000039000000010200403900000dd100b0009c0000360e0000213d00000001002001900000360e0000c13d0000004000b0043f0000001f0030008c000036140000a13d00000000020c0433000500000002001d00000df30200004100000000002b04350000000402b00039000000070400002900000000004204350000000002000414000000040050008c000034ef0000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c7000000000205001900040000000b001d36b536ab0000040f000000040b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000034db0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000034d70000c13d000000000006004b000034e80000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000036220000613d0000001f01400039000000600110018f0000000605000029000000000cb1001900000dd100c0009c0000360e0000213d0000004000c0043f000000200030008c000036140000413d00000000020b0433000400000002001d00000df40200004100000000002c04350000000402c00039000000070400002900000000004204350000000002000414000000040050008c000035300000613d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c7000000000205001900030000000c001d36b536ab0000040f000000030c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c00190000351c0000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000035180000c13d000000000006004b000035290000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000362e0000613d0000001f01400039000000600110018f0000000605000029000000000bc1001900000dd100b0009c0000360e0000213d0000004000b0043f000000200030008c000036140000413d00000000020c0433000300000002001d00000dda0200004100000000002b04350000000002000414000000040050008c0000356e0000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900020000000b001d36b536b00000040f000000020b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b00190000355a0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000035560000c13d000000000006004b000035670000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000363a0000613d0000001f01400039000000600110018f0000000605000029000000000cb1001900000dd100c0009c0000360e0000213d0000004000c0043f000000200030008c000036140000413d00000000020b043300000db10020009c000036140000213d00000df20400004100000000004c04350000000406c00039000000070400002900000000004604350000000004000414000000040020008c000035b10000613d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000dd9011001c7000100000002001d00020000000c001d36b536b00000040f000000020c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c00190000359c0000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000035980000c13d000000000006004b000035a90000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000036460000613d0000001f01400039000000600110018f00000006050000290000000102000029000000000bc1001900000dd100b0009c0000360e0000213d0000004000b0043f000000200030008c000036140000413d00000000070c04330000002404b00039000000000054043500000df50400004100000000004b04350000000406b00039000000070400002900000000004604350000000004000414000000040020008c000035f40000613d000200000007001d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000ddd011001c700070000000b001d36b536b00000040f000000070b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000035df0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000035db0000c13d000000000006004b000035ec0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000036520000613d0000001f01400039000000600110018f000000060500002900000002070000290000000001b1001900000dd10010009c0000360e0000213d000000400010043f000000200030008c000036140000413d00000df10010009c0000360e0000213d00000000020b0433000000c003100039000000400030043f000000a0031000390000000000230435000000800210003900000000007204350000006002100039000000030300002900000000003204350000004002100039000000040300002900000000003204350000002002100039000000050300002900000000003204350000000000510435000000000001042d00000e1301000041000000000010043f0000004101000039000000040010043f00000dd901000041000036b7000104300000000001000019000036b7000104300000001f0530018f00000db006300198000000400200043d00000000046200190000365d0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000361d0000c13d0000365d0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000365d0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000036290000c13d0000365d0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000365d0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000036350000c13d0000365d0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000365d0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000036410000c13d0000365d0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000365d0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000364d0000c13d0000365d0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000365d0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000036590000c13d000000000005004b0000366a0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000dae0020009c00000dae020080410000004002200210000000000112019f000036b700010430000000010010008c000036780000613d000000020010008c000036860000c13d00000e0801000041000000000010044300000000010004140000367b0000013d00000e06010000410000000000100443000000000100041400000dae0010009c00000dae01008041000000c00110021000000e07011001c70000800b0200003936b536b00000040f0000000100200190000036850000613d000000000101043b000000000001042d000000000001042f00000e1301000041000000000010043f0000005101000039000000040010043f00000dd901000041000036b700010430000000000001042f00000000050100190000000000200443000000050030008c0000369b0000413d000000040100003900000000020000190000000506200210000000000664001900000005066002700000000006060031000000000161043a0000000102200039000000000031004b000036930000413d00000dae0030009c00000dae030080410000006001300210000000000200041400000dae0020009c00000dae02008041000000c002200210000000000112019f00000e2a011001c7000000000205001936b536b00000040f0000000100200190000036aa0000613d000000000101043b000000000001042d000000000001042f000036ae002104210000000102000039000000000001042d0000000002000019000000000001042d000036b3002104230000000102000039000000000001042d0000000002000019000000000001042d000036b500000432000036b60001042e000036b70001043000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000ffffffffffffffffffffffffffffffffffffffff09c8f7ec0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000001e13380ae0fcab3000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000140000001000000000000000000000000000000000000000000000000000000000000000000000000007c51b64100000000000000000000000000000000000000000000000000000000c7ad089400000000000000000000000000000000000000000000000000000000d77ebf9500000000000000000000000000000000000000000000000000000000d77ebf9600000000000000000000000000000000000000000000000000000000e0a67f1100000000000000000000000000000000000000000000000000000000e1d146fb00000000000000000000000000000000000000000000000000000000c7ad089500000000000000000000000000000000000000000000000000000000d26998e900000000000000000000000000000000000000000000000000000000aa5dbd2200000000000000000000000000000000000000000000000000000000aa5dbd2300000000000000000000000000000000000000000000000000000000b3124239000000000000000000000000000000000000000000000000000000007c51b642000000000000000000000000000000000000000000000000000000007c84e3b30000000000000000000000000000000000000000000000000000000047d86a80000000000000000000000000000000000000000000000000000000006857249b000000000000000000000000000000000000000000000000000000006857249c000000000000000000000000000000000000000000000000000000007a27db570000000000000000000000000000000000000000000000000000000047d86a810000000000000000000000000000000000000000000000000000000055dd951500000000000000000000000000000000000000000000000000000000345954db00000000000000000000000000000000000000000000000000000000345954dc000000000000000000000000000000000000000000000000000000003e3e399c000000000000000000000000000000000000000000000000000000000d3ae318000000000000000000000000000000000000000000000000000000001f884fdf310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e0000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000000000000000000000000000000000ffffffffffffff7f00000000000000000000000000000000000000000000003fffffffffffffffe0000000000000000000000000000000000000000000000000fffffffffffffddf182df0f5000000000000000000000000000000000000000000000000000000005fe3b567000000000000000000000000000000000000000000000000000000008e8f294b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000006f307dc300000000000000000000000000000000000000000000000000000000313ce56700000000000000000000000000000000000000000000000000000000e85a2960000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffdf18160ddd00000000000000000000000000000000000000000000000000000000ae9d70b000000000000000000000000000000000000000000000000000000000f8f9da2800000000000000000000000000000000000000000000000000000000173b99040000000000000000000000000000000000000000000000000000000002c3bcbb000000000000000000000000000000000000000000000000000000004a5844320000000000000000000000000000000000000000000000000000000047bd3718000000000000000000000000000000000000000000000000000000008f840ddd000000000000000000000000000000000000000000000000000000003b1d21a200000000000000000000000000000000000000000000000000000000f36dba380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000008000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000080000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffebf000000000000000000000000000000000000000000000000ffffffffffffff3f70a082310000000000000000000000000000000000000000000000000000000017bfdfbc000000000000000000000000000000000000000000000000000000003af9e66900000000000000000000000000000000000000000000000000000000dd62ed3e00000000000000000000000000000000000000000000000000000000b0772d0b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000800000000000000000020000020000000000000000000000000000004400000000000000000000000022abdbf50000000000000000000000000000000000000000000000000000000061252fd100000000000000000000000000000000000000000000000000000000f7c618c1000000000000000000000000000000000000000000000000000000001627ee8900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffbf000000000000000000000000000000000000000000000000ffffffffffffff9f8f693ec70000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff81814945000000000000000000000000000000000000000000000000000000002c427b570000000000000000000000000000000000000000000000000000000092a1823500000000000000000000000000000000000000000000000000000000aa5af0fd000000000000000000000000000000000000000000000000000000007c05a7c500000000000000000000000000000000000000000000000000000000796b89b91644bc98cd93958e4c9038275d622183e25ac5af08cc6b5d95539132020000020000000000000000000000000000000400000000000000000000000042cbb15ccdc3cad6266b0e7a08c0454b23bf29dc2df74b6f3c209e9336465bd10000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000c097ce7bc90715b34b9f10000000006e657720696e646578206f766572666c6f777300000000000000000000000000000000010000000000000000000000000000000000000000000000000000000008c379a00000000000000000000000000000000000000000000000000000000074c4c1cc000000000000000000000000000000000000000000000000000000006dfd08ca00000000000000000000000000000000000000000000000000000000160c3a030000000000000000000000000000000000000000000000000000000095dd919300000000000000000000000000000000000000000000000000000000552c0971000000000000000000000000000000000000000000000000000000004e487b7100000000000000000000000000000000000000000000000000000000266e0a7f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000440000008000000000000000007aee632d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000002200000000000000000000000000000000000000000000000000000000000000000ffffffffffffff5f0000000000000000000000000000000000000004000000e00000000000000000000000000000000000000000000000000000000000000000ffffffffffffff1f7dc0d1d000000000000000000000000000000000000000000000000000000000bbcac55700000000000000000000000000000000000000000000000000000000fc57d4df00000000000000000000000000000000000000000000000000000000d88ff1f400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffe5fa3aefa2c00000000000000000000000000000000000000000000000000000000e8755446000000000000000000000000000000000000000000000000000000004ada90af00000000000000000000000000000000000000000000000000000000db5c65de00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffedfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000000000000000000000000000000000fffffffffffffe60000000000000000000000000000000000000000000000000ffffffffffffffc0000000000000000000000000000000000000000000000000fffffffffffffde0000000000000000000000000000000000000000000000000ffffffffffffff4002000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd266e967e3b2382c6511fd4150dd11c23ea0355910672dd36d07081e6b4a2b6", + "deployedBytecode": "0x00030000000000020036000000000002000000000301034f0000000001030019000000600110027000000dae04100197000200000043035500010000000303550000000100200190000000320000c13d0000008009000039000000400090043f000000040040008c0000005b0000413d000000000543034f000000000203043b000000e00220027000000db70020009c0000005d0000a13d00000db80020009c000000a10000a13d00000db90020009c0000013a0000a13d00000dba0020009c000002f40000613d00000dbb0020009c000001b20000613d00000dbc0020009c0000005b0000c13d0000000001000416000000000001004b0000005b0000c13d0000000001000412001f00000001001d001e00400000003d0000800501000039000000440300003900000000040004150000001f0440008a000000050440021000000dcf0200004136b5368d0000040f36b536700000040f000000400200043d000000000012043500000dae0020009c00000dae02008041000000400120021000000dd0011001c7000036b60001042e0000000001000416000000000001004b0000005b0000c13d0000001f0140003900000daf011001970000010001100039000000400010043f0000001f0240018f00000db0054001980000010001500039000000430000613d0000010006000039000000000703034f000000007807043c0000000006860436000000000016004b0000003f0000c13d000000000002004b000000500000613d000000000353034f0000000302200210000000000501043300000000052501cf000000000525022f000000000303043b0000010002200089000000000323022f00000000022301cf000000000252019f0000000000210435000000600040008c0000005b0000413d000001000100043d000000000001004b0000000002000039000000010200c039000000000021004b0000005b0000c13d000001400200043d00000db10020009c000000dd0000a13d0000000001000019000036b70001043000000dc40020009c000000ba0000213d00000dca0020009c000001000000213d00000dcd0020009c000002420000613d00000dce0020009c0000005b0000c13d000000240040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000101043b00000dd10010009c0000005b0000213d0000002302100039000000000042004b0000005b0000813d0000000402100039000000000223034f000000000202043b001a00000002001d00000dd10020009c0000005b0000213d001900240010003d0000001a0100002900000005021002100000001901200029000000000041004b0000005b0000213d0000003f0120003900000dd20310019700000dd30030009c000006870000213d0000008001300039000000400010043f0000001a04000029000000800040043f000000000004004b0000065e0000c13d00000020020000390000000003210436000000800200043d00000000002304350000004003100039000000000002004b0000009f0000613d000000800400003900000000050000190000000006010019000000000703001900000020044000390000000003040433000000008303043400000db103300197000000000037043500000060036000390000000006080433000000000063043500000040037000390000000105500039000000000025004b0000000006070019000000910000413d00000000021300490000023a0000013d00000dbf0020009c000000e50000213d00000dc20020009c000001540000613d00000dc30020009c0000005b0000c13d000000240040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000101043b00000db10010009c0000005b0000213d36b52d7c0000040f000000400200043d001d00000002001d36b5293c0000040f0000001d0100002900000dae0010009c00000dae01008041000000400110021000000def011001c7000036b60001042e00000dc50020009c0000011d0000213d00000dc80020009c000002aa0000613d00000dc90020009c0000005b0000c13d000000640040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000201043b00000db10020009c0000005b0000213d0000002401300370000000000101043b00000db10010009c0000005b0000213d0000004403300370000000000303043b00000db10030009c0000005b0000213d00000e1404000041000000800040043f000000840010043f000000a40030043f0000000001000414000000040020008c000005f10000c13d0000000003000031000000200030008c00000020040000390000000004034019000006170000013d000001200300043d000000000001004b0000014f0000613d000000000003004b0000031d0000c13d00000db4030000410000000104000039000003260000013d00000dc00020009c0000019f0000613d00000dc10020009c0000005b0000c13d000000440040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000101043b00000db10010009c0000005b0000213d0000002402300370000000000202043b00000db10020009c0000005b0000213d36b534560000040f000000400200043d001d00000002001d36b529420000040f0000001d0100002900000dae0010009c00000dae01008041000000400110021000000ded011001c7000036b60001042e00000dcb0020009c000002d20000613d00000dcc0020009c0000005b0000c13d000000240040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000101043b001600000001001d00000db10010009c0000005b0000213d000000e009000039000000400090043f000000800000043f000000a00000043f0000006001000039000000c00010043f00000df601000041000000e00010043f00000000010004140000001602000029000000040020008c000003ba0000c13d0000000003000031000000000105034f000003c70000013d00000dc60020009c000002e40000613d00000dc70020009c0000005b0000c13d0000000001000416000000000001004b0000005b0000c13d000000440040008c0000005b0000413d0000000401300370000000000201043b00000db10020009c0000005b0000213d0000002401300370000000000101043b001600000001001d00000db10010009c0000005b0000213d002c0db100000045002d00000002001d00000df601000041000000800010043f00000000010004140000001602000029000000040020008c0000056c0000c13d0000000003000031000000000105034f000005780000013d00000dbd0020009c0000030a0000613d00000dbe0020009c0000005b0000c13d0000000001000416000000000001004b0000005b0000c13d0000000001000412002100000001001d002000600000003d000080050100003900000044030000390000000004000415000000210440008a000000050440021000000dcf0200004136b5368d0000040f00000db101100197000000800010043f00000dec01000041000036b60001042e000000000003004b000003250000c13d000000400100043d00000db2020000410000031f0000013d000000440040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000101043b00000dd10010009c0000005b0000213d0000002302100039000000000042004b0000005b0000813d0000000402100039000000000223034f000000000202043b001600000002001d00000dd10020009c0000005b0000213d001500240010003d000000160100002900000005021002100000001501200029000000000041004b0000005b0000213d0000002401300370000000000301043b00000db10030009c0000005b0000213d0000003f0120003900000dd20410019700000dd30040009c000006870000213d0000008001400039000000400010043f0000001605000029000000800050043f000000000005004b0000066f0000c13d00000020020000390000000002210436000000800300043d00000000003204350000004002100039000000000003004b000002390000613d0000008004000039000000000500001900000020044000390000000006040433000000008706043400000db107700197000000000772043600000000080804330000000000870435000000400760003900000000070704330000004008200039000000000078043500000060076000390000000007070433000000600820003900000000007804350000008007600039000000000707043300000080082000390000000000780435000000a0066000390000000006060433000000a0072000390000000000670435000000c0022000390000000105500039000000000035004b000001830000413d000002390000013d000000240040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000101043b00000db10010009c0000005b0000213d36b52e930000040f000000400200043d001d00000002001d36b528240000040f0000001d0100002900000dae0010009c00000dae01008041000000400110021000000dee011001c7000036b60001042e000000240040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000101043b00000dd10010009c0000005b0000213d0000002302100039000000000042004b0000005b0000813d0000000402100039000000000223034f000000000502043b00000dd10050009c000006870000213d00000005025002100000003f0620003900000dd20660019700000dd30060009c000006870000213d0000008006600039000000400060043f000000800050043f00000024011000390000000002120019000000000042004b0000005b0000213d000000000005004b0000000004000019000006240000c13d000a00000004001d00000005014002100000003f0210003900000dd4032001970000000002630019000000000032004b0000000003000039000000010300403900000dd10020009c000006870000213d0000000100300190000006870000c13d000000400020043f0000000a020000290000000005260436000000000002004b001900000006001d0000068d0000c13d000000400100043d00000020020000390000000002210436000000000306043300000000003204350000004002100039000000000003004b000002390000613d0000000004000019000000190800002900000020088000390000000005080433000000007605043400000db106600197000000000662043600000000070704330000000000760435000000400650003900000000060604330000004007200039000000000067043500000060065000390000000006060433000000600720003900000000006704350000008006500039000000000606043300000080072000390000000000670435000000a0065000390000000006060433000000a0072000390000000000670435000000c0065000390000000006060433000000c0072000390000000000670435000000e0065000390000000006060433000000e007200039000000000067043500000100065000390000000006060433000001000720003900000000006704350000012006500039000000000606043300000120072000390000000000670435000001400650003900000000060604330000014007200039000000000067043500000160065000390000000006060433000000000006004b0000000006000039000000010600c039000001600720003900000000006704350000018006500039000000000606043300000180072000390000000000670435000001a006500039000000000606043300000db106600197000001a0072000390000000000670435000001c0065000390000000006060433000001c0072000390000000000670435000001e0065000390000000006060433000001e0072000390000000000670435000002000550003900000000050504330000020006200039000000000056043500000220022000390000000104400039000000000034004b000001ee0000413d000000000212004900000dae0020009c00000dae02008041000000600220021000000dae0010009c00000dae010080410000004001100210000000000112019f000036b60001042e000000440040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000101043b00000db10010009c0000005b0000213d0000002402300370000000000602043b00000dd10060009c0000005b0000213d000000000264004900000dea0020009c0000005b0000213d000000a40020008c0000005b0000413d0000012002000039000000400020043f0000000405600039000000000753034f000000000707043b00000dd10070009c0000005b0000213d00000000076700190000002306700039000000000046004b0000005b0000813d0000000408700039000000000683034f000000000606043b00000dd10060009c000006870000213d0000001f0a60003900000e250aa001970000003f0aa0003900000e250aa0019700000e2400a0009c000006870000213d000001200aa000390000004000a0043f000001200060043f00000000076700190000002407700039000000000047004b0000005b0000213d0000002004800039000000000743034f00000e25086001980000001f0960018f00000140048000390000027d0000613d000001400a000039000000000b07034f00000000bc0b043c000000000aca043600000000004a004b000002790000c13d000000000009004b0000028a0000613d000000000787034f0000000308900210000000000904043300000000098901cf000000000989022f000000000707043b0000010008800089000000000787022f00000000078701cf000000000797019f000000000074043500000140046000390000000000040435000000800020043f0000002002500039000000000423034f000000000404043b00000db10040009c0000005b0000213d000000a00040043f0000002002200039000000000423034f000000000404043b00000db10040009c0000005b0000213d000000c00040043f0000002004200039000000000443034f000000000404043b000000e00040043f0000004002200039000000000223034f000000000202043b000001000020043f000000800200003936b529580000040f0000000002010019000000400100043d001d00000001001d36b5286a0000040f0000001d020000290000000001210049000005260000013d000000440040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000101043b001d00000001001d00000db10010009c0000005b0000213d0000002401300370000000000201043b00000db10020009c0000005b0000213d0000022009000039000000400090043f0000006001000039000000800010043f000000a00000043f000000c00000043f000000e00000043f000001000000043f000001200010043f000001400010043f000001600010043f000001800000043f000001a00000043f000001c00000043f000001e00000043f000002000010043f00000e1601000041000002200010043f000002240020043f00000000010004140000001d02000029000000040020008c0000043c0000c13d0000000003000031000000000105034f000004490000013d000000240040008c0000005b0000413d0000000002000416000000000002004b0000005b0000c13d0000000402300370000000000202043b003600000002001d00000db10020009c0000005b0000213d00000e1e03000041000000800030043f0000000003000414000000040020008c0000033a0000c13d000000000a000031000000000105034f000003460000013d0000000001000416000000000001004b0000005b0000c13d0000000001000412002f00000001001d002e00000000003d0000800501000039000000440300003900000000040004150000002f0440008a000000050440021000000dcf0200004136b5368d0000040f000000800010043f00000dec01000041000036b60001042e000000440040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000201043b00000db10020009c0000005b0000213d0000002401300370000000000301043b00000db10030009c0000005b0000213d00000de801000041000000800010043f000000840030043f0000000003000414000000040020008c000004bc0000c13d0000000003000031000000000105034f000004c90000013d0000000001000416000000000001004b0000005b0000c13d0000000001000412002300000001001d002200200000003d000080050100003900000044030000390000000004000415000000230440008a000000050440021000000dcf0200004136b5368d0000040f000000000001004b0000000001000039000000010100c039000000800010043f00000dec01000041000036b60001042e000000400100043d00000db502000041000000000021043500000dae0010009c00000dae01008041000000400110021000000db3011001c7000036b7000104300000000204000039000000a00010043f000000800030043f000000c00040043f000000e00020043f0000014000000443000001600030044300000020030000390000018000300443000001a0001004430000004001000039000001c000100443000001e00040044300000060010000390000020000100443000002200020044300000100003004430000000401000039000001200010044300000db601000041000036b60001042e00000dae0030009c00000dae03008041000000c00130021000000df7011001c736b536b00000040f0000000003010019000000600330027000000dae0030019d00000dae0a300197000200000001035500000001002001900000052e0000613d00000e2504a001980000001f05a0018f0000008002400039000003500000613d0000008006000039000000000701034f000000007807043c0000000006860436000000000026004b0000034c0000c13d000000000005004b0000035d0000613d000000000441034f0000000305500210000000000602043300000000065601cf000000000656022f000000000404043b0000010005500089000000000454022f00000000045401cf000000000464019f0000000000420435001c000000010353001d0000000a001d0000001f02a0003900000e250220019700000dd30020009c000006870000213d0000008001200039001b00000001001d000000400010043f0000001d0100002900000dea0010009c0000005b0000213d0000001d01000029000000200010008c0000005b0000413d000000800700043d00000dd10070009c0000005b0000213d0000001d0100002900000080041000390000009f02700039000000000042004b000000000600001900000deb0600804100000deb0540019700000deb02200197000000000852013f000000000052004b000000000200001900000deb0200404100000deb0080009c000000000206c019000000000002004b0000005b0000c13d0000008001700039000000000901043300000dd10090009c000006870000213d00000005029002100000003f0820003900000dd2088001970000001b0880002900000dd10080009c000006870000213d000000400080043f0000001b030000290000000000930435000000a0077000390000000008720019000000000048004b0000005b0000213d000000000009004b00000e850000c13d0035001b0000002d0000000001000415000000340110008a00010005001002180000000001000415000000330110008a0002000500100218003400000000003d000000000600001900000005046002100000003f0140003900000dd401100197000000400200043d0000000005210019000000000015004b0000000007000039000000010700403900000dd10050009c000006870000213d0000000100700190000006870000c13d000000400050043f0000000005620436000000000006004b00000ffd0000c13d00000002010000290000000501100270000000000102001f000000400100043d0000002003000039000000000431043600000000030204330000000000340435000000400410003900000005053002100000000005450019000000000003004b000019bb0000c13d00000000021500490000023a0000013d00000dae0010009c00000dae01008041000000c00110021000000e19011001c736b536b00000040f0000000003010019000000600330027000000dae0030019d00000dae0330019700020000000103550000000100200190000005480000613d000000e00900003900000e25053001980000001f0630018f000000e004500039000003d00000613d000000000701034f000000007807043c0000000009890436000000000049004b000003cc0000c13d000000000006004b000003dd0000613d000000000151034f0000000305600210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000001f0130003900000e2501100197001d00000001001d00000e1a0010009c000006870000213d0000001d01000029000000e007100039000000400070043f00000dea0030009c0000005b0000213d000000200030008c0000005b0000413d000000e00100043d00000dd10010009c0000005b0000213d000000e002300039000000ff03100039000000000023004b000000000400001900000deb0400804100000deb0520019700000deb03300197000000000653013f000000000053004b000000000300001900000deb0300404100000deb0060009c000000000304c019000000000003004b0000005b0000c13d000000e003100039000000000403043300000dd10040009c000006870000213d00000005034002100000003f0530003900000dd205500197000000000575001900000dd10050009c000006870000213d000000400050043f000000000047043500000100011000390000000003130019000000000023004b0000005b0000213d000000000004004b000004150000613d0000000002070019000000001401043400000db10040009c0000005b0000213d00000020022000390000000000420435000000000031004b0000040e0000413d001900000007001d00000dcf0100004100000000001004430000000001000412000000040010044300000060010000390000002400100443000000000100041400000dae0010009c00000dae01008041000000c00110021000000df8011001c7000080050200003936b536b00000040f0000000100200190000026890000613d000000000101043b00000db101100197000000160010006b0000042f0000613d00000019050000290000000006050433000000000006004b000000000700001900000f770000c13d0000000000750435000000400200043d00000e1b01000041001d00000002001d000000000012043500000000010004140000001602000029000000040020008c00000ee70000c13d0000000003000031000000200030008c0000002004000039000000000403401900000f130000013d00000dae0010009c00000dae01008041000000c00110021000000e17011001c736b536b00000040f0000000003010019000000600330027000000dae0030019d00000dae0330019700020000000103550000000100200190000005540000613d000002200900003900000e25043001980000001f0630018f0000022002400039000004520000613d000000000701034f000000007807043c0000000009890436000000000029004b0000044e0000c13d000000000006004b0000045f0000613d000000000141034f0000000304600210000000000602043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f00000000001204350000001f0130003900000e250110019700000dd50010009c000006870000213d0000022002100039000000400020043f00000dea0030009c0000005b0000213d000000200030008c0000005b0000413d000002200400043d00000dd10040009c0000005b0000213d00000220063000390000022007400039000000000376004900000dea0030009c0000005b0000213d000000a00030008c0000005b0000413d00000e180020009c000006870000213d000002c003100039000000400030043f000000000807043300000dd10080009c0000005b0000213d00000000077800190000001f08700039000000000068004b000000000900001900000deb0900804100000deb0880019700000deb0a600197000000000ba8013f0000000000a8004b000000000800001900000deb0800404100000deb00b0009c000000000809c019000000000008004b0000005b0000c13d000000008707043400000dd10070009c000006870000213d0000001f0970003900000e25099001970000003f0990003900000e2505900197000000000535001900000dd10050009c000006870000213d000000400050043f00000000007304350000000005870019000000000065004b0000005b0000213d000002e005100039000000000007004b000004a30000613d00000000060000190000000009560019000000000a860019000000000a0a04330000000000a904350000002006600039000000000076004b0000049c0000413d0000000005570019000000000005043500000000003204350000024003400039000000000303043300000db10030009c0000005b0000213d000002400510003900000000003504350000026003400039000000000303043300000db10030009c0000005b0000213d000002600510003900000000003504350000028003400039000000000303043300000280051000390000000000350435000002a001100039000002a003400039000000000303043300000000003104350000001d01000029000002a20000013d00000dae0030009c00000dae03008041000000c00130021000000de9011001c736b536b00000040f0000000003010019000000600330027000000dae0030019d00000dae0330019700020000000103550000000100200190000005600000613d000000800900003900000e25053001980000001f0630018f0000008004500039000004d20000613d000000000701034f000000007807043c0000000009890436000000000049004b000004ce0000c13d000000000006004b000004df0000613d000000000151034f0000000305600210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000001f0130003900000e250110019700000dd30010009c000006870000213d0000008001100039000000400010043f00000dea0030009c0000005b0000213d000000200030008c0000005b0000413d000000800200043d00000dd10020009c0000005b0000213d00000080033000390000009f04200039000000000034004b000000000500001900000deb0500804100000deb0630019700000deb04400197000000000764013f000000000064004b000000000400001900000deb0400404100000deb0070009c000000000405c019000000000004004b0000005b0000c13d0000008004200039000000000504043300000dd10050009c000006870000213d00000005045002100000003f0640003900000dd206600197000000000616001900000dd10060009c000006870000213d000000400060043f0000000000510435000000a0022000390000000004240019000000000034004b0000005b0000213d000000000005004b000005150000613d0000000003010019000000002502043400000db10050009c0000005b0000213d00000020033000390000000000530435000000000042004b0000050e0000413d000000400200043d00000020030000390000000003320436000000000401043300000000004304350000004003200039000000000004004b000005250000613d00000000050000190000002001100039000000000601043300000db10660019700000000036304360000000105500039000000000045004b0000051e0000413d000000000123004900000dae0010009c00000dae01008041000000600110021000000dae0020009c00000dae020080410000004002200210000000000121019f000036b60001042e0000001f05a0018f00000db006a00198000000400200043d0000000004620019000005390000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000005350000c13d000000000005004b000005460000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000006001a00210000006590000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000054f0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000055b0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000005670000c13d0000064b0000013d00000dae0010009c00000dae01008041000000c00110021000000df7011001c736b536b00000040f0000000003010019000000600330027000000dae0030019d00000dae0330019700020000000103550000000100200190000006340000613d00000e25043001980000001f0530018f0000008002400039000005820000613d0000008006000039000000000701034f000000007807043c0000000006860436000000000026004b0000057e0000c13d000000000005004b0000058f0000613d000000000141034f0000000304500210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001204350000001f0130003900000e2501100197001c00000001001d00000dd30010009c000006870000213d0000001c010000290000008001100039001d00000001001d000000400010043f00000dea0030009c0000005b0000213d000000200030008c0000005b0000413d000000800100043d00000dd10010009c0000005b0000213d00000080023000390000009f03100039000000000023004b000000000400001900000deb0400804100000deb0520019700000deb03300197000000000653013f000000000053004b000000000300001900000deb0300404100000deb0060009c000000000304c019000000000003004b0000005b0000c13d0000008003100039000000000403043300000dd10040009c000006870000213d00000005034002100000003f0530003900000dd2055001970000001d0550002900000dd10050009c000006870000213d000000400050043f0000001d050000290000000000450435000000a0011000390000000003130019000000000023004b0000005b0000213d000000000004004b000005c90000613d0000001d02000029000000001401043400000db10040009c0000005b0000213d00000020022000390000000000420435000000000031004b000005c20000413d00000dcf0100004100000000001004430000000001000412000000040010044300000060010000390000002400100443000000000100041400000dae0010009c00000dae01008041000000c00110021000000df8011001c7000080050200003936b536b00000040f0000000100200190000026890000613d000000000101043b00000db101100197000000160010006b000005e30000613d0000001d010000290000000005010433000000000005004b000000000600001900001a940000c13d0000001d010000290000000000610435002b001d0000002d002a00400000003d00000dfa01000041000000400200043d001d00000002001d0000000000120435002900040000003d00000000010004140000001602000029000000040020008c000019480000c13d000000020100036700000000030000310000195a0000013d00000dae0010009c00000dae01008041000000c00110021000000e15011001c736b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000080057001bf000006060000613d0000008008000039000000000901034f000000009a09043c0000000008a80436000000000058004b000006020000c13d000000000006004b000006130000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000006400000613d0000001f01400039000000600110018f00000080011001bf000000400010043f000000200030008c0000005b0000413d000000800200043d00000db10020009c0000005b0000213d0000000000210435000000400110021000000dd0011001c7000036b60001042e000000a004000039000000000513034f000000000505043b00000db10050009c0000005b0000213d00000000045404360000002001100039000000000021004b000006250000413d000000800200043d000000000102001900000dd10020009c000006870000213d000000400600043d0000000004010019000001d20000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000063b0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000006470000c13d000000000005004b000006580000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000dae0020009c00000dae020080410000004002200210000000000112019f000036b70001043000000df10030009c000006870000213d00000000030000190000004004100039000000400040043f000000200410003900000000000404350000000000010435000000a00430003900000000001404350000002003300039000000000023004b00000bd10000813d000000400100043d00000dfd0010009c000006610000a13d000006870000013d00000df00040009c000006870000213d0000000004000019000000c005100039000000400050043f000000a0051000390000000000050435000000800510003900000000000504350000006005100039000000000005043500000040051000390000000000050435000000200510003900000000000504350000000000010435000000a00540003900000000001504350000002004400039000000000024004b00000cbc0000813d000000400100043d00000df10010009c000006720000a13d00000e1301000041000000000010043f0000004101000039000000040010043f00000dd901000041000036b7000104300000000002000019000000400300043d00000dd50030009c000006870000213d0000022004300039000000400040043f00000200043000390000000000040435000001e0043000390000000000040435000001c0043000390000000000040435000001a00430003900000000000404350000018004300039000000000004043500000160043000390000000000040435000001400430003900000000000404350000012004300039000000000004043500000100043000390000000000040435000000e0043000390000000000040435000000c0043000390000000000040435000000a0043000390000000000040435000000800430003900000000000404350000006004300039000000000004043500000040043000390000000000040435000000200430003900000000000404350000000000030435000000000452001900000000003404350000002002200039000000000012004b0000068e0000413d0000000003000019001800000005001d000000800100043d000000000031004b0000268a0000a13d001500000003001d000000400100043d00000dd50010009c000006870000213d00000015020000290000000502200210001400000002001d000000a002200039000000000202043300000db1072001970000022002100039000000400020043f00000200021000390000000000020435000001e0021000390000000000020435000001c0021000390000000000020435000001a00210003900000000000204350000018002100039000000000002043500000160021000390000000000020435000001400210003900000000000204350000012002100039000000000002043500000100021000390000000000020435000000e0021000390000000000020435000000c0021000390000000000020435000000a0021000390000000000020435000000800210003900000000000204350000006002100039000000000002043500000040021000390000000000020435000000200210003900000000000204350000000000010435000000400a00043d00000dd60100004100000000001a04350000000001000414000000040070008c001a00000007001d000006f70000c13d0000000003000031000000200030008c00000020040000390000000004034019000007270000013d00000dae00a0009c00000dae0200004100000000020a4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c70000000002070019001d0000000a001d36b536b00000040f0000001d0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000007130000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b0000070f0000c13d0000001f07400190000007200000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001b6f0000613d000000190600002900000018050000290000001a070000290000001f01400039000000600110018f000000000ba1001900000000001b004b0000000002000039000000010200403900000dd100b0009c000006870000213d0000000100200190000006870000c13d0000004000b0043f000000200030008c0000005b0000413d00000000020a0433001300000002001d00000dd70200004100000000002b04350000000002000414000000040070008c0000076d0000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000000002070019001d0000000b001d36b536b00000040f0000001d0b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b0019000007570000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b000007530000c13d0000001f07400190000007640000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001b7b0000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a07000029000000000ab1001900000dd100a0009c000006870000213d0000004000a0043f000000200030008c0000005b0000413d00000000090b043300000db10090009c0000005b0000213d00000dd80100004100000000081a04360000000401a0003900000000007104350000000001000414000000040090008c001700000009001d000007820000c13d000000400030008c00000040040000390000000004034019000007b50000013d001c00000008001d00000dae00a0009c00000dae0200004100000000020a4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000dd9011001c70000000002090019001d0000000a001d36b536b00000040f0000001d0a0000290000000003010019000000600330027000000dae03300197000000400030008c00000040040000390000000004034019000000600640019000000000056a00190000079f0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b0000079b0000c13d0000001f07400190000007ac0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000170900002900001b870000613d000000190600002900000018050000290000001a070000290000001c080000290000001f01400039000000e00110018f000000000ba1001900000dd100b0009c000006870000213d0000004000b0043f000000400030008c0000005b0000413d00000000020a0433000000000002004b0000000001000039000000010100c039001200000002001d000000000012004b0000005b0000c13d0000000001080433001100000001001d00000dda0100004100000000001b04350000000001000414000000040070008c0000002004000039000007fd0000613d00000dae00b0009c00000dae0200004100000000020b4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c70000000002070019001d0000000b001d36b536b00000040f0000001d0b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b0019000007e80000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b000007e40000c13d0000001f07400190000007f50000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000170900002900001b930000613d000000190600002900000018050000290000001a070000290000001f01400039000000600110018f000000000ab1001900000dd100a0009c000006870000213d0000004000a0043f000000200030008c0000005b0000413d00000000020b0433001600000002001d00000db10020009c0000005b0000213d00000ddb0200004100000000002a043500000000020004140000001604000029000000040040008c000008420000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000001602000029001d0000000a001d36b536b00000040f0000001d0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000082b0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000008270000c13d0000001f07400190000008380000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000170900002900001b9f0000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000000004a1001900000dd10040009c000006870000213d000000400040043f000000200030008c0000005b0000413d00000000010a0433001000000001001d000000ff0010008c0000005b0000213d000000040090008c000008680000c13d000000000100001900000000080000190000002402400039000000000012043500000ddc02000041000000000b2404360000000402400039000000000072043500000dde0040009c000006870000213d0000004000b0043f0000000002040433000000000002004b0000000004000039000000010400c039000000000042004b0000005b0000c13d00000000021201cf000000000882019f0000000101100039000000ff0110018f000000090010008c00000000040b0019000008500000413d0000002001000039000008c00000013d00000000020000190000000008000019001c00000004001d001d00000008001d0000002401400039001b00000002001d000000000021043500000ddc0100004100000000001404350000000401400039000000000071043500000dae0040009c00000dae0100004100000000010440190000004001100210000000000200041400000dae0020009c00000dae02008041000000c002200210000000000112019f00000ddd011001c7000000000209001936b536b00000040f0000001c0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000088f0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b0000088b0000c13d0000001f074001900000089c0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000170900002900000fe50000613d0000001f01400039000000600110018f000000000ba1001900000000001b004b0000000002000039000000010200403900000dd100b0009c000000190600002900000018050000290000001a070000290000001d08000029000006870000213d0000000100200190000006870000c13d0000004000b0043f000000200030008c0000005b0000413d00000000020a0433000000000002004b0000000004000039000000010400c039000000000042004b0000005b0000c13d0000001b0400002900000000024201cf000000000882019f0000000102400039000000ff0220018f000000080020008c00000000040b00190000086a0000a13d00000ddf0200004100000000002b04350000000002000414000000040070008c001d00000008001d000008fa0000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000000002070019001c0000000b001d36b536b00000040f0000001c0b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b0019000008e20000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b000008de0000c13d0000001f07400190000008ef0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000170900002900001bab0000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000001d08000029000000000ab1001900000dd100a0009c000006870000213d0000004000a0043f000000200030008c0000005b0000413d00000000020b0433000000000002004b000009460000613d00000de00200004100000000002a04350000000002000414000000040070008c0000093c0000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000000002070019001b0000000a001d36b536b00000040f0000001b0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000009240000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000009200000c13d0000001f07400190000009310000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000170900002900001c2f0000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000001d080000290000000001a1001900000dd10010009c000006870000213d000000400010043f000000200030008c0000005b0000413d00000000020a0433001c00000002001d000000000a010019000009470000013d001c00000000001d00000de10100004100000000001a04350000000001000414000000040070008c00000020040000390000097f0000613d00000dae00a0009c00000dae0200004100000000020a4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c70000000002070019001b0000000a001d36b536b00000040f0000001b0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000009690000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000009650000c13d0000001f07400190000009760000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000170900002900001bb70000613d000000190600002900000018050000290000001a070000290000001d080000290000001f01400039000000600110018f000000000ba1001900000dd100b0009c000006870000213d0000004000b0043f000000200030008c0000005b0000413d00000000020a0433001b00000002001d00000de20200004100000000002b04350000000002000414000000040070008c000009c20000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000000002070019000f0000000b001d36b536b00000040f0000000f0b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b0019000009aa0000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b000009a60000c13d0000001f07400190000009b70000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000170900002900001bc30000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000001d08000029000000000ab1001900000dd100a0009c000006870000213d0000004000a0043f000000200030008c0000005b0000413d00000000020b0433000f00000002001d00000de30200004100000000002a04350000000402a0003900000000007204350000000002000414000000040090008c00000a050000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c70000000002090019000e0000000a001d36b536b00000040f0000000e0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000009ed0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000009e90000c13d0000001f07400190000009fa0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000170900002900001bcf0000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000001d08000029000000000ba1001900000dd100b0009c000006870000213d0000004000b0043f000000200030008c0000005b0000413d00000000020a0433001700000002001d00000de40200004100000000002b04350000000402b0003900000000007204350000000002000414000000040090008c00000a470000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c70000000002090019000e0000000b001d36b536b00000040f0000000e0b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b001900000a300000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b00000a2c0000c13d0000001f0740019000000a3d0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001bdb0000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000001d08000029000000000ab1001900000dd100a0009c000006870000213d0000004000a0043f000000200030008c0000005b0000413d00000000020b0433000e00000002001d00000de50200004100000000002a04350000000002000414000000040070008c00000a870000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000000002070019000d0000000a001d36b536b00000040f0000000d0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000a700000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000a6c0000c13d0000001f0740019000000a7d0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001be70000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000001d08000029000000000ba1001900000dd100b0009c000006870000213d0000004000b0043f000000200030008c0000005b0000413d00000000020a0433000d00000002001d00000de60200004100000000002b04350000000002000414000000040070008c00000ac70000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000000002070019000c0000000b001d36b536b00000040f0000000c0b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b001900000ab00000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b00000aac0000c13d0000001f0740019000000abd0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001bf30000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000001d08000029000000000ab1001900000dd100a0009c000006870000213d0000004000a0043f000000200030008c0000005b0000413d00000000020b0433000c00000002001d00000ddf0200004100000000002a04350000000002000414000000040070008c00000b070000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000000002070019000b0000000a001d36b536b00000040f0000000b0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000af00000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000aec0000c13d0000001f0740019000000afd0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001bff0000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000001d08000029000000000ba1001900000dd100b0009c000006870000213d0000004000b0043f000000200030008c0000005b0000413d00000000020a0433000b00000002001d00000de70200004100000000002b04350000000002000414000000040070008c00000b470000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000207001900090000000b001d36b536b00000040f000000090b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b001900000b300000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b00000b2c0000c13d0000001f0740019000000b3d0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001c0b0000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000001d08000029000000000ab1001900000dd100a0009c000006870000213d0000004000a0043f000000200030008c0000005b0000413d00000000090b043300000ddb0200004100000000002a04350000000002000414000000040070008c00000b880000613d000900000009001d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000207001900080000000a001d36b536b00000040f000000080a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000b700000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000b6c0000c13d0000001f0740019000000b7d0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000090900002900001c170000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000001d080000290000000001a1001900000dd10010009c000006870000213d000000400010043f000000200030008c0000005b0000413d00000000020a0433000000ff0020008c0000005b0000213d00000dd50010009c000006870000213d0000022003100039000000400030043f000002000310003900000000008304350000001003000029000000ff0330018f000001e0041000390000000000340435000001c0031000390000000000230435000001a002100039000000160300002900000000003204350000018002100039000000110300002900000000003204350000016002100039000000120300002900000000003204350000014002100039000000000092043500000120021000390000000b03000029000000000032043500000100021000390000000c030000290000000000320435000000e0021000390000000d030000290000000000320435000000c0021000390000000e030000290000000000320435000000a0021000390000001703000029000000000032043500000080021000390000000f03000029000000000032043500000060021000390000001b03000029000000000032043500000040021000390000001c030000290000000000320435000000200210003900000013030000290000000000320435000000000071043500000000020604330000001503000029000000000032004b0000268a0000a13d000000140250002900000000001204350000000001060433000000000031004b0000268a0000a13d00000001033000390000000a0030006c000006bb0000413d000001e40000013d0000000003000019001c00000003001d0000000502300210001b00000002001d00000019012000290000000101100367000000000501043b00000db10050009c0000005b0000213d000000400100043d00000dfd0010009c000006870000213d0000004002100039000000400020043f000000200210003900000000000204350000000000010435000000400b00043d00000dd70100004100000000001b04350000000001000414000000040050008c001d00000005001d00000bee0000c13d0000000003000031000000200030008c0000002004000039000000000403401900000c1c0000013d00000dae00b0009c00000dae0200004100000000020b4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c7000000000205001900180000000b001d36b536b00000040f000000180b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b001900000c0a0000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b00000c060000c13d0000001f0740019000000c170000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000019240000613d0000001d050000290000001f01400039000000600110018f000000000ab1001900000000001a004b0000000002000039000000010200403900000dd100a0009c000006870000213d0000000100200190000006870000c13d0000004000a0043f000000200030008c0000005b0000413d00000000020b043300000db10020009c0000005b0000213d00000e1b0400004100000000004a04350000000004000414000000040020008c00000c600000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000db3011001c700180000000a001d36b536b00000040f000000180a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000c4c0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000c480000c13d0000001f0740019000000c590000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000019300000613d0000001f01400039000000600110018f0000001d05000029000000000ba1001900000dd100b0009c000006870000213d0000004000b0043f000000200030008c0000005b0000413d00000000020a043300000db10020009c0000005b0000213d00000e1d0400004100000000004b04350000000404b0003900000000005404350000000004000414000000040020008c00000c9f0000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000dd9011001c700180000000b001d36b536b00000040f000000180b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b001900000c8b0000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b00000c870000c13d0000001f0740019000000c980000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000193c0000613d0000001f01400039000000600110018f0000001d050000290000000001b1001900000dd10010009c000006870000213d000000400010043f000000200030008c0000005b0000413d00000dfd0010009c000006870000213d00000000020b04330000004003100039000000400030043f000000200310003900000000002304350000000000510435000000800200043d0000001c03000029000000000032004b0000268a0000a13d0000001b02000029000000a0022000390000000000120435000000800100043d000000000031004b0000268a0000a13d00000001033000390000001a0030006c00000bd20000413d000000400100043d000000870000013d001d0db10030019b0000000003000019001b00000003001d0000000502300210001a00000002001d00000015012000290000000101100367000000000501043b00000db10050009c0000005b0000213d000000400100043d00000df10010009c000006870000213d000000c002100039000000400020043f000000a0021000390000000000020435000000800210003900000000000204350000006002100039000000000002043500000040021000390000000000020435000000200210003900000000000204350000000000010435000000400b00043d00000df20100004100000000001b04350000000401b000390000001d0200002900000000002104350000000001000414000000040050008c001c00000005001d00000ce50000c13d0000000003000031000000200030008c0000002004000039000000000403401900000d130000013d00000dae00b0009c00000dae0200004100000000020b4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000dd9011001c7000000000205001900190000000b001d36b536b00000040f000000190b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b001900000d010000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b00000cfd0000c13d0000001f0740019000000d0e0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001b0f0000613d0000001c050000290000001f01400039000000600110018f000000000ab1001900000000001a004b0000000002000039000000010200403900000dd100a0009c000006870000213d0000000100200190000006870000c13d0000004000a0043f000000200030008c0000005b0000413d00000000020b0433001900000002001d00000df30200004100000000002a04350000000402a000390000001d0400002900000000004204350000000002000414000000040050008c00000d5a0000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c7000000000205001900180000000a001d36b536ab0000040f000000180a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000d460000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000d420000c13d0000001f0740019000000d530000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001b1b0000613d0000001f01400039000000600110018f0000001c05000029000000000ba1001900000dd100b0009c000006870000213d0000004000b0043f000000200030008c0000005b0000413d00000000020a0433001800000002001d00000df40200004100000000002b04350000000402b000390000001d0400002900000000004204350000000002000414000000040050008c00000d9a0000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c7000000000205001900170000000b001d36b536ab0000040f000000170b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b001900000d860000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b00000d820000c13d0000001f0740019000000d930000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001b270000613d0000001f01400039000000600110018f0000001c05000029000000000ab1001900000dd100a0009c000006870000213d0000004000a0043f000000200030008c0000005b0000413d00000000020b0433001700000002001d00000dda0200004100000000002a04350000000002000414000000040050008c00000dd70000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900140000000a001d36b536b00000040f000000140a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000dc30000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000dbf0000c13d0000001f0740019000000dd00000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001b330000613d0000001f01400039000000600110018f0000001c05000029000000000ba1001900000dd100b0009c000006870000213d0000004000b0043f000000200030008c0000005b0000413d00000000060a043300000db10060009c0000005b0000213d00000df20200004100000000002b04350000000402b000390000001d0400002900000000004204350000000002000414000000040060008c00000e1a0000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c7001300000006001d000000000206001900140000000b001d36b536b00000040f000000140b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b001900000e050000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b00000e010000c13d0000001f0740019000000e120000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001b3f0000613d0000001f01400039000000600110018f0000001c050000290000001306000029000000000ab1001900000dd100a0009c000006870000213d0000004000a0043f000000200030008c0000005b0000413d00000000070b04330000002402a00039000000000052043500000df50200004100000000002a04350000000402a000390000001d0400002900000000004204350000000002000414000000040060008c00000e5d0000613d001300000007001d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000ddd011001c7000000000206001900140000000a001d36b536b00000040f000000140a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000e480000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000e440000c13d0000001f0740019000000e550000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001b4b0000613d0000001f01400039000000600110018f0000001c0500002900000013070000290000000001a1001900000dd10010009c000006870000213d000000400010043f000000200030008c0000005b0000413d00000df10010009c000006870000213d00000000020a0433000000c003100039000000400030043f000000a0031000390000000000230435000000800210003900000000007204350000006002100039000000170300002900000000003204350000004002100039000000180300002900000000003204350000002002100039000000190300002900000000003204350000000000510435000000800200043d0000001b03000029000000000032004b0000268a0000a13d0000001a02000029000000a0022000390000000000120435000000800100043d000000000031004b0000268a0000a13d0000000103300039000000160030006c00000cbe0000413d000000400100043d0000017a0000013d0000001b09000029000000007207043400000dd10020009c0000005b0000213d000000000a120019000000200da000390000000002d4004900000dea0020009c0000005b0000213d000000a00020008c0000005b0000413d000000400b00043d00000e1800b0009c000006870000213d000000a00cb000390000004000c0043f00000000020d043300000dd10020009c0000005b0000213d000000000dd200190000001f02d00039000000000042004b000000000e00001900000deb0e00804100000deb02200197000000000f52013f000000000052004b000000000200001900000deb0200404100000deb00f0009c00000000020ec019000000000002004b0000005b0000c13d00000000ed0d043400000dd100d0009c000006870000213d0000001f02d0003900000e25022001970000003f0220003900000e25022001970000000002c2001900000dd10020009c000006870000213d000000400020043f0000000000dc04350000000002ed0019000000000042004b0000005b0000213d000000c00fb0003900000000000d004b00000ec00000613d00000000020000190000000003f200190000000006e200190000000006060433000000000063043500000020022000390000000000d2004b00000eb90000413d0000000002fd001900000000000204350000000002cb04360000004003a00039000000000c03043300000db100c0009c0000005b0000213d0000000000c204350000006002a00039000000000202043300000db10020009c0000005b0000213d00000020099000390000004003b0003900000000002304350000008002a0003900000000020204330000006003b000390000000000230435000000a002a0003900000000020204330000008003b0003900000000002304350000000000b90435000000000087004b00000e860000413d0000001b010000290000000006010433003500000001001d0000000001000415000000320110008a00010005001002180000000001000415000000310110008a0002000500100218003200000006001d00000dd10060009c0000039b0000a13d000006870000013d0000001d0200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c7000000160200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000001d0570002900000f020000613d000000000801034f0000001d09000029000000008a08043c0000000009a90436000000000059004b00000efe0000c13d000000000006004b00000f0f0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000000ff10000613d0000001f01400039000000600210018f0000001d01200029000000000021004b0000000002000039000000010200403900000dd10010009c0000001909000029000006870000213d0000000100200190000006870000c13d000000400010043f000000200030008c0000005b0000413d0000001d02000029000000000202043300000db10020009c0000005b0000213d000000000609043300000dd10060009c000006870000213d00000005046002100000003f0540003900000dd205500197000000000515001900000dd10050009c000006870000213d000000400050043f0000000005610436000000000006004b00000f400000613d0000000006000019000000400700043d00000dfd0070009c000006870000213d0000004008700039000000400080043f000000200870003900000000000804350000000000070435000000000865001900000000007804350000002006600039000000000046004b00000f330000413d000000400400043d001200000004001d00000dfe0040009c000006870000213d00000012050000290000006004500039000000400040043f0000004004500039001400000004001d000000000014043500000016010000290000000001150436001100000001001d00000000000104350000000001090433000000000001004b001a00000000001d00001c3b0000c13d00000011040000290000001a0100002900000000001404350000002002000039000000400100043d00000000022104360000001203000029000000000303043300000db103300197000000000032043500000000020404330000004003100039000000000023043500000014020000290000000002020433000000600310003900000060040000390000000000430435000000800310003900000000040204330000000000430435000000a003100039000000000004004b0000009f0000613d000000000500001900000020022000390000000006020433000000007606043400000db10660019700000000066304360000000007070433000000000076043500000040033000390000000105500039000000000045004b00000f6b0000413d0000009f0000013d0000001d01000029000001000810003900000df909000041000000000a0000190000000007000019001800000006001d001700000008001d00000f820000013d000000010aa0003900000000006a004b0000042e0000813d00000000010504330000000000a1004b0000268a0000a13d0000000501a00210000000000b81001900000000020b0433000000400c00043d00000000009c0435000000000100041400000db102200197000000040020008c00000f930000c13d0000000003000031000000200030008c0000002004000039000000000403401900000fc90000013d001c0000000b001d001d0000000a001d001a00000007001d00000dae00c0009c00000dae0300004100000000030c4019000000400330021000000dae0010009c00000dae01008041000000c001100210000000000131019f00000db3011001c7001b0000000c001d36b536b00000040f0000001b0c0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056c001900000fb10000613d000000000701034f00000000080c0019000000007907043c0000000008980436000000000058004b00000fad0000c13d0000001f0740019000000fbe0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000190500002900000df9090000410000001d0a0000290000001c0b00002900001b570000613d00000018060000290000001a0700002900000017080000290000001f01400039000000600210018f0000000001c20019000000000021004b0000000002000039000000010200403900000dd10010009c000006870000213d0000000100200190000006870000c13d000000400010043f000000200030008c0000005b0000413d00000000010c0433000000000001004b00000f7f0000613d00000000010504330000000000a1004b0000268a0000a13d000000000071004b0000268a0000a13d0000000501700210000000000181001900000000020b043300000db1022001970000000000210435000000010770003900000f7f0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000fec0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000ff80000c13d0000064b0000013d000000600d0000390000000006000019000000400700043d00000e1f0070009c000006870000213d000001a001700039000000400010043f00000180017000390000000000d10435000000e0017000390000000000d10435000000c0017000390000000000d10435000000a0017000390000000000d104350000000001d70436000001600370003900000000000304350000014003700039000000000003043500000120037000390000000000030435000001000370003900000000000304350000008003700039000000000003043500000060037000390000000000030435000000400370003900000000000304350000000000010435000000000165001900000000007104350000002006600039000000000046004b00000fff0000413d00000002010000290000000501100270000000000102001f003000000000003d000000000400001900000035050000290000000001050433000000000041004b0000268a0000a13d000000400200043d00000e1f0020009c000006870000213d00000005014002100000000001510019000400360000002d00000020011000390000000004010433000001a001200039000000400010043f00000180012000390000000000d10435000000e0012000390000000000d10435000000c0012000390000000000d10435000000a0012000390000000000d104350000000001d20436000001600320003900000000000304350000014003200039000000000003043500000120032000390000000000030435000001000320003900000000000304350000008003200039000000000003043500000060032000390000000000030435000000400220003900000000000204350000000000010435000300000004001d0000004001400039000500000001001d0000000001010433000000400900043d00000df6020000410000000000290435000000000200041400000db101100197001a00000001001d000000040010008c0000001c0100035f0000001d080000290000106f0000613d00000dae0090009c001d00000009001d00000dae010000410000000001094019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000001a0200002936b536b00000040f0000000003010019000000600330027000000dae0030019d00000dae0830019700020000000103550000000100200190000026960000613d000000600d0000390000001d0900002900000e25048001980000000002490019000010780000613d000000000501034f0000000006090019000000005305043c0000000006360436000000000026004b000010740000c13d0000001f05800190000010850000613d000000000141034f0000000303500210000000000402043300000000043401cf000000000434022f000000000101043b0000010003300089000000000131022f00000000013101cf000000000141019f000000000012043500000000030800190000001f0180003900000e250110019700000000040900190000000002910019000000000012004b00000000010000390000000101004039001400000002001d00000dd10020009c000006870000213d0000000100100190000006870000c13d0000001401000029000000400010043f00000dea0030009c0000005b0000213d000000200030008c0000005b0000413d000000000104043300000dd10010009c0000005b0000213d000000000243001900000000014100190000001f03100039000000000023004b000000000400001900000deb0400804100000deb0330019700000deb05200197000000000653013f000000000053004b000000000300001900000deb0300404100000deb0060009c000000000304c019000000000003004b0000005b0000c13d000000001301043400000dd10030009c000006870000213d00000005043002100000003f0540003900000dd205500197000000140550002900000dd10050009c000006870000213d000000400050043f00000014050000290000000003350436000600000003001d0000000003140019000000000023004b0000005b0000213d000000000031004b000010c50000813d0000001402000029000000001401043400000db10040009c0000005b0000213d00000020022000390000000000420435000000000031004b000010be0000413d00000dcf010000410000000000100443000000000100041200000004001004430000002400d00443000000000100041400000dae0010009c00000dae01008041000000c00110021000000df8011001c7000080050200003936b536b00000040f0000000100200190000026890000613d00000014020000290000000004020433000000000101043b00000db1011001970000001a0010006b000010dc0000c13d0000000003040019000000600d000039000011520000013d000000000004004b000000600d0000390000114f0000613d00000000050000190000000003000019001b00000004001d000010e70000013d0000001d050000290000000105500039000000000045004b000011500000813d00000014010000290000000001010433000000000051004b0000268a0000a13d001600000003001d00000005015002100000000601100029001c00000001001d0000000002010433000000400a00043d00000df90100004100000000001a0435000000000100041400000db102200197000000040020008c001d00000005001d000010fd0000c13d0000000003000031000000200030008c000000200400003900000000040340190000112a0000013d00000dae00a0009c00000dae0300004100000000030a4019000000400330021000000dae0010009c00000dae01008041000000c001100210000000000131019f00000db3011001c7001a0000000a001d36b536b00000040f0000001a0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000011180000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000011140000c13d0000001f07400190000011250000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001e4a0000613d0000001f01400039000000600210018f00000000040a00190000000001a20019000000000021004b0000000002000039000000010200403900000dd10010009c000006870000213d0000000100200190000006870000c13d000000400010043f000000200030008c0000005b0000413d0000000001040433000000000001004b00000016030000290000001b04000029000010e30000613d000000140100002900000000010104330000001d05000029000000000051004b0000268a0000a13d000000000031004b0000268a0000a13d000000050130021000000006011000290000001c02000029000000000202043300000db102200197000000000021043500000001033000390000000105500039000000000045004b000010e70000413d000011500000013d000000000300001900000014010000290000000000310435001600000003001d00000dd10030009c000006870000213d000000160100002900000005011002100000003f0210003900000dd202200197000000400300043d0000000002230019001500000003001d000000000032004b0000000003000039000000010300403900000dd10020009c000006870000213d0000000100300190000006870000c13d000000400020043f000000150200002900000016030000290000000002320436001300000002001d000000000003004b000000200700008a000016c40000613d0000000002000019000000400300043d00000dd50030009c000006870000213d0000022004300039000000400040043f00000200043000390000000000040435000001e0043000390000000000040435000001c0043000390000000000040435000001a00430003900000000000404350000018004300039000000000004043500000160043000390000000000040435000001400430003900000000000404350000012004300039000000000004043500000100043000390000000000040435000000e0043000390000000000040435000000c0043000390000000000040435000000a0043000390000000000040435000000800430003900000000000404350000006004300039000000000004043500000040043000390000000000040435000000200430003900000000000404350000000000030435000000130420002900000000003404350000002002200039000000000012004b0000116c0000413d000000000400001900000014010000290000000001010433000000000041004b0000268a0000a13d001700000004001d000000400100043d00000dd50010009c000006870000213d00000017020000290000000503200210001200000003001d0000000602300029000000000202043300000db1052001970000022002100039000000400020043f00000200021000390000000000020435000001e0021000390000000000020435000001c0021000390000000000020435000001a00210003900000000000204350000018002100039000000000002043500000160021000390000000000020435000001400210003900000000000204350000012002100039000000000002043500000100021000390000000000020435000000e0021000390000000000020435000000c0021000390000000000020435000000a0021000390000000000020435000000800210003900000000000204350000006002100039000000000002043500000040021000390000000000020435000000200210003900000000000204350000000000010435000000400a00043d00000dd60100004100000000001a04350000000001000414000000040050008c001a00000005001d000011d50000c13d0000000003000031000000200030008c00000020040000390000000004034019000012040000013d00000dae00a0009c00000dae0200004100000000020a4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c70000000002050019001d0000000a001d36b536b00000040f0000001d0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000011f10000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000011ed0000c13d0000001f07400190000011fe0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001d8a0000613d0000001a050000290000001f01400039000000600110018f00000000060a00190000000004a10019000000000014004b00000000020000390000000102004039001d00000004001d00000dd10040009c000006870000213d0000000100200190000006870000c13d0000001d02000029000000400020043f000000200030008c0000005b0000413d0000000002060433001100000002001d00000dd7020000410000001d0a00002900000000002a04350000000002000414000000040050008c0000124c0000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001936b536b00000040f0000001d0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000012370000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000012330000c13d0000001f07400190000012440000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001d720000613d0000001f01400039000000600110018f0000001a050000290000000001a10019001c00000001001d00000dd10010009c000006870000213d0000001c01000029000000400010043f000000200030008c0000005b0000413d0000001d010000290000000001010433001900000001001d00000db10010009c0000005b0000213d00000dd8010000410000001c0a00002900000000011a0436001b00000001001d0000000401a00039000000000051043500000000010004140000001902000029000000040020008c000012670000c13d000000400030008c00000040040000390000000004034019000012940000013d00000dae00a0009c00000dae0300004100000000030a4019000000400330021000000dae0010009c00000dae01008041000000c001100210000000000131019f00000dd9011001c736b536b00000040f0000001c0a0000290000000003010019000000600330027000000dae03300197000000400030008c00000040040000390000000004034019000000600640019000000000056a0019000012810000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b0000127d0000c13d0000001f074001900000128e0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001d960000613d0000001a050000290000001f01400039000000e00110018f0000000001a10019001d00000001001d00000dd10010009c000006870000213d0000001d01000029000000400010043f000000400030008c0000005b0000413d0000001c010000290000000002010433000000000002004b0000000001000039000000010100c039001000000002001d000000000012004b0000005b0000c13d0000001b010000290000000001010433000f00000001001d00000dda010000410000001d0a00002900000000001a04350000000001000414000000040050008c0000002004000039000012de0000613d00000dae00a0009c00000dae0200004100000000020a4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c7000000000205001936b536b00000040f0000001d0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000012cb0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000012c70000c13d0000001f07400190000012d80000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001d7e0000613d0000001a050000290000001f01400039000000600110018f0000000002a10019001c00000002001d00000dd10020009c000006870000213d0000001c02000029000000400020043f000000200030008c0000005b0000413d0000001d020000290000000002020433001800000002001d00000db10020009c0000005b0000213d00000ddb020000410000001c0a00002900000000002a043500000000020004140000001804000029000000040040008c000013240000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000180200002936b536b00000040f0000001c0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000130f0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b0000130b0000c13d0000001f074001900000131c0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001da20000613d0000001f01400039000000600110018f0000001a050000290000000004a1001900000dd10040009c000006870000213d000000400040043f000000200030008c0000005b0000413d0000001c010000290000000001010433000e00000001001d000000ff0010008c0000005b0000213d0000001901000029000000040010008c0000134c0000c13d000000000100001900000000060000190000002402400039000000000012043500000ddc02000041000000000a2404360000000402400039000000000052043500000dde0040009c000006870000213d0000004000a0043f0000000002040433000000000002004b0000000004000039000000010400c039000000000042004b0000005b0000c13d00000000021201cf000000000662019f0000000101100039000000ff0110018f000000090010008c00000000040a0019000013340000413d0000002001000039000013a20000013d00000000020000190000000006000019001c00000004001d001d00000006001d0000002401400039001b00000002001d000000000021043500000ddc0100004100000000001404350000000401400039000000000051043500000dae0040009c00000dae0100004100000000010440190000004001100210000000000200041400000dae0020009c00000dae02008041000000c002200210000000000112019f00000ddd011001c7000000190200002936b536b00000040f0000001c0b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b0019000013730000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b0000136f0000c13d0000001f07400190000000600d000039000013810000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001b630000613d0000001f01400039000000600110018f000000000ab1001900000000001a004b0000000002000039000000010200403900000dd100a0009c0000001a050000290000001d06000029000006870000213d0000000100200190000006870000c13d0000004000a0043f000000200030008c0000005b0000413d00000000020b0433000000000002004b0000000004000039000000010400c039000000000042004b0000005b0000c13d0000001b0400002900000000024201cf000000000662019f0000000102400039000000ff0220018f000000080020008c00000000040a00190000134e0000a13d00000ddf0200004100000000002a04350000000002000414000000040050008c001d00000006001d000013da0000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000000002050019001c0000000a001d36b536b00000040f0000001c0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000013c40000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000013c00000c13d0000001f07400190000013d10000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001dea0000613d0000001f01400039000000600110018f0000001a050000290000001d060000290000000002a10019001c00000002001d00000dd10020009c000006870000213d0000001c02000029000000400020043f000000200030008c0000005b0000413d00000000020a0433000000000002004b000014270000613d00000de0020000410000001c0a00002900000000002a04350000000002000414000000040050008c0000141c0000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001936b536b00000040f0000001c0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000014060000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000014020000c13d0000001f07400190000014130000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001e260000613d0000001f01400039000000600110018f0000001a050000290000001d060000290000000001a1001900000dd10010009c000006870000213d000000400010043f000000200030008c0000005b0000413d0000001c020000290000000002020433000d00000002001d000000000a010019000014290000013d000d00000000001d0000001c0a00002900000de10100004100000000001a04350000000001000414000000040050008c00000020040000390000145f0000613d00000dae00a0009c00000dae0200004100000000020a4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c70000000002050019001c0000000a001d36b536b00000040f0000001c0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000144b0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000014470000c13d0000001f07400190000014580000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001df60000613d0000001a050000290000001d060000290000001f01400039000000600110018f00000000020a00190000000004a10019001c00000004001d00000dd10040009c000006870000213d0000001c04000029000000400040043f000000200030008c0000005b0000413d0000000002020433000c00000002001d00000de2020000410000001c0a00002900000000002a04350000000002000414000000040050008c000014a30000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001936b536b00000040f0000001c0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000148d0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000014890000c13d0000001f074001900000149a0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001dae0000613d0000001f01400039000000600110018f0000001a050000290000001d060000290000000002a10019001b00000002001d00000dd10020009c000006870000213d0000001b02000029000000400020043f000000200030008c0000005b0000413d0000001c020000290000000002020433000b00000002001d00000de3020000410000001b0a00002900000000002a04350000000402a00039000000000052043500000000040004140000001902000029000000040020008c000014e70000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000dd9011001c736b536b00000040f0000001b0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000014d10000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000014cd0000c13d0000001f07400190000014de0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001e020000613d0000001f01400039000000600110018f0000001a050000290000001d060000290000000002a10019001c00000002001d00000dd10020009c000006870000213d0000001c02000029000000400020043f000000200030008c0000005b0000413d0000001b020000290000000002020433000a00000002001d00000de4020000410000001c0a00002900000000002a04350000000402a00039000000000052043500000000040004140000001902000029000000040020008c0000152b0000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000dd9011001c736b536b00000040f0000001c0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000015150000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000015110000c13d0000001f07400190000015220000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001dba0000613d0000001f01400039000000600110018f0000001a050000290000001d060000290000000002a10019001b00000002001d00000dd10020009c000006870000213d0000001b02000029000000400020043f000000200030008c0000005b0000413d0000001c020000290000000002020433001900000002001d00000de5020000410000001b0a00002900000000002a04350000000002000414000000040050008c0000156d0000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001936b536b00000040f0000001b0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000015570000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000015530000c13d0000001f07400190000015640000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001e0e0000613d0000001f01400039000000600110018f0000001a050000290000001d060000290000000002a10019001c00000002001d00000dd10020009c000006870000213d0000001c02000029000000400020043f000000200030008c0000005b0000413d0000001b020000290000000002020433000900000002001d00000de6020000410000001c0a00002900000000002a04350000000002000414000000040050008c000015af0000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001936b536b00000040f0000001c0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000015990000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000015950000c13d0000001f07400190000015a60000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001dc60000613d0000001f01400039000000600110018f0000001a050000290000001d060000290000000002a10019001b00000002001d00000dd10020009c000006870000213d0000001b02000029000000400020043f000000200030008c0000005b0000413d0000001c020000290000000002020433000800000002001d00000ddf020000410000001b0a00002900000000002a04350000000002000414000000040050008c000015f10000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001936b536b00000040f0000001b0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000015db0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000015d70000c13d0000001f07400190000015e80000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001e1a0000613d0000001f01400039000000600110018f0000001a050000290000001d060000290000000002a10019001c00000002001d00000dd10020009c000006870000213d0000001c02000029000000400020043f000000200030008c0000005b0000413d0000001b020000290000000002020433000700000002001d00000de7020000410000001c0a00002900000000002a04350000000002000414000000040050008c000016330000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001936b536b00000040f0000001c0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000161d0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000016190000c13d0000001f074001900000162a0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001dd20000613d0000001f01400039000000600110018f0000001a050000290000001d060000290000000002a10019001b00000002001d00000dd10020009c000006870000213d0000001b02000029000000400020043f000000200030008c0000005b0000413d0000001c020000290000000002020433001c00000002001d00000ddb020000410000001b0a00002900000000002a04350000000002000414000000040050008c000016750000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001936b536b00000040f0000001b0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000165f0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b0000165b0000c13d0000001f074001900000166c0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001dde0000613d0000001f01400039000000600110018f0000001a050000290000001d060000290000000001a1001900000dd10010009c000006870000213d000000400010043f000000200030008c0000005b0000413d0000001b020000290000000002020433000000ff0020008c0000005b0000213d00000dd50010009c000006870000213d0000022003100039000000400030043f000002000310003900000000006304350000000e03000029000000ff0330018f000001e0041000390000000000340435000001c0031000390000000000230435000001a0021000390000001803000029000000000032043500000180021000390000000f03000029000000000032043500000160021000390000001003000029000000000032043500000140021000390000001c030000290000000000320435000001200210003900000007030000290000000000320435000001000210003900000008030000290000000000320435000000e00210003900000009030000290000000000320435000000c00210003900000019030000290000000000320435000000a0021000390000000a03000029000000000032043500000080021000390000000b03000029000000000032043500000060021000390000000c03000029000000000032043500000040021000390000000d0300002900000000003204350000002002100039000000110300002900000000003204350000000000510435000000150200002900000000020204330000001704000029000000000042004b000000200700008a00000016030000290000268a0000a13d00000012050000290000001302500029000000000012043500000015010000290000000001010433000000000041004b0000268a0000a13d0000000104400039000000000034004b000011980000413d00000005010000290000000001010433000000400900043d00000e2002000041000000000029043500000db101100197000000040290003900000000001204350000000001000414000000040200002900000db102200197000000040020008c000016d40000c13d00000002010003670000000008000031000016e90000013d00000dae0090009c001d00000009001d00000dae030000410000000003094019000000400330021000000dae0010009c00000dae01008041000000c001100210000000000131019f00000dd9011001c736b536b00000040f0000000003010019000000600330027000000dae0030019d00000dae0830019700020000000103550000000100200190000026a40000613d000000200700008a000000600d0000390000001d0900002900000000047801700000000002490019000016f20000613d000000000501034f0000000006090019000000005305043c0000000006360436000000000026004b000016ee0000c13d0000001f05800190000016ff0000613d000000000641034f0000000303500210000000000402043300000000043401cf000000000434022f000000000506043b0000010003300089000000000535022f00000000033501cf000000000343019f0000000000320435001c000000010353001d00000008001d0000001f01800039000000000171016f00000000030900190000000002910019000000000012004b0000000004000039000000010400403900000dd10020009c000006870000213d0000000100400190000006870000c13d000000400020043f0000001d0100002900000dea0010009c0000005b0000213d0000001d01000029000000200010008c0000005b0000413d000000000503043300000dd10050009c0000005b0000213d0000001d043000290000000005350019000000000654004900000dea0060009c0000005b0000213d000000600060008c0000005b0000413d00000dfe0020009c000006870000213d0000006006200039000000400060043f000000008705043400000dd10070009c0000005b0000213d00000000095700190000001f01900039000000000041004b000000000300001900000deb0300804100000deb0110019700000deb07400197000000000a71013f000000000071004b000000000100001900000deb0100404100000deb00a0009c000000000103c019000000000001004b0000005b0000c13d00000000a909043400000dd10090009c000006870000213d0000001f0190003900000e25011001970000003f0110003900000e2501100197000000000b61001900000dd100b0009c000006870000213d0000004000b0043f00000000009604350000000001a90019000000000041004b0000005b0000213d000000800b200039000000000009004b0000174d0000613d000000000c0000190000000001bc00190000000003ac001900000000030304330000000000310435000000200cc0003900000000009c004b000017460000413d0000000001b9001900000000000104350000000006620436000000000808043300000dd10080009c0000005b0000213d00000000085800190000001f01800039000000000041004b000000000300001900000deb0300804100000deb01100197000000000971013f000000000071004b000000000100001900000deb0100404100000deb0090009c000000000103c019000000000001004b0000005b0000c13d000000009808043400000dd10080009c000006870000213d0000001f0180003900000e25011001970000003f0110003900000e2501100197000000400a00043d000000000b1a00190000000000ab004b000000000c000039000000010c00403900000dd100b0009c000006870000213d0000000100c00190000006870000c13d0000004000b0043f000000000b8a04360000000001980019000000000041004b0000005b0000213d000000000008004b000017800000613d000000000c0000190000000001bc001900000000039c001900000000030304330000000000310435000000200cc0003900000000008c004b000017790000413d00000000018b001900000000000104350000000000a604350000004001500039000000000801043300000dd10080009c0000005b0000213d00000000055800190000001f01500039000000000041004b000000000300001900000deb0300804100000deb01100197000000000871013f000000000071004b000000000100001900000deb0100404100000deb0080009c000000000103c019000000000001004b0000005b0000c13d000000007505043400000dd10050009c000006870000213d0000001f0150003900000e25011001970000003f0110003900000e2501100197000000400300043d0000000008130019001800000003001d000000000038004b0000000009000039000000010900403900000dd10080009c000006870000213d0000000100900190000006870000c13d000000400080043f000000180100002900000000085104360000000001750019000000000041004b0000005b0000213d000000000005004b000017b60000613d000000000400001900000000018400190000000003740019000000000303043300000000003104350000002004400039000000000054004b000017af0000413d000000000158001900000000000104350000004001200039000000180300002900000000003104350000000001020433001400000001001d0000000001060433001100000001001d000000030200002900000080012000390000000001010433001200000001001d00000060012000390000000001010433001300000001001d00000020012000390000000001010433001600000001001d0000000001020433001700000001001d00000005010000290000000001010433000000400a00043d00000e1b0200004100000000002a0435000000000300041400000db102100197000000040020008c0000001d01000029001b00000002001d000017da0000c13d000000200010008c00000020040000390000000004014019000018090000013d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0030009c00000dae03008041000000c003300210000000000113019f00000db3011001c7001a0000000a001d36b536b00000040f0000001a0a0000290000000003010019000000600330027000000dae09300197000000200090008c00000020040000390000000004094019000000200640019000000000056a0019000017f50000613d000000000701034f00000000080a0019000000007307043c0000000008380436000000000058004b000017f10000c13d0000001f07400190000018020000613d000000000861034f0000000303700210000000000605043300000000063601cf000000000636022f000000000708043b0000010003300089000000000737022f00000000033701cf000000000363019f0000000000350435000000000009001f001c00000001035300020000000103550000000100200190000000600d000039000026c00000613d001d00000009001d0000001f01400039000000600310018f00000000020a00190000000001a30019000000000031004b00000000040000390000000104004039001a00000001001d00000dd10010009c000006870000213d0000000100400190000006870000c13d0000001a01000029000000400010043f0000001d01000029000000200010008c0000005b0000413d0000000001020433001000000001001d00000db10010009c0000005b0000213d00000e21010000410000001a0a00002900000000001a043500000000040004140000001b02000029000000040020008c000018550000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000db3011001c736b536b00000040f0000001a0a0000290000000003010019000000600330027000000dae09300197000000200090008c00000020040000390000000004094019000000200640019000000000056a00190000183f0000613d000000000701034f00000000080a0019000000007307043c0000000008380436000000000058004b0000183b0000c13d0000001f074001900000184c0000613d000000000861034f0000000303700210000000000605043300000000063601cf000000000636022f000000000708043b0000010003300089000000000737022f00000000033701cf000000000363019f0000000000350435001d00000009001d000000000009001f001c00000001035300020000000103550000000100200190000000600d000039000026d90000613d0000001f01400039000000600310018f0000000001a30019001900000001001d00000dd10010009c000006870000213d0000001901000029000000400010043f0000001d01000029000000200010008c0000005b0000413d0000001a010000290000000001010433000f00000001001d00000e2201000041000000190a00002900000000001a043500000000040004140000001b02000029000000040020008c000018980000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000db3011001c736b536b00000040f000000190a0000290000000003010019000000600330027000000dae09300197000000200090008c00000020040000390000000004094019000000200640019000000000056a0019000018820000613d000000000701034f00000000080a0019000000007307043c0000000008380436000000000058004b0000187e0000c13d0000001f074001900000188f0000613d000000000861034f0000000303700210000000000605043300000000063601cf000000000636022f000000000708043b0000010003300089000000000737022f00000000033701cf000000000363019f0000000000350435001d00000009001d000000000009001f001c00000001035300020000000103550000000100200190000000600d000039000026e60000613d0000001f01400039000000600310018f0000000001a30019001a00000001001d00000dd10010009c000006870000213d0000001a01000029000000400010043f0000001d01000029000000200010008c0000005b0000413d00000019010000290000000001010433001900000001001d00000e23010000410000001a0a00002900000000001a043500000000040004140000001b02000029000000040020008c000018db0000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000db3011001c736b536b00000040f0000001a0a0000290000000003010019000000600330027000000dae09300197000000200090008c00000020040000390000000004094019000000200640019000000000056a0019000018c50000613d000000000701034f00000000080a0019000000007307043c0000000008380436000000000058004b000018c10000c13d0000001f07400190000018d20000613d000000000861034f0000000303700210000000000605043300000000063601cf000000000636022f000000000708043b0000010003300089000000000737022f00000000033701cf000000000363019f0000000000350435001d00000009001d000000000009001f001c00000001035300020000000103550000000100200190000000600d000039000026f30000613d0000001f01400039000000600310018f0000000004a3001900000dd10040009c000006870000213d000000400040043f0000001d01000029000000200010008c0000005b0000413d00000e1f0040009c000006870000213d0000001a010000290000000001010433000001a002400039000000400020043f0000018002400039000000150300002900000000003204350000016002400039000000000012043500000140014000390000001902000029000000000021043500000120014000390000000f020000290000000000210435000001000140003900000010020000290000000000210435000000e00140003900000018020000290000000000210435000000c00140003900000011020000290000000000210435000000a0014000390000001402000029000000000021043500000080014000390000001202000029000000000021043500000060014000390000001302000029000000000021043500000040014000390000001b020000290000000000210435000000160100002900000db101100197000000200240003900000000001204350000001701000029000000000014043500000002010000290000000501100270000000000201003100000000010204330000003005000029000000000051004b0000268a0000a13d00000005015002100000000001120019000000200110003900000000004104350000000001020433000000000051004b0000268a0000a13d003000010050003d0000000104500039000000010100002900000005011002700000000001010031000000000014004b000010260000413d000003ae0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000192b0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000019370000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000019430000c13d0000064b0000013d0000001d0200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c7000000160200002936b536b00000040f0000000003010019000000600330027000000dae0030019d00000dae033001970002000000010355000000010020019000001b030000613d00000e25043001980000001f0530018f0000001d02400029000019640000613d000000000601034f0000001d07000029000000006806043c0000000007870436000000000027004b000019600000c13d000000000005004b000019710000613d000000000141034f0000000304500210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001204350000001f0130003900000e25011001970000001d02100029000000000012004b00000000010000390000000101004039001c00000002001d00000dd10020009c000006870000213d0000000100100190000006870000c13d0000001c01000029000000400010043f00000dea0030009c0000005b0000213d000000200030008c0000005b0000413d0000001d01000029000000000101043300000dd10010009c0000005b0000213d0000001d053000290000001d011000290000001f02100039000000000052004b000000000300001900000deb0300804100000deb0220019700000deb04500197000000000642013f000000000042004b000000000200001900000deb0200404100000deb0060009c000000000203c019000000000002004b0000005b0000c13d000000003201043400000dd10020009c000006870000213d00000005012002100000003f0410003900000dd2044001970000001c0640002900000dd10060009c000006870000213d000000400060043f0000001c0600002900000000002604350000000006310019000000000056004b0000005b0000213d000000000063004b00001d0c0000813d0000001c01000029000000003203043400000db10020009c0000005b0000213d00000020011000390000000000210435000000000063004b000019a80000413d0000001c010000290000000002010433002600000001001d00000dd10020009c000006870000213d0000000001000415000000280110008a000800050010021800000005012002100000003f0310003900000dd20430019700001d100000013d0000000007000019000019c00000013d0000000107700039000000000037004b000003b80000813d0000000008150049000000400880008a00000000048404360000002002200039000000000802043300000000c9080434000001a006000039000000000b650436000001a00a50003900000000d909043400000000009a0435000001c00a500039000000000009004b000019d60000613d000000000e000019000000000fae00190000000006ed0019000000000606043300000000006f0435000000200ee0003900000000009e004b000019cf0000413d0000000006a90019000000000006043500000000060c043300000db10660019700000000006b04350000004006800039000000000606043300000db106600197000000400b50003900000000006b043500000060068000390000000006060433000000600b50003900000000006b043500000080068000390000000006060433000000800b50003900000000006b04350000001f0690003900000e25066001970000000006a600190000000009560049000000a00a500039000000a00b800039000000000b0b043300000000009a043500000000ba0b04340000000009a6043600000000000a004b000019fc0000613d000000000c00001900000000069c0019000000000dcb0019000000000d0d04330000000000d60435000000200cc000390000000000ac004b000019f50000413d00000000069a001900000000000604350000001f06a0003900000e25066001970000000006960019000000c0098000390000000009090433000000000a560049000000c00b5000390000000000ab043500000000ba0904340000000009a6043600000000000a004b00001a120000613d000000000c00001900000000069c0019000000000dcb0019000000000d0d04330000000000d60435000000200cc000390000000000ac004b00001a0b0000413d00000000069a001900000000000604350000001f06a0003900000e25066001970000000006960019000000e0098000390000000009090433000000000a560049000000e00b5000390000000000ab043500000000ba0904340000000009a6043600000000000a004b00001a280000613d000000000c00001900000000069c0019000000000dcb0019000000000d0d04330000000000d60435000000200cc000390000000000ac004b00001a210000413d00000000069a001900000000000604350000010006800039000000000606043300000db106600197000001000b50003900000000006b043500000120068000390000000006060433000001200b50003900000000006b043500000140068000390000000006060433000001400b50003900000000006b043500000160068000390000000006060433000001600b50003900000000006b04350000001f06a0003900000e250660019700000000069600190000000009560049000001800550003900000180088000390000000008080433000000000095043500000000090804330000000005960436000000000009004b000019bd0000613d000000000a0000190000002008800039000000000b08043300000000c60b043400000db1066001970000000006650436000000000c0c04330000000000c604350000004006b000390000000006060433000000400c50003900000000006c04350000006006b000390000000006060433000000600c50003900000000006c04350000008006b000390000000006060433000000800c50003900000000006c0435000000a006b000390000000006060433000000a00c50003900000000006c0435000000c006b000390000000006060433000000c00c50003900000000006c0435000000e006b000390000000006060433000000e00c50003900000000006c04350000010006b000390000000006060433000001000c50003900000000006c04350000012006b000390000000006060433000001200c50003900000000006c04350000014006b000390000000006060433000001400c50003900000000006c04350000016006b000390000000006060433000000000006004b0000000006000039000000010600c039000001600c50003900000000006c04350000018006b000390000000006060433000001800c50003900000000006c0435000001a006b00039000000000606043300000db106600197000001a00c50003900000000006c0435000001c006b000390000000006060433000001c00c50003900000000006c0435000001e006b000390000000006060433000001e00c50003900000000006c04350000020006b000390000000006060433000002000b50003900000000006b04350000022005500039000000010aa0003900000000009a004b00001a480000413d000019bd0000013d0000001c01000029000000a00710003900000df90800004100000000090000190000000006000019001800000005001d001700000007001d00001a9f0000013d0000000109900039000000000059004b000005e10000813d0000001d010000290000000001010433000000000091004b0000268a0000a13d0000000501900210000000000a71001900000000020a0433000000400b00043d00000000008b0435000000000100041400000db102200197000000040020008c00001ab10000c13d0000000003000031000000200030008c0000002004000039000000000403401900001ae60000013d001b0000000a001d001c00000009001d001900000006001d00000dae00b0009c00000dae0300004100000000030b4019000000400330021000000dae0010009c00000dae01008041000000c001100210000000000131019f00000db3011001c7001a0000000b001d36b536b00000040f0000001a0b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b001900001acf0000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b00001acb0000c13d0000001f0740019000001adc0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001c090000290000001b0a00002900001c230000613d00000018050000290000001906000029000000170700002900000df9080000410000001f01400039000000600210018f0000000001b20019000000000021004b0000000002000039000000010200403900000dd10010009c000006870000213d0000000100200190000006870000c13d000000400010043f000000200030008c0000005b0000413d00000000010b0433000000000001004b00001a9c0000613d0000001d010000290000000001010433000000000091004b0000268a0000a13d000000000061004b0000268a0000a13d0000000501600210000000000171001900000000020a043300000db1022001970000000000210435000000010660003900001a9c0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b0a0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b160000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b220000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b2e0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b3a0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b460000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b520000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b5e0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b6a0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b760000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b820000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b8e0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b9a0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001ba60000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001bb20000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001bbe0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001bca0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001bd60000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001be20000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001bee0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001bfa0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001c060000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001c120000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001c1e0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001c2a0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001c360000c13d0000064b0000013d00130db10020019b001b00000000001d001a00000000001d000000400100043d001c00000001001d00000dfd0010009c000006870000213d0000001c020000290000004001200039000000400010043f0000000001020436001800000001001d000000000001043500000000010904330000001b02000029000000000021004b0000268a0000a13d0000000501200210001600200010003d0000001605900029000000000105043300000db1011001970000001c0400002900000000001404350000000001090433000000000021004b0000268a0000a13d0000000002050433000000400a00043d00000e1c0100004100000000001a0435000000000100041400000db102200197000000040020008c001700000005001d00001c630000c13d000000200030008c0000002004000039000000000403401900001c900000013d00000dae00a0009c00000dae0300004100000000030a4019000000400330021000000dae0010009c00000dae01008041000000c001100210000000000131019f00000db3011001c7001d0000000a001d36b536b00000040f0000001d0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900001c7e0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00001c7a0000c13d0000001f0740019000001c8b0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000190900002900001e320000613d0000001f01400039000000600110018f00000000060a00190000000005a10019000000000015004b00000000020000390000000102004039001d00000005001d00000dd10050009c000006870000213d0000000100200190000006870000c13d0000001d02000029000000400020043f000000200040008c0000005b0000413d00000000020904330000001b0020006c00000017020000290000268a0000a13d0000000004060433001500000004001d000000000202043300000e1d040000410000001d050000290000000000450435000000040450003900000db102200197000000000024043500000000040004140000001302000029000000040020008c00001cb60000c13d000000000115001900000dd10010009c000006870000213d000000400010043f00001cea0000013d00000dae0040009c00000dae04008041000000c00140021000000dae0050009c00000dae0300004100000000030540190000004003300210000000000113019f00000dd9011001c736b536b00000040f0000001d0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900001cd00000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00001ccc0000c13d0000001f0740019000001cdd0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000190900002900001e3e0000613d0000001f01400039000000600110018f0000000001a1001900000dd10010009c000006870000213d000000400010043f000000200030008c0000005b0000413d0000001d010000290000000002010433000000150400002900000000014200a9000000000004004b0000001b0500002900001cf40000613d00000000044100d9000000000024004b000026900000c13d00000e090110012a00000018020000290000000000120435000000140100002900000000010104330000000002010433000000000052004b0000268a0000a13d00000016021000290000001c0400002900000000004204350000000001010433000000000051004b0000268a0000a13d000000180100002900000000010104330000001a0010002a000026900000413d001a001a0010002d001b00010050003d00000000010904330000001b0010006b00001c3e0000413d00000f520000013d0026001c0000002d0000000003000415000000250330008a0008000500300218000000400500043d0000000003450019001600000005001d000000000053004b0000000004000039000000010400403900000dd10030009c000006870000213d0000000100400190000006870000c13d000000400030043f00000016030000290000000003230436000000000002004b00001d320000613d00000000020000190000006006000039000000400400043d00000dd30040009c000006870000213d0000008005400039000000400050043f0000006005400039000000000065043500000040054000390000000000050435000000200540003900000000000504350000000000040435000000000523001900000000004504350000002002200039000000000012004b00001d210000413d00000008010000290000000501100270000000160100002f002700000000003d0000001c010000290000000001010433000000000001004b00001e560000c13d000000400100043d00000020020000390000000002210436000000160300002900000000030304330000000000320435000000400410003900000005023002100000000002420019000000000003004b000002390000613d00000080050000390000000006000019000000160c00002900001d4c0000013d0000000106600039000000000036004b000002390000813d0000000007120049000000400770008a0000000004740436000000200cc0003900000000070c0433000000009807043400000db1088001970000000008820436000000000909043300000db109900197000000000098043500000040087000390000000008080433000000400920003900000000008904350000006007700039000000000707043300000060082000390000000000580435000000800920003900000000080704330000000000890435000000a002200039000000000008004b00001d490000613d00000000090000190000002007700039000000000a07043300000000ba0a043400000db10aa00197000000000aa20436000000000b0b04330000000000ba043500000040022000390000000109900039000000000089004b00001d660000413d00001d490000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001d790000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001d850000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001d910000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001d9d0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001da90000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001db50000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001dc10000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001dcd0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001dd90000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001de50000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001df10000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001dfd0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e090000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e150000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e210000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e2d0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e390000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e450000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e510000c13d0000064b0000013d001d00000000001d000000400100043d001a00000001001d00000dd30010009c000006870000213d0000001a020000290000008001200039000000400010043f00000060032000390000006001000039001400000003001d0000000000130435000000400120003900000000000104350000002001200039001500000001001d00000000000104350000000000020435002400000002001d0000001c0100002900000000010104330000001d0010006c0000268a0000a13d0000001d0300002900000005013002100000001c0200002900000000011200190000002001100039001900000001001d000000000101043300000db1011001970000001a0400002900000000001404350000000001020433000000000031004b0000268a0000a13d000000190100002900000000020104330000002a01000029001700000001001d000000000301043300000dfb01000041001b00000003001d0000000000130435001800290000002d000000000100041400000db102200197000000040020008c00001e8c0000c13d0000000003000031000000200030008c0000002004000039000000000403401900001eba0000013d0000001b0300002900000dae0030009c00000dae030080410000004003300210000000180400002900000dae0040009c00000dae040080410000006004400210000000000334019f00000dae0010009c00000dae01008041000000c001100210000000000113019f36b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001b0560002900001ea90000613d000000000701034f0000001b08000029000000007907043c0000000008980436000000000058004b00001ea50000c13d0000001f0740019000001eb60000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027fa0000613d0000001f01400039000000600110018f0000001b02100029000000000012004b0000000004000039000000010400403900000dd10020009c000006870000213d0000000100400190000006870000c13d000000400020043f000000200030008c0000005b0000413d0000001b02000029000000000202043300000db10020009c0000005b0000213d0000002c0220017f000000150400002900000000002404350000001c0200002900000000020204330000001d0020006c0000268a0000a13d000000190200002900000000020204330000001704000029000000000504043300000dfc040000410000000000450435001b00000005001d000000180450002900000db1050000410000002d0550017f001500000005001d0000000000540435000000000400041400000db102200197000000040020008c00001f130000613d0000001b0100002900000dae0010009c00000dae0100804100000040011002100000001803000029000000200330003900000dae0030009c00000dae030080410000006003300210000000000131019f00000dae0040009c00000dae04008041000000c003400210000000000113019f36b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001b0560002900001f000000613d000000000701034f0000001b08000029000000007907043c0000000008980436000000000058004b00001efc0000c13d0000001f0740019000001f0d0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000028060000613d0000001f01400039000000600110018f0000001b02100029000000000012004b0000000001000039000000010100403900000dd10020009c000006870000213d0000000100100190000006870000c13d000000400020043f000000200030008c0000005b0000413d00000017020000290000001a012000290000001b02000029000000000202043300000000002104350000001c0100002900000000010104330000001d0010006c0000268a0000a13d0000002b01000029001b00000001001d0000000012010434000d00000001001d00000dd10020009c000006870000213d00000005012002100000003f0310003900000dd203300197000000400400043d0000000003340019000f00000004001d000000000043004b0000000004000039000000010400403900000dd10030009c000006870000213d0000000100400190000006870000c13d00000019040000290000000004040433001c00000004001d000000400030043f0000000f030000290000000003230436000e00000003001d000000000002004b00001f510000613d0000000002000019000000400300043d00000dfd0030009c000006870000213d0000004004300039000000400040043f0000002004300039000000000004043500000000000304350000000e0420002900000000003404350000002002200039000000000012004b00001f440000413d00000dcf0100004100000000001004430000000001000412000000040010044300000020010000390000002400100443000000000100041400000dae0010009c00000dae01008041000000c00110021000000df8011001c7000080050200003936b536b00000040f0000000100200190000026890000613d0000001b020000290000000002020433000000000002004b0000266e0000613d0000001c02000029001c0db10020019b000000000101043b000900000001001d001d00000000001d000000400100043d001900000001001d00000dfe0010009c000006870000213d00000019020000290000006001200039000000400010043f0000004001200039001100000001001d00000000000104350000000001020436001300000001001d0000000000010435000000400100043d001600000001001d00000dfe0010009c000006870000213d00000016020000290000006001200039000000400010043f0000004001200039001000000001001d00000000000104350000000001020436001200000001001d00000000000104350000001b010000290000000001010433000000090000006b0000001d02000029001400050020021800001fa00000613d0000001d0010006c0000268a0000a13d00000014020000290000000d01200029001700000001001d0000000001010433000000400300043d00000dff020000410000000002230436001800000002001d00000db101100197001a00000003001d0000000402300039000000000012043500000000010004140000001c02000029000000040020008c00001fb70000c13d0000000003000031000000600030008c0000006004000039000000000403401900001fe20000013d0000001d0010006c0000268a0000a13d00000014020000290000000d01200029001700000001001d0000000001010433000000400300043d00000e02020000410000000002230436001800000002001d00000db101100197001a00000003001d0000000402300039000000000012043500000000010004140000001c02000029000000040020008c000020520000c13d0000000003000031000000600030008c000000600400003900000000040340190000207d0000013d0000001a0200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000dd9011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000600030008c0000006004000039000000000403401900000060064001900000001a0560002900001fd10000613d000000000701034f0000001a08000029000000007907043c0000000008980436000000000058004b00001fcd0000c13d0000001f0740019000001fde0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027820000613d0000001f01400039000000e00110018f0000001a02100029000000000012004b0000000004000039000000010400403900000dd10020009c000006870000213d0000000100400190000006870000c13d000000400020043f000000600030008c0000005b0000413d0000001a02000029000000000202043300000e000020009c0000005b0000213d000000180400002900000000040404330000001a05000029000000400550003900000000050504330000001106000029000000000056043500000013050000290000000000450435000000190400002900000000002404350000001b0200002900000000020204330000001d0020006c0000268a0000a13d00000017020000290000000002020433000000400500043d00000e01040000410000000004450436001800000004001d00000db102200197001a00000005001d0000000404500039000000000024043500000000020004140000001c04000029000000040040008c0000203d0000613d0000001a0100002900000dae0010009c00000dae01008041000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000600030008c0000006004000039000000000403401900000060064001900000001a056000290000202a0000613d000000000701034f0000001a08000029000000007907043c0000000008980436000000000058004b000020260000c13d0000001f07400190000020370000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000278e0000613d0000001f01400039000000e00110018f0000001a02100029000000000012004b0000000001000039000000010100403900000dd10020009c000006870000213d0000000100100190000006870000c13d000000400020043f000000600030008c0000005b0000413d0000001a01000029000000000101043300000e000010009c0000005b0000213d0000001a020000290000004002200039000000000402043300000018020000290000000002020433000020f40000013d0000001a0200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000dd9011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000600030008c0000006004000039000000000403401900000060064001900000001a056000290000206c0000613d000000000701034f0000001a08000029000000007907043c0000000008980436000000000058004b000020680000c13d0000001f07400190000020790000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000279a0000613d0000001f01400039000000e00110018f0000001a02100029000000000012004b0000000004000039000000010400403900000dd10020009c000006870000213d0000000100400190000006870000c13d000000400020043f000000600030008c0000005b0000413d0000001a02000029000000000202043300000e000020009c0000005b0000213d0000001804000029000000000404043300000dae0040009c0000005b0000213d0000001a050000290000004005500039000000000505043300000dae0050009c0000005b0000213d0000001106000029000000000056043500000013050000290000000000450435000000190400002900000000002404350000001b0200002900000000020204330000001d0020006c0000268a0000a13d00000017020000290000000002020433000000400500043d00000e03040000410000000004450436001800000004001d00000db102200197001a00000005001d0000000404500039000000000024043500000000020004140000001c04000029000000040040008c000020dc0000613d0000001a0100002900000dae0010009c00000dae01008041000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000600030008c0000006004000039000000000403401900000060064001900000001a05600029000020c90000613d000000000701034f0000001a08000029000000007907043c0000000008980436000000000058004b000020c50000c13d0000001f07400190000020d60000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027a60000613d0000001f01400039000000e00110018f0000001a02100029000000000012004b0000000001000039000000010100403900000dd10020009c000006870000213d0000000100100190000006870000c13d000000400020043f000000600030008c0000005b0000413d0000001a01000029000000000101043300000e000010009c0000005b0000213d0000001802000029000000000202043300000dae0020009c0000005b0000213d0000001a040000290000004004400039000000000404043300000dae0040009c0000005b0000213d0000001005000029000000000045043500000012040000290000000000240435000000160200002900000000001204350000001b0100002900000000010104330000001d0010006c0000268a0000a13d00000014020000290000000d01200029001a00000001001d0000000002010433000000400400043d00000e0401000041001700000004001d0000000000140435000000000100041400000db102200197000000040020008c0000002004000039000021350000613d000000170300002900000dae0030009c00000dae03008041000000400330021000000dae0010009c00000dae01008041000000c001100210000000000131019f00000db3011001c736b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001705600029000021240000613d000000000701034f0000001708000029000000007907043c0000000008980436000000000058004b000021200000c13d0000001f07400190000021310000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000272e0000613d0000001f01400039000000600110018f0000001704100029000000000014004b00000000020000390000000102004039001800000004001d00000dd10040009c000006870000213d0000000100200190000006870000c13d0000001802000029000000400020043f000000200030008c0000005b0000413d000000180200002900000dde0020009c000006870000213d0000001702000029000000000202043300000018050000290000002004500039000000400040043f00000000002504350000001b0200002900000000020204330000001d0020006c0000268a0000a13d0000001a020000290000000002020433000000400500043d00000e0504000041000000000045043500000db104200197001700000005001d0000000402500039000c00000004001d000000000042043500000000020004140000001c04000029000000040040008c0000218c0000613d000000170100002900000dae0010009c00000dae01008041000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001705600029000021790000613d000000000701034f0000001708000029000000007907043c0000000008980436000000000058004b000021750000c13d0000001f07400190000021860000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000273a0000613d0000001f01400039000000600110018f0000001702100029000000000012004b0000000001000039000000010100403900000dd10020009c000006870000213d0000000100100190000006870000c13d000000400020043f000000200030008c0000005b0000413d00000017010000290000000001010433001700000001001d00000dcf0100004100000000001004430000000001000412000000040010044300000040010000390000002400100443000000000100041400000dae0010009c00000dae01008041000000c00110021000000df8011001c7000080050200003936b536b00000040f0000000100200190000026890000613d000000000101043b000000010010008c000021b20000613d000000020010008c000027150000c13d00000e080100004100000000001004430000000001000414000021b50000013d00000e06010000410000000000100443000000000100041400000dae0010009c00000dae01008041000000c00110021000000e07011001c70000800b0200003936b536b00000040f0000000100200190000026890000613d00000011020000290000000004020433000000000101043b000000000041004b00000000020000390000000102002039000000000004004b0000000003000039000000010300c0390000000000230170000000000401601900000013010000290000000001010433001100000004001d000a000000140053000026900000413d0000226a0000613d000000170000006b000022670000613d000000400200043d00000de501000041000b00000002001d000000000012043500000000010004140000000c02000029000000040020008c000021dd0000c13d0000000003000031000000200030008c00000020040000390000000004034019000022080000013d0000000b0200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c70000000c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000000b05600029000021f70000613d000000000701034f0000000b08000029000000007907043c0000000008980436000000000058004b000021f30000c13d0000001f07400190000022040000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027ca0000613d0000001f01400039000000600210018f0000000b01200029000000000021004b0000000002000039000000010200403900000dd10010009c000006870000213d0000000100200190000006870000c13d000000400010043f000000200030008c0000005b0000413d0000000b02000029000000000302043300000e09023000d1000000000003004b0000221d0000613d00000000033200d900000e090030009c000026900000c13d00000018030000290000000003030433000000000003004b0000270f0000613d0000000a0500002900000017045000b900000000055400d9000000170050006c000026900000c13d000000000023004b0000222c0000a13d00000dde0010009c00000000020000190000223c0000a13d000006870000013d00000dde0010009c000006870000213d0000002005100039000000400050043f000000000001043500000e0a054000d1000000000004004b000022370000613d00000000014500d900000e0a0010009c000026900000c13d000000400100043d00000dde0010009c000006870000213d00000000023200d900000000022500d90000002003100039000000400030043f0000000000210435000000400200043d00000dde0020009c000006870000213d000000190300002900000000030304330000002004200039000000400040043f00000e00033001970000000000320435000000400300043d00000dde0030009c000006870000213d0000002004300039000000400040043f000000000003043500000000020204330000000001010433000000000021001a000026900000413d000000400300043d00000dde0030009c000006870000213d00000000022100190000002001300039000000400010043f0000000000230435000000400100043d00000dfd0010009c000006870000213d0000004003100039000000400030043f000000200310003900000e0b0400004100000000004304350000001303000039000000000031043500000e0c0020009c0000271b0000813d000000190100002900000000002104350000001301000029000000110200002900000000002104350000001b0100002900000000010104330000001d0010006c0000268a0000a13d0000001a010000290000000001010433000000400300043d00000e0e02000041000000000023043500000db102100197001700000003001d0000000401300039001100000002001d000000000021043500000000010004140000001c02000029000000040020008c000022810000c13d0000000003000031000000200030008c00000020040000390000000004034019000022ac0000013d000000170200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000dd9011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000017056000290000229b0000613d000000000701034f0000001708000029000000007907043c0000000008980436000000000058004b000022970000c13d0000001f07400190000022a80000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027460000613d0000001f01400039000000600210018f0000001701200029000000000021004b0000000002000039000000010200403900000dd10010009c000006870000213d0000000100200190000006870000c13d000000400010043f000000200030008c0000005b0000413d00000017010000290000000001010433001700000001001d00000dcf0100004100000000001004430000000001000412000000040010044300000040010000390000002400100443000000000100041400000dae0010009c00000dae01008041000000c00110021000000df8011001c7000080050200003936b536b00000040f0000000100200190000026890000613d000000000101043b000000010010008c000022d40000613d000000020010008c000027150000c13d00000e080100004100000000001004430000000001000414000022d70000013d00000e06010000410000000000100443000000000100041400000dae0010009c00000dae01008041000000c00110021000000e07011001c70000800b0200003936b536b00000040f0000000100200190000026890000613d00000010020000290000000004020433000000000101043b000000000041004b00000000020000390000000102002039000000000004004b0000000003000039000000010300c0390000000000230170000000000401601900000012010000290000000001010433001300000004001d000c000000140053000026900000413d000023810000613d000000170000006b0000237e0000613d000000400200043d00000ddf01000041001000000002001d000000000012043500000000010004140000001102000029000000040020008c000022ff0000c13d0000000003000031000000200030008c000000200400003900000000040340190000232a0000013d000000100200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c7000000110200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001005600029000023190000613d000000000701034f0000001008000029000000007907043c0000000008980436000000000058004b000023150000c13d0000001f07400190000023260000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027d60000613d0000001f01400039000000600210018f0000001001200029000000000021004b0000000002000039000000010200403900000dd10010009c000006870000213d0000000100200190000006870000c13d000000400010043f000000200030008c0000005b0000413d0000000c0200002900000017032000b900000000022300d9000000170020006c000026900000c13d00000010020000290000000002020433000000000002004b000023500000613d00000dde0010009c000006870000213d0000002004100039000000400040043f000000000001043500000e0a043000d1000000000003004b0000234b0000613d00000000013400d900000e0a0010009c000026900000c13d000000400100043d00000dde0010009c000006870000213d00000000022400d9000023530000013d00000dde0010009c0000000002000019000006870000213d0000002003100039000000400030043f0000000000210435000000400200043d00000dde0020009c000006870000213d000000160300002900000000030304330000002004200039000000400040043f00000e00033001970000000000320435000000400300043d00000dde0030009c000006870000213d0000002004300039000000400040043f000000000003043500000000020204330000000001010433000000000021001a000026900000413d000000400300043d00000dde0030009c000006870000213d00000000022100190000002001300039000000400010043f0000000000230435000000400100043d00000dfd0010009c000006870000213d0000004003100039000000400030043f000000200310003900000e0b0400004100000000004304350000001303000039000000000031043500000e0c0020009c0000271b0000813d000000160100002900000000002104350000001201000029000000130200002900000000002104350000001b0100002900000000010104330000001d0010006c0000268a0000a13d000000400100043d001300000001001d00000dde0010009c000006870000213d0000001a01000029000000000101043300000db1031001970000001901000029000000000101043300000013040000290000002002400039000000400020043f00000e00011001970000000000140435000000400400043d00000024014000390000001502000029000000000021043500000e0f010000410000000000140435001700000004001d0000000401400039001200000003001d000000000031043500000000010004140000001c02000029000000040020008c000023a60000c13d0000000003000031000000200030008c00000020040000390000000004034019000023d10000013d000000170200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000ddd011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001705600029000023c00000613d000000000701034f0000001708000029000000007907043c0000000008980436000000000058004b000023bc0000c13d0000001f07400190000023cd0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027520000613d0000001f01400039000000600110018f0000001704100029000000000014004b00000000020000390000000102004039001900000004001d00000dd10040009c000006870000213d0000000100200190000006870000c13d0000001902000029000000400020043f000000200030008c0000005b0000413d000000190200002900000dde0020009c000006870000213d0000001702000029000000000202043300000019050000290000002004500039000000400040043f0000000000250435000000400400043d001700000004001d000000000002004b0000247b0000c13d00000013020000290000000002020433001000000002001d00000e10020000410000001704000029000000000024043500000000020004140000001c04000029000000040040008c000024240000613d000000170100002900000dae0010009c00000dae01008041000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001705600029000024110000613d000000000701034f0000001708000029000000007907043c0000000008980436000000000058004b0000240d0000c13d0000001f074001900000241e0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027b20000613d0000001f01400039000000600110018f0000001704100029000000000014004b00000000020000390000000102004039001100000004001d00000dd10040009c000006870000213d0000000100200190000006870000c13d0000001102000029000000400020043f000000200030008c0000005b0000413d0000001702000029000000000202043300000e000020009c0000005b0000213d000000100020006b000024390000813d00000011010000290000247a0000013d00000e10020000410000001104000029000000000024043500000000020004140000001c04000029000000040040008c0000246d0000613d000000110100002900000dae0010009c00000dae01008041000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000011056000290000245a0000613d000000000701034f0000001108000029000000007907043c0000000008980436000000000058004b000024560000c13d0000001f07400190000024670000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027e20000613d0000001f01400039000000600110018f000000110110002900000dd10010009c000006870000213d000000400010043f000000200030008c0000005b0000413d0000001101000029000000000101043300000e000010009c0000005b0000213d00000019020000290000000000120435000000400100043d001700000001001d000000170100002900000dde0010009c000006870000213d00000017020000290000002001200039000000400010043f00000000000204350000001901000029000000000101043300000013020000290000000002020433000000000112004b000026900000413d000000400200043d001300000002001d00000dde0020009c000006870000213d00000013040000290000002002400039000000400020043f0000000000140435000000400200043d00000e11010000410000000000120435001700000002001d00000004012000390000001502000029000000000021043500000000010004140000001202000029000000040020008c0000002004000039000024c70000613d000000170200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000dd9011001c7000000120200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001705600029000024b60000613d000000000701034f0000001708000029000000007907043c0000000008980436000000000058004b000024b20000c13d0000001f07400190000024c30000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000275e0000613d0000001f01400039000000600110018f0000001702100029000000000012004b00000000010000390000000101004039001900000002001d00000dd10020009c000006870000213d0000000100100190000006870000c13d0000001901000029000000400010043f000000200030008c0000005b0000413d0000001701000029000000000201043300000e09012000d1000000000002004b000024de0000613d00000000022100d900000e090020009c000026900000c13d00000018020000290000000002020433000000000002004b0000270f0000613d0000001304000029000000000404043300000000052100d900130000005400ad000000000012004b000024eb0000213d00000013015000f9000000000041004b000026900000c13d0000001b0100002900000000010104330000001d0010006c0000268a0000a13d000000190100002900000dde0010009c000006870000213d0000001a01000029000000000101043300000db1051001970000001601000029000000000101043300000019040000290000002002400039000000400020043f00000e00011001970000000000140435000000400400043d00000024014000390000001502000029000000000021043500000e12010000410000000000140435001700000004001d0000000401400039001600000005001d000000000051043500000000010004140000001c02000029000000040020008c0000002004000039000025360000613d000000170200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000ddd011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001705600029000025250000613d000000000701034f0000001708000029000000007907043c0000000008980436000000000058004b000025210000c13d0000001f07400190000025320000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000276a0000613d0000001f01400039000000600110018f0000001704100029000000000014004b00000000020000390000000102004039001800000004001d00000dd10040009c000006870000213d0000000100200190000006870000c13d0000001802000029000000400020043f000000200030008c0000005b0000413d000000180200002900000dde0020009c000006870000213d0000001702000029000000000202043300000018050000290000002004500039000000400040043f0000000000250435000000400400043d001700000004001d000000000002004b000025e00000c13d00000019020000290000000002020433001100000002001d00000e10020000410000001704000029000000000024043500000000020004140000001c04000029000000040040008c000025890000613d000000170100002900000dae0010009c00000dae01008041000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001705600029000025760000613d000000000701034f0000001708000029000000007907043c0000000008980436000000000058004b000025720000c13d0000001f07400190000025830000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027be0000613d0000001f01400039000000600110018f0000001704100029000000000014004b00000000020000390000000102004039001200000004001d00000dd10040009c000006870000213d0000000100200190000006870000c13d0000001202000029000000400020043f000000200030008c0000005b0000413d0000001702000029000000000202043300000e000020009c0000005b0000213d000000110020006b0000259e0000813d0000001201000029000025df0000013d00000e10020000410000001204000029000000000024043500000000020004140000001c04000029000000040040008c000025d20000613d000000120100002900000dae0010009c00000dae01008041000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001205600029000025bf0000613d000000000701034f0000001208000029000000007907043c0000000008980436000000000058004b000025bb0000c13d0000001f07400190000025cc0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027ee0000613d0000001f01400039000000600110018f000000120110002900000dd10010009c000006870000213d000000400010043f000000200030008c0000005b0000413d0000001201000029000000000101043300000e000010009c0000005b0000213d00000018020000290000000000120435000000400100043d001700000001001d000000170100002900000dde0010009c000006870000213d00000017020000290000002001200039000000400010043f00000000000204350000001801000029000000000101043300000019020000290000000002020433000000000112004b000026900000413d000000400200043d001800000002001d00000dde0020009c000006870000213d00000018040000290000002002400039000000400020043f0000000000140435000000400200043d00000df2010000410000000000120435001900000002001d00000004012000390000001502000029000000000021043500000000010004140000001602000029000000040020008c00000020040000390000262c0000613d000000190200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000dd9011001c7000000160200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000019056000290000261b0000613d000000000701034f0000001908000029000000007907043c0000000008980436000000000058004b000026170000c13d0000001f07400190000026280000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027760000613d0000001f01400039000000600210018f0000001901200029000000000021004b0000000002000039000000010200403900000dd10010009c000006870000213d0000000100200190000006870000c13d000000400010043f000000200030008c0000005b0000413d000000180200002900000000030204330000001902000029000000000402043300000000024300a9000000000004004b000026430000613d00000000044200d9000000000034004b000026900000c13d00000dfd0010009c000006870000213d0000004003100039000000400030043f000000000301043600000000000304350000001b0400002900000000040404330000001d0040006c0000268a0000a13d000000130400002900000e0a0440012a00000e0a0220012a0000001a05000029000000000505043300000db1055001970000000000510435000000000242001900000000002304350000000f0200002900000000020204330000001d0020006c0000268a0000a13d00000014030000290000000e0230002900000000001204350000000f0100002900000000010104330000001d0010006c0000268a0000a13d0000001d02000029001d00010020003d0000001b0100002900000000010104330000001d0010006b00001f690000413d001d00270000002d0000002401000029001a00000001001d001400600010003d0000000801000029000000050110027000160000000100350000000f0100002900000014020000290000000000120435000000160100002900000000010104330000001d0010006c0000268a0000a13d0000001d0300002900000005013002100000001602000029000000000112001900000020011000390000001a0400002900000000004104350000000001020433000000000031004b0000268a0000a13d0000001d02000029002700010020003d00000001022000390000002601000029001c00000001001d0000000001010433001d00000002001d000000000012004b00001e570000413d00001d3a0000013d000000000001042f00000e1301000041000000000010043f0000003201000039000000040010043f00000dd901000041000036b70001043000000e1301000041000000000010043f0000001101000039000000040010043f00000dd901000041000036b700010430000000000301034f0000001f0580018f000000000908001900000db006800198000000400200043d0000000004620019000026b10000613d000000000703034f0000000008020019000000007107043c0000000008180436000000000048004b0000269f0000c13d000026b10000013d000000000301034f0000001f0580018f000000000908001900000db006800198000000400200043d0000000004620019000026b10000613d000000000703034f0000000008020019000000007107043c0000000008180436000000000048004b000026ad0000c13d000000000005004b000026be0000613d000000000163034f0000000303500210000000000504043300000000053501cf000000000535022f000000000101043b0000010003300089000000000131022f00000000013101cf000000000151019f00000000001404350000006001900210000006590000013d0000001f0590018f000000000a09001900000db006900198000000400200043d0000000004620019000026cc0000613d0000001c0700035f0000000008020019000000007107043c0000000008180436000000000048004b000026c80000c13d000000000005004b000005460000613d0000001c0160035f0000000303500210000000000504043300000000053501cf000000000535022f000000000101043b0000010003300089000000000131022f00000000013101cf000000000151019f000005450000013d0000001d010000290000001f0510018f00000db006100198000000400200043d0000000004620019000026ff0000613d0000001c0700035f0000000008020019000000007107043c0000000008180436000000000048004b000026e10000c13d000026ff0000013d0000001d010000290000001f0510018f00000db006100198000000400200043d0000000004620019000026ff0000613d0000001c0700035f0000000008020019000000007107043c0000000008180436000000000048004b000026ee0000c13d000026ff0000013d0000001d010000290000001f0510018f00000db006100198000000400200043d0000000004620019000026ff0000613d0000001c0700035f0000000008020019000000007107043c0000000008180436000000000048004b000026fb0000c13d000000000005004b0000270c0000613d0000001c0160035f0000000303500210000000000504043300000000053501cf000000000535022f000000000101043b0000010003300089000000000131022f00000000013101cf000000000151019f00000000001404350000001d010000290000006001100210000006590000013d00000e1301000041000000000010043f0000001201000039000000040010043f00000dd901000041000036b70001043000000e1301000041000000000010043f0000005101000039000000040010043f00000dd901000041000036b700010430000000400400043d001d00000004001d00000e0d020000410000000000240435000000040240003900000020030000390000000000320435000000240240003936b528120000040f0000001d02000029000000000121004900000dae0010009c00000dae0100804100000dae0020009c00000dae0200804100000060011002100000004002200210000000000121019f000036b7000104300000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027350000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027410000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000274d0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027590000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027650000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027710000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000277d0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027890000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027950000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027a10000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027ad0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027b90000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027c50000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027d10000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027dd0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027e90000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027f50000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000028010000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000280d0000c13d0000064b0000013d00000000430104340000000001320436000000000003004b0000281e0000613d000000000200001900000000051200190000000006240019000000000606043300000000006504350000002002200039000000000032004b000028170000413d000000000213001900000000000204350000001f0230003900000e25022001970000000001210019000000000001042d000000004301043400000db103300197000000000332043600000000040404330000000000430435000000400310003900000000030304330000004004200039000000000034043500000060031000390000000003030433000000600420003900000000003404350000008003100039000000000303043300000080042000390000000000340435000000a0031000390000000003030433000000a0042000390000000000340435000000c0031000390000000003030433000000c0042000390000000000340435000000e0031000390000000003030433000000e004200039000000000034043500000100031000390000000003030433000001000420003900000000003404350000012003100039000000000303043300000120042000390000000000340435000001400310003900000000030304330000014004200039000000000034043500000160031000390000000003030433000000000003004b0000000003000039000000010300c039000001600420003900000000003404350000018003100039000000000303043300000180042000390000000000340435000001a003100039000000000303043300000db103300197000001a0042000390000000000340435000001c0031000390000000003030433000001c0042000390000000000340435000001e0031000390000000003030433000001e00420003900000000003404350000020002200039000002000110003900000000010104330000000000120435000000000001042d000000200300003900000000033104360000000064020434000001a0050000390000000000530435000001c00510003900000000740404340000000000450435000001e005100039000000000004004b0000287d0000613d00000000080000190000000009580019000000000a870019000000000a0a04330000000000a904350000002008800039000000000048004b000028760000413d00000000075400190000000000070435000000000606043300000db106600197000000400710003900000000006704350000004006200039000000000606043300000db10660019700000060071000390000000000670435000000600620003900000000060604330000008007100039000000000067043500000080062000390000000006060433000000a00710003900000000006704350000001f0640003900000e250660019700000000055600190000000006350049000000c007100039000000a0082000390000000008080433000000000067043500000000760804340000000005650436000000000006004b000028a40000613d00000000080000190000000009580019000000000a870019000000000a0a04330000000000a904350000002008800039000000000068004b0000289d0000413d000000000756001900000000000704350000001f0660003900000e250660019700000000055600190000000006350049000000c0072000390000000007070433000000e008100039000000000068043500000000760704340000000005650436000000000006004b000028ba0000613d00000000080000190000000009580019000000000a870019000000000a0a04330000000000a904350000002008800039000000000068004b000028b30000413d000000000756001900000000000704350000001f0660003900000e250660019700000000055600190000000006350049000000e00720003900000000070704330000010008100039000000000068043500000000760704340000000005650436000000000006004b000028d00000613d00000000080000190000000009580019000000000a870019000000000a0a04330000000000a904350000002008800039000000000068004b000028c90000413d000000000756001900000000000704350000010007200039000000000707043300000db107700197000001200810003900000000007804350000012007200039000000000707043300000140081000390000000000780435000001400720003900000000070704330000016008100039000000000078043500000160072000390000000007070433000001800810003900000000007804350000001f0660003900000e250460019700000000045400190000000003340049000001a00110003900000180022000390000000002020433000000000031043500000000030204330000000001340436000000000003004b0000293b0000613d000000000400001900000020022000390000000005020433000000007605043400000db106600197000000000661043600000000070704330000000000760435000000400650003900000000060604330000004007100039000000000067043500000060065000390000000006060433000000600710003900000000006704350000008006500039000000000606043300000080071000390000000000670435000000a0065000390000000006060433000000a0071000390000000000670435000000c0065000390000000006060433000000c0071000390000000000670435000000e0065000390000000006060433000000e007100039000000000067043500000100065000390000000006060433000001000710003900000000006704350000012006500039000000000606043300000120071000390000000000670435000001400650003900000000060604330000014007100039000000000067043500000160065000390000000006060433000000000006004b0000000006000039000000010600c039000001600710003900000000006704350000018006500039000000000606043300000180071000390000000000670435000001a006500039000000000606043300000db106600197000001a0071000390000000000670435000001c0065000390000000006060433000001c0071000390000000000670435000001e0065000390000000006060433000001e0071000390000000000670435000002000550003900000000050504330000020006100039000000000056043500000220011000390000000104400039000000000034004b000028f00000413d000000000001042d000000003101043400000db101100197000000000112043600000000020304330000000000210435000000000001042d000000004301043400000db103300197000000000332043600000000040404330000000000430435000000400310003900000000030304330000004004200039000000000034043500000060031000390000000003030433000000600420003900000000003404350000008003100039000000000303043300000080042000390000000000340435000000a002200039000000a00110003900000000010104330000000000120435000000000001042d000d000000000002000600000002001d000400000001001d000000400100043d00000e260010009c00002d0d0000813d000001a002100039000000400020043f000001800210003900000060090000390000000000920435000000e0021000390000000000920435000000c0021000390000000000920435000000a0021000390000000000920435000000000291043600000160031000390000000000030435000001400310003900000000000304350000012003100039000000000003043500000100031000390000000000030435000000800310003900000000000304350000006003100039000000000003043500000040011000390000000000010435000000000002043500000006010000290000004001100039000500000001001d0000000002010433000000400a00043d00000df60100004100000000001a0435000000000100041400000db102200197000000040020008c000d00000002001d000029880000c13d000000020100036700000000030000310000299c0000013d00000dae00a0009c000c0000000a001d00000dae0300004100000000030a4019000000400330021000000dae0010009c00000dae01008041000000c001100210000000000131019f00000db3011001c736b536b00000040f0000000003010019000000600330027000000dae0030019d00000dae033001970002000000010355000000010020019000002d340000613d00000060090000390000000c0a00002900000e25043001980000001f0530018f00000000024a0019000029a60000613d000000000601034f00000000070a0019000000006806043c0000000007870436000000000027004b000029a20000c13d000000000005004b000029b30000613d000000000141034f0000000304500210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001204350000001f0130003900000e25011001970000000002a10019000000000012004b00000000010000390000000101004039000c00000002001d00000dd10020009c00002d0d0000213d000000010010019000002d0d0000c13d0000000c01000029000000400010043f00000dea0030009c00002d130000213d0000001f0030008c00002d130000a13d00000000010a043300000dd10010009c00002d130000213d0000000002a300190000000001a100190000001f03100039000000000023004b000000000400001900000deb0400804100000deb0330019700000deb05200197000000000653013f000000000053004b000000000300001900000deb0300404100000deb0060009c000000000304c019000000000003004b00002d130000c13d000000001301043400000dd10030009c00002d0d0000213d00000005043002100000003f0540003900000dd2055001970000000c0550002900000dd10050009c00002d0d0000213d000000400050043f0000000c050000290000000003350436000900000003001d0000000003140019000000000023004b00002d130000213d000000000031004b000029f10000813d0000000c02000029000000001401043400000db10040009c00002d130000213d00000020022000390000000000420435000000000031004b000029ea0000413d00000dcf010000410000000000100443000000000100041200000004001004430000002400900443000000000100041400000dae0010009c00000dae01008041000000c00110021000000df8011001c7000080050200003936b536b00000040f000000010020019000002d330000613d0000000c020000290000000006020433000000000101043b00000db1011001970000000d0010006b00002a070000c13d000000000506001900002a7c0000013d000000000006004b00002a790000613d00000df90700004100000000080000190000000005000019000700000006001d00002a170000013d00000005015002100000000901100029000000000209043300000db102200197000000000021043500000001055000390000000108800039000000000068004b00002a7a0000813d0000000c010000290000000001010433000000000081004b00002a730000a13d000000050180021000000009091000290000000002090433000000400a00043d00000000007a0435000000000100041400000db102200197000000040020008c00002a290000c13d0000000003000031000000200030008c0000002004000039000000000403401900002a5d0000013d000d00000009001d000a00000008001d000800000005001d00000dae00a0009c00000dae0300004100000000030a4019000000400330021000000dae0010009c00000dae01008041000000c001100210000000000131019f00000db3011001c7000b0000000a001d36b536b00000040f0000000b0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900002a470000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00002a430000c13d0000001f0740019000002a540000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000000d0900002900002d150000613d0000000805000029000000070600002900000df9070000410000000a080000290000001f01400039000000600210018f0000000001a20019000000000021004b0000000002000039000000010200403900000dd10010009c00002d0d0000213d000000010020019000002d0d0000c13d000000400010043f000000200030008c00002d130000413d00000000010a0433000000000001004b00002a140000613d0000000c010000290000000001010433000000000081004b00002a730000a13d000000000051004b00002a0e0000213d00000e1301000041000000000010043f0000003201000039000000040010043f00000dd901000041000036b70001043000000000050000190000000c01000029000000000051043500000dd10050009c00002d0d0000213d00000005015002100000003f0210003900000dd202200197000000400300043d0000000002230019000d00000003001d000000000032004b0000000003000039000000010300403900000dd10020009c00002d0d0000213d000000010030019000002d0d0000c13d000000400020043f0000000d020000290000000006520436000000000005004b00002ada0000613d0000000002000019000000400300043d00000dd50030009c00002d0d0000213d0000022004300039000000400040043f00000200043000390000000000040435000001e0043000390000000000040435000001c0043000390000000000040435000001a00430003900000000000404350000018004300039000000000004043500000160043000390000000000040435000001400430003900000000000404350000012004300039000000000004043500000100043000390000000000040435000000e0043000390000000000040435000000c0043000390000000000040435000000a0043000390000000000040435000000800430003900000000000404350000006004300039000000000004043500000040043000390000000000040435000000200430003900000000000404350000000000030435000000000462001900000000003404350000002002200039000000000012004b00002a910000413d0000000003000019000800000005001d000700000006001d0000000c010000290000000001010433000000000031004b00002a730000a13d0000000502300210000a00000002001d0000000901200029000000000101043300000db101100197000b00000003001d36b52e930000040f0000000b03000029000000070600002900000008050000290000000d020000290000000002020433000000000032004b00002a730000a13d0000000a0260002900000000001204350000000d010000290000000001010433000000000031004b00002a730000a13d0000000103300039000000000053004b00002abf0000413d00000005010000290000000001010433000000400900043d00000e2002000041000000000029043500000db101100197000000040290003900000000001204350000000001000414000000040200002900000db102200197000000040020008c00002aea0000c13d0000000201000367000000000300003100002afd0000013d00000dae0090009c000c00000009001d00000dae030000410000000003094019000000400330021000000dae0010009c00000dae01008041000000c001100210000000000131019f00000dd9011001c736b536b00000040f0000000003010019000000600330027000000dae0030019d00000dae033001970002000000010355000000010020019000002d400000613d0000000c0900002900000e25043001980000001f0530018f000000000249001900002b070000613d000000000601034f0000000007090019000000006806043c0000000007870436000000000027004b00002b030000c13d000000000005004b00002b140000613d000000000141034f0000000304500210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001204350000001f0130003900000e25021001970000000001920019000000000021004b0000000002000039000000010200403900000dd10010009c00002d0d0000213d000000010020019000002d0d0000c13d000000400010043f00000dea0030009c00002d130000213d000000200030008c00002d130000413d000000000409043300000dd10040009c00002d130000213d00000000029300190000000004940019000000000542004900000dea0050009c00002d130000213d000000600050008c00002d130000413d00000dfe0010009c00002d0d0000213d0000006005100039000000400050043f000000007604043400000dd10060009c00002d130000213d00000000084600190000001f06800039000000000026004b000000000900001900000deb0900804100000deb0a60019700000deb06200197000000000b6a013f00000000006a004b000000000a00001900000deb0a00404100000deb00b0009c000000000a09c01900000000000a004b00002d130000c13d000000009808043400000dd10080009c00002d0d0000213d0000001f0a80003900000e250aa001970000003f0aa0003900000e250aa00197000000000a5a001900000dd100a0009c00002d0d0000213d0000004000a0043f0000000000850435000000000a98001900000000002a004b00002d130000213d000000800a100039000000000008004b00002b5d0000613d000000000b000019000000000cab0019000000000d9b0019000000000d0d04330000000000dc0435000000200bb0003900000000008b004b00002b560000413d0000000008a8001900000000000804350000000005510436000000000707043300000dd10070009c00002d130000213d00000000074700190000001f08700039000000000028004b000000000900001900000deb0900804100000deb08800197000000000a68013f000000000068004b000000000800001900000deb0800404100000deb00a0009c000000000809c019000000000008004b00002d130000c13d000000008707043400000dd10070009c00002d0d0000213d0000001f0970003900000e25099001970000003f0990003900000e250a900197000000400900043d000000000aa9001900000000009a004b000000000b000039000000010b00403900000dd100a0009c00002d0d0000213d0000000100b0019000002d0d0000c13d0000004000a0043f000000000a790436000000000b87001900000000002b004b00002d130000213d000000000007004b00002b900000613d000000000b000019000000000cab0019000000000d8b0019000000000d0d04330000000000dc0435000000200bb0003900000000007b004b00002b890000413d00000000077a0019000000000007043500000000009504350000004007400039000000000707043300000dd10070009c00002d130000213d00000000044700190000001f07400039000000000027004b000000000800001900000deb0800804100000deb07700197000000000967013f000000000067004b000000000600001900000deb0600404100000deb0090009c000000000608c019000000000006004b00002d130000c13d000000006404043400000dd10040009c00002d0d0000213d0000001f0740003900000e25077001970000003f0770003900000e2507700197000000400a00043d00000000077a00190000000000a7004b0000000008000039000000010800403900000dd10070009c00002d0d0000213d000000010080019000002d0d0000c13d000000400070043f00000000074a04360000000008640019000000000028004b00002d130000213d000000000004004b00002bc40000613d000000000200001900000000087200190000000009620019000000000909043300000000009804350000002002200039000000000042004b00002bbd0000413d0000000002470019000000000002043500000040021000390000000000a204350000000001010433000800000001001d0000000001050433000300000001001d000000060200002900000080012000390000000001010433000400000001001d00000060012000390000000001010433000700000001001d00000020012000390000000001010433000900000001001d0000000001020433000a00000001001d00000005010000290000000002010433000000400c00043d00000e1b0100004100000000001c0435000000000100041400000db105200197000000040050008c000c0000000a001d000b00000005001d00002be70000c13d000000200030008c0000002004000039000000000403401900002c170000013d00000dae00c0009c00000dae0200004100000000020c4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c7000000000205001900060000000c001d36b536b00000040f000000060c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c001900002c040000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b00002c000000c13d000000000006004b00002c110000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000000c0a00002900002d4c0000613d0000000b050000290000001f01400039000000600110018f000000000bc1001900000000001b004b0000000002000039000000010200403900000dd100b0009c00002d0d0000213d000000010020019000002d0d0000c13d0000004000b0043f000000200030008c00002d130000413d00000000020c0433000600000002001d00000db10020009c00002d130000213d00000e210200004100000000002b04350000000002000414000000040050008c00002c5f0000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900050000000b001d36b536b00000040f000000050b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900002c4a0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00002c460000c13d000000000006004b00002c570000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000000c0a00002900002d580000613d0000001f01400039000000600110018f0000000b05000029000000000cb1001900000dd100c0009c00002d0d0000213d0000004000c0043f000000200030008c00002d130000413d00000000020b0433000500000002001d00000e220200004100000000002c04350000000002000414000000040050008c00002c9e0000613d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900020000000c001d36b536b00000040f000000020c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c001900002c890000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b00002c850000c13d000000000006004b00002c960000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000000c0a00002900002d640000613d0000001f01400039000000600110018f0000000b05000029000000000bc1001900000dd100b0009c00002d0d0000213d0000004000b0043f000000200030008c00002d130000413d00000000060c043300000e230200004100000000002b04350000000002000414000000040050008c00002cde0000613d000100000006001d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900020000000b001d36b536b00000040f000000020b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900002cc80000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00002cc40000c13d000000000006004b00002cd50000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000000c0a00002900002d700000613d0000001f01400039000000600110018f0000000b0500002900000001060000290000000001b1001900000dd10010009c00002d0d0000213d000000400010043f000000200030008c00002d130000413d00000e1f0010009c00002d0d0000213d00000000020b0433000001a003100039000000400030043f00000180031000390000000d0400002900000000004304350000016003100039000000000023043500000140021000390000000000620435000001200210003900000005030000290000000000320435000001000210003900000006030000290000000000320435000000e0021000390000000000a20435000000c00210003900000003030000290000000000320435000000a0021000390000000803000029000000000032043500000080021000390000000403000029000000000032043500000060021000390000000703000029000000000032043500000040021000390000000000520435000000090200002900000db102200197000000200310003900000000002304350000000a020000290000000000210435000000000001042d00000e1301000041000000000010043f0000004101000039000000040010043f00000dd901000041000036b7000104300000000001000019000036b7000104300000001f0530018f00000db006300198000000400200043d000000000462001900002d200000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d1c0000c13d000000000005004b00002d2d0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000dae0020009c00000dae020080410000004002200210000000000112019f000036b700010430000000000001042f0000001f0530018f00000db006300198000000400200043d000000000462001900002d200000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d3b0000c13d00002d200000013d0000001f0530018f00000db006300198000000400200043d000000000462001900002d200000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d470000c13d00002d200000013d0000001f0530018f00000db006300198000000400200043d000000000462001900002d200000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d530000c13d00002d200000013d0000001f0530018f00000db006300198000000400200043d000000000462001900002d200000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d5f0000c13d00002d200000013d0000001f0530018f00000db006300198000000400200043d000000000462001900002d200000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d6b0000c13d00002d200000013d0000001f0530018f00000db006300198000000400200043d000000000462001900002d200000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d770000c13d00002d200000013d0002000000000002000000400200043d00000e270020009c00002e570000813d0000004003200039000000400030043f00000020032000390000000000030435000000000002043500000dd702000041000000400c00043d00000000002c0435000000000200041400000db105100197000000040050008c000200000005001d00002d920000c13d0000000003000031000000200030008c0000002004000039000000000403401900002dc10000013d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900010000000c001d36b536b00000040f000000010c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c001900002daf0000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b00002dab0000c13d000000000006004b00002dbc0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002e5d0000613d00000002050000290000001f01400039000000600110018f000000000bc1001900000000001b004b0000000002000039000000010200403900000dd100b0009c00002e570000213d000000010020019000002e570000c13d0000004000b0043f0000001f0030008c00002e550000a13d00000000020c043300000db10020009c00002e550000213d00000e1b0400004100000000004b04350000000004000414000000040020008c00002e060000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000db3011001c700010000000b001d36b536b00000040f000000010b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900002df20000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00002dee0000c13d000000000006004b00002dff0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002e690000613d0000001f01400039000000600110018f0000000205000029000000000cb1001900000dd100c0009c00002e570000213d0000004000c0043f000000200030008c00002e550000413d00000000020b043300000db10020009c00002e550000213d00000e1d0400004100000000004c04350000000404c0003900000000005404350000000004000414000000040020008c00002e460000613d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000dd9011001c700010000000c001d36b536b00000040f000000010c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c001900002e320000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b00002e2e0000c13d000000000006004b00002e3f0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002e750000613d0000001f01400039000000600110018f00000002050000290000000001c1001900000dd10010009c00002e570000213d000000400010043f000000200030008c00002e550000413d00000dfd0010009c00002e570000213d00000000020c04330000004003100039000000400030043f000000200310003900000000002304350000000000510435000000000001042d0000000001000019000036b70001043000000e1301000041000000000010043f0000004101000039000000040010043f00000dd901000041000036b7000104300000001f0530018f00000db006300198000000400200043d000000000462001900002e800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002e640000c13d00002e800000013d0000001f0530018f00000db006300198000000400200043d000000000462001900002e800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002e700000c13d00002e800000013d0000001f0530018f00000db006300198000000400200043d000000000462001900002e800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002e7c0000c13d000000000005004b00002e8d0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000dae0020009c00000dae020080410000004002200210000000000112019f000036b7000104300011000000000002000000400200043d00000e280020009c000033720000813d0000022003200039000000400030043f00000200032000390000000000030435000001e0032000390000000000030435000001c0032000390000000000030435000001a00320003900000000000304350000018003200039000000000003043500000160032000390000000000030435000001400320003900000000000304350000012003200039000000000003043500000100032000390000000000030435000000e0032000390000000000030435000000c0032000390000000000030435000000a003200039000000000003043500000080032000390000000000030435000000600320003900000000000304350000004003200039000000000003043500000020032000390000000000030435000000000002043500000dd602000041000000400b00043d00000000002b0435000000000200041400000db105100197000000040050008c000e00000005001d00002ec70000c13d0000000003000031000000200030008c0000002004000039000000000403401900002ef60000013d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900110000000b001d36b536b00000040f000000110b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900002ee40000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00002ee00000c13d000000000006004b00002ef10000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000033960000613d0000000e050000290000001f01400039000000600110018f000000000cb1001900000000001c004b0000000002000039000000010200403900000dd100c0009c000033720000213d0000000100200190000033720000c13d0000004000c0043f0000001f0030008c000033700000a13d00000000020b0433000b00000002001d00000dd70200004100000000002c04350000000002000414000000040050008c00002f3b0000613d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900110000000c001d36b536b00000040f000000110c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c001900002f270000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b00002f230000c13d000000000006004b00002f340000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000033a20000613d0000001f01400039000000600110018f0000000e05000029000000000bc1001900000dd100b0009c000033720000213d0000004000b0043f000000200030008c000033700000413d00000000070c043300000db10070009c000033700000213d00000dd80100004100000000061b04360000000401b0003900000000005104350000000001000414000000040070008c000d00000007001d00002f500000c13d000000400030008c0000004004000039000000000403401900002f820000013d001000000006001d00000dae00b0009c00000dae0200004100000000020b4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000dd9011001c7000000000207001900110000000b001d36b536b00000040f000000110b0000290000000003010019000000600330027000000dae03300197000000400030008c000000400400003900000000040340190000001f0640018f000000600740019000000000057b001900002f6e0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00002f6a0000c13d000000000006004b00002f7b0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000033ae0000613d0000000e050000290000000d0700002900000010060000290000001f01400039000000e00110018f000000000cb1001900000dd100c0009c000033720000213d0000004000c0043f000000400030008c000033700000413d00000000020b0433000000000002004b0000000001000039000000010100c039000a00000002001d000000000012004b000033700000c13d0000000001060433000900000001001d00000dda0100004100000000001c04350000000001000414000000040050008c00002f9a0000c13d000000200400003900002fca0000013d00000dae00c0009c00000dae0200004100000000020c4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c7000000000205001900110000000c001d36b536b00000040f000000110c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c001900002fb70000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b00002fb30000c13d000000000006004b00002fc40000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000033ba0000613d0000000e050000290000000d070000290000001f01400039000000600110018f000000000bc1001900000dd100b0009c000033720000213d0000004000b0043f000000200030008c000033700000413d00000000020c0433000c00000002001d00000db10020009c000033700000213d00000ddb0200004100000000002b043500000000020004140000000c04000029000000040040008c0000300e0000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000000c0200002900110000000b001d36b536b00000040f000000110b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900002ff90000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00002ff50000c13d000000000006004b000030060000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000033c60000613d0000001f01400039000000600110018f0000000e050000290000000d07000029000000000ab1001900000dd100a0009c000033720000213d0000004000a0043f000000200030008c000033700000413d00000000010b0433000800000001001d000000ff0010008c000033700000213d00000ddc080000410000002009000039000000000b00001900000000060000190000002401a000390000000000b1043500000000008a04350000000401a0003900000000005104350000000001000414000000040070008c00000000040900190000305a0000613d000f0000000b001d001100000006001d00000dae00a0009c00000dae0200004100000000020a4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000ddd011001c7000000000207001900100000000a001d36b536b00000040f000000100a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000030430000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b0000303f0000c13d0000001f07400190000030500000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000000020090000390000000f0b000029000033780000613d0000000e0500002900000011060000290000000d0700002900000ddc080000410000001f01400039000000600110018f000000000ca1001900000000001c004b0000000002000039000000010200403900000dd100c0009c000033720000213d0000000100200190000033720000c13d0000004000c0043f000000200030008c000033700000413d00000000020a0433000000000002004b0000000004000039000000010400c039000000000042004b000033700000c13d0000000002b201cf000000000626019f0000000102b00039000000ff0b20018f0000000800b0008c000000000a0c00190000301c0000a13d00000ddf0200004100000000002c04350000000002000414000000040050008c000030ad0000613d001100000006001d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900100000000c001d36b536b00000040f000000100c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000030970000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000030930000c13d000000000006004b000030a40000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000033d20000613d0000001f01400039000000600110018f0000000e0500002900000011060000290000000d07000029000000000bc1001900000dd100b0009c000033720000213d0000004000b0043f000000200030008c000033700000413d00000000020c0433000000000002004b001100000006001d000030f80000613d00000de00200004100000000002b04350000000002000414000000040050008c000030ef0000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000000002050019000f0000000b001d36b536b00000040f0000000f0b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000030d90000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000030d50000c13d000000000006004b000030e60000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000344a0000613d0000001f01400039000000600110018f0000000e0500002900000011060000290000000d070000290000000001b1001900000dd10010009c000033720000213d000000400010043f000000200030008c000033700000413d00000000020b0433000000000b010019000030f90000013d000000000200001900000de10100004100000000001b04350000000001000414000000040050008c001000000002001d000031010000c13d0000002004000039000031320000013d00000dae00b0009c00000dae0200004100000000020b4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c70000000002050019000f0000000b001d36b536b00000040f0000000f0b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b00190000311e0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000311a0000c13d000000000006004b0000312b0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000033de0000613d0000000e0500002900000011060000290000000d070000290000001f01400039000000600110018f000000000cb1001900000dd100c0009c000033720000213d0000004000c0043f000000200030008c000033700000413d00000000020b0433000f00000002001d00000de20200004100000000002c04350000000002000414000000040050008c000031740000613d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900070000000c001d36b536b00000040f000000070c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c00190000315e0000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b0000315a0000c13d000000000006004b0000316b0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000033ea0000613d0000001f01400039000000600110018f0000000e0500002900000011060000290000000d07000029000000000bc1001900000dd100b0009c000033720000213d0000004000b0043f000000200030008c000033700000413d00000000020c0433000700000002001d00000de30200004100000000002b04350000000402b0003900000000005204350000000002000414000000040070008c000031b60000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c7000000000207001900060000000b001d36b536b00000040f000000060b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000031a00000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000319c0000c13d000000000006004b000031ad0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000033f60000613d0000001f01400039000000600110018f0000000e0500002900000011060000290000000d07000029000000000cb1001900000dd100c0009c000033720000213d0000004000c0043f000000200030008c000033700000413d00000000020b0433000d00000002001d00000de40200004100000000002c04350000000402c0003900000000005204350000000002000414000000040070008c000031f70000613d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c7000000000207001900060000000c001d36b536b00000040f000000060c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000031e20000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000031de0000c13d000000000006004b000031ef0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000034020000613d0000001f01400039000000600110018f0000000e050000290000001106000029000000000bc1001900000dd100b0009c000033720000213d0000004000b0043f000000200030008c000033700000413d00000000020c0433000600000002001d00000de50200004100000000002b04350000000002000414000000040050008c000032360000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900050000000b001d36b536b00000040f000000050b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000032210000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000321d0000c13d000000000006004b0000322e0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000340e0000613d0000001f01400039000000600110018f0000000e050000290000001106000029000000000cb1001900000dd100c0009c000033720000213d0000004000c0043f000000200030008c000033700000413d00000000020b0433000500000002001d00000de60200004100000000002c04350000000002000414000000040050008c000032750000613d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900040000000c001d36b536b00000040f000000040c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000032600000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b0000325c0000c13d000000000006004b0000326d0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000341a0000613d0000001f01400039000000600110018f0000000e050000290000001106000029000000000bc1001900000dd100b0009c000033720000213d0000004000b0043f000000200030008c000033700000413d00000000020c0433000400000002001d00000ddf0200004100000000002b04350000000002000414000000040050008c000032b40000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900030000000b001d36b536b00000040f000000030b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b00190000329f0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000329b0000c13d000000000006004b000032ac0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000034260000613d0000001f01400039000000600110018f0000000e050000290000001106000029000000000cb1001900000dd100c0009c000033720000213d0000004000c0043f000000200030008c000033700000413d00000000020b0433000300000002001d00000de70200004100000000002c04350000000002000414000000040050008c000032f30000613d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900020000000c001d36b536b00000040f000000020c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000032de0000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000032da0000c13d000000000006004b000032eb0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000034320000613d0000001f01400039000000600110018f0000000e050000290000001106000029000000000bc1001900000dd100b0009c000033720000213d0000004000b0043f000000200030008c000033700000413d00000000070c043300000ddb0200004100000000002b04350000000002000414000000040050008c000033330000613d000100000007001d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900020000000b001d36b536b00000040f000000020b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b00190000331d0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000033190000c13d000000000006004b0000332a0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000343e0000613d0000001f01400039000000600110018f0000000e05000029000000110600002900000001070000290000000001b1001900000dd10010009c000033720000213d000000400010043f000000200030008c000033700000413d00000000020b0433000000ff0020008c000033700000213d00000dd50010009c000033720000213d0000022003100039000000400030043f000002000310003900000000006304350000000803000029000000ff0330018f000001e0041000390000000000340435000001c0031000390000000000230435000001a0021000390000000c03000029000000000032043500000180021000390000000903000029000000000032043500000160021000390000000a03000029000000000032043500000140021000390000000000720435000001200210003900000003030000290000000000320435000001000210003900000004030000290000000000320435000000e00210003900000005030000290000000000320435000000c00210003900000006030000290000000000320435000000a0021000390000000d03000029000000000032043500000080021000390000000703000029000000000032043500000060021000390000000f03000029000000000032043500000040021000390000001003000029000000000032043500000020021000390000000b0300002900000000003204350000000000510435000000000001042d0000000001000019000036b70001043000000e1301000041000000000010043f0000004101000039000000040010043f00000dd901000041000036b7000104300000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000337f0000c13d000000000005004b000033900000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000dae0020009c00000dae020080410000004002200210000000000112019f000036b7000104300000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000339d0000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000033a90000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000033b50000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000033c10000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000033cd0000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000033d90000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000033e50000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000033f10000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000033fd0000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000034090000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000034150000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000034210000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000342d0000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000034390000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000034450000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000034510000c13d000033830000013d0007000000000002000000400300043d00000e290030009c0000360e0000813d000000c004300039000000400040043f000000a004300039000000000004043500000080043000390000000000040435000000600430003900000000000404350000004004300039000000000004043500000020043000390000000000040435000000000003043500000df203000041000000400c00043d00000000003c043500000db1032001970000000402c00039000700000003001d0000000000320435000000000200041400000db105100197000000040050008c000600000005001d000034780000c13d0000000003000031000000200030008c00000020040000390000000004034019000034a70000013d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c7000000000205001900050000000c001d36b536b00000040f000000050c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000034950000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000034910000c13d000000000006004b000034a20000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000036160000613d00000006050000290000001f01400039000000600110018f000000000bc1001900000000001b004b0000000002000039000000010200403900000dd100b0009c0000360e0000213d00000001002001900000360e0000c13d0000004000b0043f0000001f0030008c000036140000a13d00000000020c0433000500000002001d00000df30200004100000000002b04350000000402b00039000000070400002900000000004204350000000002000414000000040050008c000034ef0000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c7000000000205001900040000000b001d36b536ab0000040f000000040b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000034db0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000034d70000c13d000000000006004b000034e80000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000036220000613d0000001f01400039000000600110018f0000000605000029000000000cb1001900000dd100c0009c0000360e0000213d0000004000c0043f000000200030008c000036140000413d00000000020b0433000400000002001d00000df40200004100000000002c04350000000402c00039000000070400002900000000004204350000000002000414000000040050008c000035300000613d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c7000000000205001900030000000c001d36b536ab0000040f000000030c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c00190000351c0000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000035180000c13d000000000006004b000035290000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000362e0000613d0000001f01400039000000600110018f0000000605000029000000000bc1001900000dd100b0009c0000360e0000213d0000004000b0043f000000200030008c000036140000413d00000000020c0433000300000002001d00000dda0200004100000000002b04350000000002000414000000040050008c0000356e0000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900020000000b001d36b536b00000040f000000020b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b00190000355a0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000035560000c13d000000000006004b000035670000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000363a0000613d0000001f01400039000000600110018f0000000605000029000000000cb1001900000dd100c0009c0000360e0000213d0000004000c0043f000000200030008c000036140000413d00000000020b043300000db10020009c000036140000213d00000df20400004100000000004c04350000000406c00039000000070400002900000000004604350000000004000414000000040020008c000035b10000613d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000dd9011001c7000100000002001d00020000000c001d36b536b00000040f000000020c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c00190000359c0000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000035980000c13d000000000006004b000035a90000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000036460000613d0000001f01400039000000600110018f00000006050000290000000102000029000000000bc1001900000dd100b0009c0000360e0000213d0000004000b0043f000000200030008c000036140000413d00000000070c04330000002404b00039000000000054043500000df50400004100000000004b04350000000406b00039000000070400002900000000004604350000000004000414000000040020008c000035f40000613d000200000007001d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000ddd011001c700070000000b001d36b536b00000040f000000070b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000035df0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000035db0000c13d000000000006004b000035ec0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000036520000613d0000001f01400039000000600110018f000000060500002900000002070000290000000001b1001900000dd10010009c0000360e0000213d000000400010043f000000200030008c000036140000413d00000df10010009c0000360e0000213d00000000020b0433000000c003100039000000400030043f000000a0031000390000000000230435000000800210003900000000007204350000006002100039000000030300002900000000003204350000004002100039000000040300002900000000003204350000002002100039000000050300002900000000003204350000000000510435000000000001042d00000e1301000041000000000010043f0000004101000039000000040010043f00000dd901000041000036b7000104300000000001000019000036b7000104300000001f0530018f00000db006300198000000400200043d00000000046200190000365d0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000361d0000c13d0000365d0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000365d0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000036290000c13d0000365d0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000365d0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000036350000c13d0000365d0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000365d0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000036410000c13d0000365d0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000365d0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000364d0000c13d0000365d0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000365d0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000036590000c13d000000000005004b0000366a0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000dae0020009c00000dae020080410000004002200210000000000112019f000036b700010430000000010010008c000036780000613d000000020010008c000036860000c13d00000e0801000041000000000010044300000000010004140000367b0000013d00000e06010000410000000000100443000000000100041400000dae0010009c00000dae01008041000000c00110021000000e07011001c70000800b0200003936b536b00000040f0000000100200190000036850000613d000000000101043b000000000001042d000000000001042f00000e1301000041000000000010043f0000005101000039000000040010043f00000dd901000041000036b700010430000000000001042f00000000050100190000000000200443000000050030008c0000369b0000413d000000040100003900000000020000190000000506200210000000000664001900000005066002700000000006060031000000000161043a0000000102200039000000000031004b000036930000413d00000dae0030009c00000dae030080410000006001300210000000000200041400000dae0020009c00000dae02008041000000c002200210000000000112019f00000e2a011001c7000000000205001936b536b00000040f0000000100200190000036aa0000613d000000000101043b000000000001042d000000000001042f000036ae002104210000000102000039000000000001042d0000000002000019000000000001042d000036b3002104230000000102000039000000000001042d0000000002000019000000000001042d000036b500000432000036b60001042e000036b70001043000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000ffffffffffffffffffffffffffffffffffffffff09c8f7ec0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000001e13380ae0fcab3000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000140000001000000000000000000000000000000000000000000000000000000000000000000000000007c51b64100000000000000000000000000000000000000000000000000000000c7ad089400000000000000000000000000000000000000000000000000000000d77ebf9500000000000000000000000000000000000000000000000000000000d77ebf9600000000000000000000000000000000000000000000000000000000e0a67f1100000000000000000000000000000000000000000000000000000000e1d146fb00000000000000000000000000000000000000000000000000000000c7ad089500000000000000000000000000000000000000000000000000000000d26998e900000000000000000000000000000000000000000000000000000000aa5dbd2200000000000000000000000000000000000000000000000000000000aa5dbd2300000000000000000000000000000000000000000000000000000000b3124239000000000000000000000000000000000000000000000000000000007c51b642000000000000000000000000000000000000000000000000000000007c84e3b30000000000000000000000000000000000000000000000000000000047d86a80000000000000000000000000000000000000000000000000000000006857249b000000000000000000000000000000000000000000000000000000006857249c000000000000000000000000000000000000000000000000000000007a27db570000000000000000000000000000000000000000000000000000000047d86a810000000000000000000000000000000000000000000000000000000055dd951500000000000000000000000000000000000000000000000000000000345954db00000000000000000000000000000000000000000000000000000000345954dc000000000000000000000000000000000000000000000000000000003e3e399c000000000000000000000000000000000000000000000000000000000d3ae318000000000000000000000000000000000000000000000000000000001f884fdf310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e0000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000000000000000000000000000000000ffffffffffffff7f00000000000000000000000000000000000000000000003fffffffffffffffe0000000000000000000000000000000000000000000000000fffffffffffffddf182df0f5000000000000000000000000000000000000000000000000000000005fe3b567000000000000000000000000000000000000000000000000000000008e8f294b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000006f307dc300000000000000000000000000000000000000000000000000000000313ce56700000000000000000000000000000000000000000000000000000000e85a2960000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffdf18160ddd00000000000000000000000000000000000000000000000000000000ae9d70b000000000000000000000000000000000000000000000000000000000f8f9da2800000000000000000000000000000000000000000000000000000000173b99040000000000000000000000000000000000000000000000000000000002c3bcbb000000000000000000000000000000000000000000000000000000004a5844320000000000000000000000000000000000000000000000000000000047bd3718000000000000000000000000000000000000000000000000000000008f840ddd000000000000000000000000000000000000000000000000000000003b1d21a200000000000000000000000000000000000000000000000000000000f36dba380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000008000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000080000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffebf000000000000000000000000000000000000000000000000ffffffffffffff3f70a082310000000000000000000000000000000000000000000000000000000017bfdfbc000000000000000000000000000000000000000000000000000000003af9e66900000000000000000000000000000000000000000000000000000000dd62ed3e00000000000000000000000000000000000000000000000000000000b0772d0b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000800000000000000000020000020000000000000000000000000000004400000000000000000000000022abdbf50000000000000000000000000000000000000000000000000000000061252fd100000000000000000000000000000000000000000000000000000000f7c618c1000000000000000000000000000000000000000000000000000000001627ee8900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffbf000000000000000000000000000000000000000000000000ffffffffffffff9f8f693ec70000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff81814945000000000000000000000000000000000000000000000000000000002c427b570000000000000000000000000000000000000000000000000000000092a1823500000000000000000000000000000000000000000000000000000000aa5af0fd000000000000000000000000000000000000000000000000000000007c05a7c500000000000000000000000000000000000000000000000000000000796b89b91644bc98cd93958e4c9038275d622183e25ac5af08cc6b5d95539132020000020000000000000000000000000000000400000000000000000000000042cbb15ccdc3cad6266b0e7a08c0454b23bf29dc2df74b6f3c209e9336465bd10000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000c097ce7bc90715b34b9f10000000006e657720696e646578206f766572666c6f777300000000000000000000000000000000010000000000000000000000000000000000000000000000000000000008c379a00000000000000000000000000000000000000000000000000000000074c4c1cc000000000000000000000000000000000000000000000000000000006dfd08ca00000000000000000000000000000000000000000000000000000000160c3a030000000000000000000000000000000000000000000000000000000095dd919300000000000000000000000000000000000000000000000000000000552c0971000000000000000000000000000000000000000000000000000000004e487b7100000000000000000000000000000000000000000000000000000000266e0a7f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000440000008000000000000000007aee632d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000002200000000000000000000000000000000000000000000000000000000000000000ffffffffffffff5f0000000000000000000000000000000000000004000000e00000000000000000000000000000000000000000000000000000000000000000ffffffffffffff1f7dc0d1d000000000000000000000000000000000000000000000000000000000bbcac55700000000000000000000000000000000000000000000000000000000fc57d4df00000000000000000000000000000000000000000000000000000000d88ff1f400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffe5fa3aefa2c00000000000000000000000000000000000000000000000000000000e8755446000000000000000000000000000000000000000000000000000000004ada90af00000000000000000000000000000000000000000000000000000000db5c65de00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffedfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000000000000000000000000000000000fffffffffffffe60000000000000000000000000000000000000000000000000ffffffffffffffc0000000000000000000000000000000000000000000000000fffffffffffffde0000000000000000000000000000000000000000000000000ffffffffffffff4002000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd266e967e3b2382c6511fd4150dd11c23ea0355910672dd36d07081e6b4a2b6", "devdoc": { "author": "Venus", "kind": "dev", @@ -1294,6 +1312,7 @@ "custom:oz-upgrades-unsafe-allow": "constructor", "params": { "blocksPerYear_": "The number of blocks per year", + "corePoolComptroller_": "The address of the core pool comptroller", "timeBased_": "A boolean indicating whether the contract is based on time or block." } }, @@ -1438,6 +1457,9 @@ "blocksOrSecondsPerYear()": { "notice": "Stores blocksPerYear if isTimeBased is true else secondsPerYear is stored" }, + "corePoolComptroller()": { + "notice": "Address of the core pool comptroller (all markets are returned for this pool, including paused ones)" + }, "getAllPools(address)": { "notice": "Queries all pools with addtional details for each of them" }, @@ -1487,7 +1509,7 @@ "storageLayout": { "storage": [ { - "astId": 10243, + "astId": 5806, "contract": "contracts/Lens/PoolLens.sol:PoolLens", "label": "__gap", "offset": 0, @@ -1510,6 +1532,6 @@ } }, "factoryDeps": [ - "0x0003000000000002002e000000000002000000000301034f0000000001030019000000600110027000000b8604100197000200000043035500010000000303550000000100200190000000510000c13d0000012009000039000000400090043f000000040040008c000006070000413d000000000543034f000000000203043b000000e00220027000000b8e0020009c0000007f0000213d00000b9a0020009c0000009a0000213d00000ba00020009c000000d90000213d00000ba30020009c000001650000613d00000ba40020009c000006070000c13d000000240040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000101043b00000ba70010009c000006070000213d0000002302100039000000000042004b000006070000813d0000000402100039000000000223034f000000000202043b001d00000002001d00000ba70020009c000006070000213d001c00240010003d0000001d0100002900000005021002100000001c01200029000000000041004b000006070000213d0000003f0120003900000ba80310019700000ba90030009c000005790000213d0000012001300039000000400010043f0000001d04000029000001200040043f000000000004004b000006470000c13d00000020020000390000000002210436000001200300043d00000000003204350000004002100039000000000003004b000002180000613d000001400400003900000000050000190000000046040434000000007606043400000baa0660019700000000066204360000000007070433000000000076043500000040022000390000000105500039000000000035004b000000460000413d000002180000013d0000000001000416000000000001004b000006070000c13d0000001f0140003900000b8701100197000000e001100039000000400010043f0000001f0240018f00000b8805400198000000e001500039000000620000613d000000e006000039000000000703034f000000007807043c0000000006860436000000000016004b0000005e0000c13d000000000002004b0000006f0000613d000000000353034f0000000302200210000000000501043300000000052501cf000000000525022f000000000303043b0000010002200089000000000323022f00000000022301cf000000000252019f0000000000210435000000400040008c000006070000413d000000e00100043d000000000001004b0000000002000039000000010200c039000000000021004b000006070000c13d000001000200043d000000000001004b000000f60000613d000000000002004b0000014c0000c13d00000b8b020000410000000103000039000001550000013d00000b8f0020009c000000bd0000213d00000b950020009c000000fb0000213d00000b980020009c000001ce0000613d00000b990020009c000006070000c13d000000240040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000101043b00000baa0010009c000006070000213d2e15248d0000040f000000400200043d002000000002001d2e1520db0000040f000000200100002900000b860010009c00000b8601008041000000400110021000000bb2011001c700002e160001042e00000b9b0020009c000001160000213d00000b9e0020009c000002210000613d00000b9f0020009c000006070000c13d000000640040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000201043b00000baa0020009c000006070000213d0000002401300370000000000101043b00000baa0010009c000006070000213d0000004403300370000000000303043b00000baa0030009c000006070000213d00000bdd04000041000001200040043f000001240010043f000001440030043f0000000001000414000000040020008c000005d80000c13d0000000003000031000000200030008c00000020040000390000000004034019000005fe0000013d00000b900020009c000001330000213d00000b930020009c000002490000613d00000b940020009c000006070000c13d000000440040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000201043b00000baa0020009c000006070000213d0000002401300370000000000301043b00000baa0030009c000006070000213d00000bab01000041000001200010043f000001240030043f0000000003000414000000040020008c000000000105034f000003820000c13d00000000030000310000038f0000013d00000ba10020009c0000025c0000613d00000ba20020009c000006070000c13d000000240040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000101043b002000000001001d00000baa0010009c000006070000213d0000018009000039000000400090043f000001200000043f000001400000043f0000006001000039000001600010043f00000bbc01000041000001800010043f00000000030004140000002002000029000000040020008c000000000105034f000003190000c13d0000000003000031000003260000013d000000000002004b000001540000c13d000000400100043d00000b89020000410000014e0000013d00000b960020009c0000026f0000613d00000b970020009c000006070000c13d000000440040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000101043b00000baa0010009c000006070000213d0000002402300370000000000202043b00000baa0020009c000006070000213d2e152b470000040f000000400200043d002000000002001d2e1520e10000040f000000200100002900000b860010009c00000b8601008041000000400110021000000bb0011001c700002e160001042e00000b9c0020009c000002820000613d00000b9d0020009c000006070000c13d000000440040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000101043b002000000001001d00000baa0010009c000006070000213d002a00200000002d0000002401300370000000000101043b001f00000001001d00000baa0010009c000006070000213d00000bbc01000041000001200010043f00000000030004140000001f02000029000000040020008c000000000105034f000003f30000c13d0000000003000031000003ff0000013d00000b910020009c000002920000613d00000b920020009c000006070000c13d0000000001000416000000000001004b000006070000c13d0000000001000412002200000001001d002100400000003d000080050100003900000044030000390000000004000415000000220440008a000000050440021000000ba5020000412e152ded0000040f2e152dd00000040f000000400200043d000000000012043500000b860020009c00000b8602008041000000400120021000000ba6011001c700002e160001042e000000400100043d00000b8c02000041000000000021043500000b860010009c00000b8601008041000000400110021000000b8a011001c700002e17000104300000000203000039000000a00010043f000000800020043f000000c00030043f0000014000000443000001600020044300000020020000390000018000200443000001a0001004430000004001000039000001c000100443000001e00030044300000100002004430000000301000039000001200010044300000b8d0100004100002e160001042e000000440040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000101043b00000baa0010009c000006070000213d0000002402300370000000000602043b00000ba70060009c000006070000213d000000000264004900000bad0020009c000006070000213d000000a40020008c000006070000413d000001c002000039000000400020043f0000000405600039000000000753034f000000000707043b00000ba70070009c000006070000213d00000000076700190000002306700039000000000046004b000006070000813d0000000408700039000000000683034f000000000606043b00000bfd0060009c000005790000813d0000001f0a60003900000bff0aa001970000003f0aa0003900000bff0aa0019700000bfe00a0009c000005790000213d000001c00aa000390000004000a0043f000001c00060043f00000000076700190000002407700039000000000047004b000006070000213d0000002004800039000000000743034f00000bff086001980000001f0960018f000001e004800039000001a00000613d000001e00a000039000000000b07034f00000000bc0b043c000000000aca043600000000004a004b0000019c0000c13d000000000009004b000001ad0000613d000000000787034f0000000308900210000000000904043300000000098901cf000000000989022f000000000707043b0000010008800089000000000787022f00000000078701cf000000000797019f0000000000740435000001e0046000390000000000040435000001200020043f0000002002500039000000000423034f000000000404043b00000baa0040009c000006070000213d000001400040043f0000002002200039000000000423034f000000000404043b00000baa0040009c000006070000213d000001600040043f0000002004200039000000000443034f000000000404043b000001800040043f0000004002200039000000000223034f000000000202043b000001a00020043f00000120020000392e1520f70000040f0000002002000039000000400300043d002000000003001d00000000022304362e15200c0000040f00000020020000290000000001210049000003110000013d000000440040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000101043b00000ba70010009c000006070000213d0000002302100039000000000042004b000006070000813d0000000402100039000000000223034f000000000202043b001900000002001d00000ba70020009c000006070000213d001800240010003d000000190100002900000005021002100000001801200029000000000041004b000006070000213d0000002401300370000000000301043b00000baa0030009c000006070000213d0000003f0120003900000ba80410019700000ba90040009c000005790000213d0000012001400039000000400010043f0000001905000029000001200050043f000000000005004b0000067a0000c13d00000020020000390000000002210436000001200300043d00000000003204350000004002100039000000000003004b000002180000613d0000012004000039000000000500001900000020044000390000000006040433000000008706043400000baa07700197000000000772043600000000080804330000000000870435000000400760003900000000070704330000004008200039000000000078043500000060076000390000000007070433000000600820003900000000007804350000008007600039000000000707043300000080082000390000000000780435000000a0066000390000000006060433000000a0072000390000000000670435000000c0022000390000000105500039000000000035004b000001fd0000413d000000000212004900000b860020009c00000b8602008041000000600220021000000b860010009c00000b86010080410000004001100210000000000112019f00002e160001042e000000440040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000101043b002000000001001d00000baa0010009c000006070000213d0000002401300370000000000201043b00000baa0020009c000006070000213d000002c009000039000000400090043f0000006001000039000001200010043f000001400000043f000001600000043f000001800000043f000001a00000043f000001c00010043f000001e00010043f000002000010043f000002200000043f000002400000043f000002600000043f000002800000043f000002a00010043f00000bdf01000041000002c00010043f000002c40020043f00000000030004140000002002000029000000040020008c000000000105034f000005520000c13d00000000030000310000055f0000013d0000000001000416000000000001004b000006070000c13d0000000001000412002400000001001d002300200000003d000080050100003900000044030000390000000004000415000000240440008a000000050440021000000ba5020000412e152ded0000040f000000000001004b0000000001000039000000010100c039000001200010043f00000baf0100004100002e160001042e0000000002000416000000000002004b000006070000c13d002e00200000003d000000240040008c000006070000413d0000000402300370000000000202043b00000baa0020009c000006070000213d002d00000002001d00000be803000041000001200030043f0000000003000414000000040020008c000000000105034f000004d50000c13d000000000a000031000004e10000013d000000240040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000101043b00000baa0010009c000006070000213d2e1525b60000040f000000400200043d002000000002001d2e151fc60000040f000000200100002900000b860010009c00000b8601008041000000400110021000000bb1011001c700002e160001042e0000000001000416000000000001004b000006070000c13d0000000001000412002c00000001001d002b00000000003d0000800501000039000000440300003900000000040004150000002c0440008a000000050440021000000ba5020000412e152ded0000040f000001200010043f00000baf0100004100002e160001042e000000240040008c000006070000413d0000000001000416000000000001004b000006070000c13d0000000401300370000000000101043b00000ba70010009c000006070000213d0000002302100039000000000042004b000006070000813d0000000402100039000000000223034f000000000502043b00000ba70050009c000005790000213d00000005025002100000003f0620003900000ba80660019700000ba90060009c000005790000213d0000012006600039000000400060043f000001200050043f00000024011000390000000002210019000000000042004b000006070000213d000000000005004b000002ba0000613d0000014004000039000000000513034f000000000505043b00000baa0050009c000006070000213d00000000045404360000002001100039000000000021004b000002b20000413d00000120010000392e152d610000040f0000002003000039000000400200043d0000000003320436000000000401043300000000004304350000004003200039000000000004004b000003100000613d000000000500001900000020011000390000000006010433000000008706043400000baa07700197000000000773043600000000080804330000000000870435000000400760003900000000070704330000004008300039000000000078043500000060076000390000000007070433000000600830003900000000007804350000008007600039000000000707043300000080083000390000000000780435000000a0076000390000000007070433000000a0083000390000000000780435000000c0076000390000000007070433000000c0083000390000000000780435000000e0076000390000000007070433000000e008300039000000000078043500000100076000390000000007070433000001000830003900000000007804350000012007600039000000000707043300000120083000390000000000780435000001400760003900000000070704330000014008300039000000000078043500000160076000390000000007070433000000000007004b0000000007000039000000010700c039000001600830003900000000007804350000018007600039000000000707043300000180083000390000000000780435000001a007600039000000000707043300000baa07700197000001a0083000390000000000780435000001c0076000390000000007070433000001c0083000390000000000780435000001e0076000390000000007070433000001e0083000390000000000780435000002000660003900000000060604330000020007300039000000000067043500000220033000390000000105500039000000000045004b000002c50000413d000000000123004900000b860010009c00000b8601008041000000600110021000000b860020009c00000b86020080410000004002200210000000000121019f00002e160001042e00000b860030009c00000b8603008041000000c00130021000000be3011001c72e152e100000040f0000000003010019000000600330027000000b860030019d00000b860330019700020000000103550000000100200190000004c90000613d000001800900003900000bff053001980000001f0630018f00000180045000390000032f0000613d000000000701034f000000007807043c0000000009890436000000000049004b0000032b0000c13d000000000006004b0000033c0000613d000000000151034f0000000305600210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000001f0130003900000bff01100197001e00000001001d00000be40010009c000005790000213d0000001e010000290000018001100039001f00000001001d000000400010043f00000bad0030009c000006070000213d000000200030008c000006070000413d000001800100043d00000ba70010009c000006070000213d00000180023000390000019f04100039000000000024004b000000000500001900000bae0500804100000bae0620019700000bae04400197000000000764013f000000000064004b000000000400001900000bae0400404100000bae0070009c000000000405c019000000000004004b000006070000c13d0000018004100039000000000504043300000ba70050009c000005790000213d00000005045002100000003f0640003900000ba8066001970000001f0660002900000ba70060009c000005790000213d000000400060043f0000001f060000290000000000560435000001a0011000390000000004140019000000000024004b000006070000213d000000000005004b000003760000613d0000001f02000029000000001501043400000baa0050009c000006070000213d00000020022000390000000000520435000000000041004b0000036f0000413d000000400200043d00000be501000041001d00000002001d000000000012043500000000010004140000002002000029000000040020008c000009470000c13d000000200030008c00000020040000390000000004034019000009730000013d00000b860030009c00000b8603008041000000c00130021000000bac011001c72e152e100000040f0000000003010019000000600330027000000b860030019d00000b860330019700020000000103550000000100200190000006090000613d000001200900003900000bff053001980000001f0630018f0000012004500039000003980000613d000000000701034f000000007807043c0000000009890436000000000049004b000003940000c13d000000000006004b000003a50000613d000000000151034f0000000305600210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000001f0130003900000bff0210019700000ba90020009c000005790000213d0000012001200039000000400010043f00000bad0030009c000006070000213d000000200030008c000006070000413d000001200400043d00000ba70040009c000006070000213d00000120033000390000013f05400039000000000035004b000000000600001900000bae0600804100000bae0730019700000bae05500197000000000875013f000000000075004b000000000500001900000bae0500404100000bae0080009c000000000506c019000000000005004b000006070000c13d0000012005400039000000000605043300000ba70060009c000005790000213d00000005056002100000003f0750003900000ba807700197000000000717001900000ba70070009c000005790000213d000000400070043f000000000061043500000140044000390000000005540019000000000035004b000006070000213d0000014002200039000000000006004b000003db0000613d0000000003020019000000004604043400000baa0060009c000006070000213d0000000003630436000000000054004b000003d50000413d000000400300043d00000020040000390000000005430436000000000401043300000000004504350000004001300039000000000004004b000003ea0000613d0000000005000019000000002602043400000baa0660019700000000016104360000000105500039000000000045004b000003e40000413d000000000131004900000b860010009c00000b8601008041000000600110021000000b860030009c00000b86030080410000004002300210000000000121019f00002e160001042e00000b860030009c00000b8603008041000000c00130021000000bbd011001c72e152e100000040f0000000003010019000000600330027000000b860030019d00000b860330019700020000000103550000000100200190000006150000613d00000bff043001980000001f0530018f0000012002400039000004090000613d0000012006000039000000000701034f000000007807043c0000000006860436000000000026004b000004050000c13d000000000005004b000004160000613d000000000641034f0000000304500210000000000502043300000000054501cf000000000545022f000000000606043b0000010004400089000000000646022f00000000044601cf000000000454019f0000000000420435000000000901034f0000001f0130003900000bff0210019700000ba90020009c000005790000213d0000012001200039001e00000001001d000000400010043f00000bad0030009c000006070000213d000000200030008c000006070000413d000001200400043d00000ba70040009c000006070000213d00000120053000390000013f01400039000000000051004b000000000600001900000bae0600804100000bae0750019700000bae01100197000000000871013f000000000071004b000000000100001900000bae0100404100000bae0080009c000000000106c019000000000001004b000006070000c13d0000012001400039000000000701043300000ba70070009c000005790000213d00000005067002100000003f0160003900000ba8011001970000001e0810002900000ba70080009c000005790000213d000000400080043f0000001e01000029000000000071043500000140044000390000000006460019000000000056004b000006070000213d000000000007004b0000044f0000613d0000001e05000029000000004704043400000baa0070009c000006070000213d00000020055000390000000000750435000000000064004b000004480000413d0029001e0000002d00000bbe01000041000000400400043d001d00000004001d000000000014043500000000040004140000001f01000029000000040010008c0000046d0000613d0000001d0100002900000b860010009c00000b8601008041000000400110021000000b860040009c00000b8604008041000000c002400210000000000112019f00000b8a011001c70000001f020000292e152e100000040f0000000003010019000000600330027000000b860030019d00000b8603300197000000000901034f0002000000010355000000010020019000000a3f0000613d0000001f0130003900000b870210019700000bff053001980000001f0630018f0000001d04500029000004770000613d000000000709034f0000001d08000029000000007107043c0000000008180436000000000048004b000004730000c13d000000000006004b000004840000613d000000000159034f0000000305600210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000001d04200029000000000024004b00000000010000390000000101004039001c00000004001d00000ba70040009c000005790000213d0000000100100190000005790000c13d0000001c01000029000000400010043f00000bad0030009c000006070000213d000000200030008c000006070000413d0000001d01000029000000000101043300000ba70010009c000006070000213d0000001d053000290000001d011000290000001f02100039000000000052004b000000000400001900000bae0400804100000bae0220019700000bae06500197000000000762013f000000000062004b000000000200001900000bae0200404100000bae0070009c000000000204c019000000000002004b000006070000c13d000000004201043400000ba70020009c000005790000213d00000005012002100000003f0610003900000ba8066001970000001c0760002900000ba70070009c000005790000213d000000400070043f0000001c0700002900000000002704350000000007140019000000000057004b000006070000213d000000000074004b000014df0000813d0000001c01000029000000004204043400000baa0020009c000006070000213d00000020011000390000000000210435000000000074004b000004b90000413d0000001c010000290000000002010433002800000001001d00000ba70020009c000005790000213d00000005012002100000003f0410003900000ba806400197000014e00000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000004d00000c13d000006630000013d00000b860030009c00000b8603008041000000c00130021000000bbd011001c72e152e100000040f0000000003010019000000600330027000000b860030019d00000b860a30019700020000000103550000000100200190000006210000613d00000bff04a001980000001f05a0018f0000012002400039000004eb0000613d0000012006000039000000000701034f000000007807043c0000000006860436000000000026004b000004e70000c13d000000000005004b000004f80000613d000000000441034f0000000305500210000000000602043300000000065601cf000000000656022f000000000404043b0000010005500089000000000454022f00000000045401cf000000000464019f0000000000420435001e000000010353001f0000000a001d0000001f02a0003900000bff0820019700000ba90080009c000005790000213d0000012001800039000700000001001d000000400010043f0000001f0100002900000bad0010009c000006070000213d0000001f01000029000000200010008c000006070000413d000001200600043d00000ba70060009c000006070000213d0000001f0100002900000120021000390000013f05600039000000000025004b000000000700001900000bae0700804100000bae0420019700000bae05500197000000000945013f000000000045004b000000000500001900000bae0500404100000bae0090009c000000000507c019000000000005004b000006070000c13d0000012001600039000000000901043300000ba70090009c000005790000213d00000005079002100000003f0a70003900000ba80aa00197000000070aa0002900000ba700a0009c000005790000213d0000004000a0043f0000000703000029000000000093043500000140066000390000000007670019000000000027004b000006070000213d000101400080003d000000000009004b000200000000001d000009e50000c13d000000020100002900000005021002100000003f0420003900000be905400197000000400100043d002000000001001d0000000004150019000000000054004b0000000005000039000000010500403900000ba70040009c000005790000213d0000000100500190000005790000c13d000000400040043f000000200100002900000002030000290000000001310436001b00000001001d000000000003004b00000a720000c13d0000002002000039000000400100043d00000000002104350000000004210019000000200300002900000000030304330000000000340435000000400410003900000005053002100000000005450019000000000003004b000012da0000c13d0000000002150049000002190000013d00000b860030009c00000b8603008041000000c00130021000000be0011001c72e152e100000040f0000000003010019000000600330027000000b860030019d00000b8603300197000200000001035500000001002001900000063b0000613d000002c00900003900000bff043001980000001f0630018f000002c002400039000005680000613d000000000701034f000000007807043c0000000009890436000000000029004b000005640000c13d000000000006004b000005750000613d000000000141034f0000000304600210000000000602043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f00000000001204350000001f0130003900000bff0110019700000be10010009c0000057f0000a13d00000bdc01000041000000000010043f0000004101000039000000040010043f00000bb60100004100002e1700010430000002c002100039000000400020043f00000bad0030009c000006070000213d000000200030008c000006070000413d000002c00400043d00000ba70040009c000006070000213d000002c006300039000002c007400039000000000376004900000bad0030009c000006070000213d000000a00030008c000006070000413d00000be20020009c000005790000213d0000036003100039000000400030043f000000000807043300000ba70080009c000006070000213d00000000077800190000001f08700039000000000068004b000000000900001900000bae0900804100000bae0880019700000bae0a600197000000000ba8013f0000000000a8004b000000000800001900000bae0800404100000bae00b0009c000000000809c019000000000008004b000006070000c13d000000008707043400000ba70070009c000005790000213d0000001f0970003900000bff099001970000003f0990003900000bff05900197000000000535001900000ba70050009c000005790000213d000000400050043f00000000007304350000000005870019000000000065004b000006070000213d0000038005100039000000000007004b000005bf0000613d00000000060000190000000009560019000000000a860019000000000a0a04330000000000a904350000002006600039000000000076004b000005b80000413d000000000557001900000000000504350000000000320435000002e003400039000000000303043300000baa0030009c000006070000213d000002e00510003900000000003504350000030003400039000000000303043300000baa0030009c000006070000213d00000300051000390000000000350435000003200340003900000000030304330000032005100039000000000035043500000340011000390000034003400039000000000303043300000000003104350000002001000029000001c50000013d00000b860010009c00000b8601008041000000c00110021000000bde011001c72e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000012005700039000005ed0000613d0000012008000039000000000901034f000000009a09043c0000000008a80436000000000058004b000005e90000c13d000000000006004b000005fa0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000006580000613d0000001f01400039000000600110018f0000012001100039000000400010043f000000200030008c000006070000413d000001200200043d00000baa0020009c000006760000a13d000000000100001900002e17000104300000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000006100000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000061c0000c13d000006630000013d0000001f05a0018f00000b8806a00198000000400200043d00000000046200190000062c0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000006280000c13d000000000005004b000006390000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000006001a00210000006710000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000006420000c13d000006630000013d00000bfc0030009c000005790000213d00000000030000190000004004100039000000400040043f000000200410003900000000000404350000000000010435000001400430003900000000001404350000002003300039000000000023004b000006930000813d000000400100043d00000bc20010009c0000064a0000a13d000005790000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000065f0000c13d000000000005004b000006700000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000b860020009c00000b86020080410000004002200210000000000112019f00002e17000104300000000000210435000000400110021000000ba6011001c700002e160001042e00000bb30040009c000005790000213d0000000004000019000000c005100039000000400050043f000000a0051000390000000000050435000000800510003900000000000504350000006005100039000000000005043500000040051000390000000000050435000000200510003900000000000504350000000000010435000001400540003900000000001504350000002004400039000000000024004b0000077e0000813d000000400100043d00000bb40010009c0000067d0000a13d000005790000013d0000000003000019001f00000003001d0000000502300210001e00000002001d0000001c012000290000000101100367000000000501043b00000baa0050009c000006070000213d000000400100043d00000bc20010009c000005790000213d0000004002100039000000400020043f000000200210003900000000000204350000000000010435000000400b00043d00000bed0100004100000000001b04350000000001000414000000040050008c002000000005001d000006b00000c13d0000000003000031000000200030008c00000020040000390000000004034019000006de0000013d00000b8600b0009c00000b860200004100000000020b4019000000400220021000000b860010009c00000b8601008041000000c001100210000000000121019f00000b8a011001c70000000002050019001b0000000b001d2e152e100000040f0000001b0b0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056b0019000006cc0000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b000006c80000c13d0000001f07400190000006d90000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000000a4e0000613d00000020050000290000001f01400039000000600110018f000000000ab1001900000000001a004b0000000002000039000000010200403900000ba700a0009c000005790000213d0000000100200190000005790000c13d0000004000a0043f000000200030008c000006070000413d00000000020b043300000baa0020009c000006070000213d00000be50400004100000000004a04350000000004000414000000040020008c000007220000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c7001b0000000a001d2e152e100000040f0000001b0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000070e0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b0000070a0000c13d0000001f074001900000071b0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000000a5a0000613d0000001f01400039000000600110018f0000002005000029000000000ba1001900000ba700b0009c000005790000213d0000004000b0043f000000200030008c000006070000413d00000000020a043300000baa0020009c000006070000213d00000be70400004100000000004b04350000000404b0003900000000005404350000000004000414000000040020008c000007610000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000bb6011001c7001b0000000b001d2e152e100000040f0000001b0b0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056b00190000074d0000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b000007490000c13d0000001f074001900000075a0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000000a660000613d0000001f01400039000000600110018f00000020050000290000000001b1001900000ba70010009c000005790000213d000000400010043f000000200030008c000006070000413d00000bc20010009c000005790000213d00000000020b04330000004003100039000000400030043f000000200310003900000000002304350000000000510435000001200200043d0000001f03000029000000000032004b00001d6c0000a13d0000001e0200002900000140022000390000000000120435000001200100043d000000000031004b00001d6c0000a13d00000001033000390000001d0030006c000006940000413d000000400100043d0000003d0000013d00200baa0030019b0000000003000019001e00000003001d0000000502300210001d00000002001d00000018012000290000000101100367000000000501043b00000baa0050009c000006070000213d000000400100043d00000bb40010009c000005790000213d000000c002100039000000400020043f000000a0021000390000000000020435000000800210003900000000000204350000006002100039000000000002043500000040021000390000000000020435000000200210003900000000000204350000000000010435000000400b00043d00000bb50100004100000000001b04350000000401b00039000000200200002900000000002104350000000001000414000000040050008c001f00000005001d000007a70000c13d0000000003000031000000200030008c00000020040000390000000004034019000007d50000013d00000b8600b0009c00000b860200004100000000020b4019000000400220021000000b860010009c00000b8601008041000000c001100210000000000121019f00000bb6011001c70000000002050019001c0000000b001d2e152e100000040f0000001c0b0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056b0019000007c30000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b000007bf0000c13d0000001f07400190000007d00000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000013b50000613d0000001f050000290000001f01400039000000600110018f000000000ab1001900000000001a004b0000000002000039000000010200403900000ba700a0009c000005790000213d0000000100200190000005790000c13d0000004000a0043f000000200030008c000006070000413d00000000020b0433001c00000002001d00000bb70200004100000000002a04350000000402a00039000000200400002900000000004204350000000002000414000000040050008c0000081c0000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bb6011001c70000000002050019001b0000000a001d2e152e0b0000040f0000001b0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000008080000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000008040000c13d0000001f07400190000008150000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000013c10000613d0000001f01400039000000600110018f0000001f05000029000000000ba1001900000ba700b0009c000005790000213d0000004000b0043f000000200030008c000006070000413d00000000020a0433001b00000002001d00000bb80200004100000000002b04350000000402b00039000000200400002900000000004204350000000002000414000000040050008c0000085c0000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bb6011001c70000000002050019001a0000000b001d2e152e0b0000040f0000001a0b0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056b0019000008480000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b000008440000c13d0000001f07400190000008550000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000013cd0000613d0000001f01400039000000600110018f0000001f05000029000000000ab1001900000ba700a0009c000005790000213d0000004000a0043f000000200030008c000006070000413d00000000020b0433001a00000002001d00000bb90200004100000000002a04350000000002000414000000040050008c000008990000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c7000000000205001900170000000a001d2e152e100000040f000000170a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000008850000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000008810000c13d0000001f07400190000008920000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000013d90000613d0000001f01400039000000600110018f0000001f05000029000000000ba1001900000ba700b0009c000005790000213d0000004000b0043f000000200030008c000006070000413d00000000060a043300000baa0060009c000006070000213d00000bb50200004100000000002b04350000000402b00039000000200400002900000000004204350000000002000414000000040060008c000008dc0000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bb6011001c7001600000006001d000000000206001900170000000b001d2e152e100000040f000000170b0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056b0019000008c70000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b000008c30000c13d0000001f07400190000008d40000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000013e50000613d0000001f01400039000000600110018f0000001f050000290000001606000029000000000ab1001900000ba700a0009c000005790000213d0000004000a0043f000000200030008c000006070000413d00000000070b04330000002402a00039000000000052043500000bba0200004100000000002a04350000000402a00039000000200400002900000000004204350000000002000414000000040060008c0000091f0000613d001600000007001d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bbb011001c7000000000206001900170000000a001d2e152e100000040f000000170a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000090a0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000009060000c13d0000001f07400190000009170000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000013f10000613d0000001f01400039000000600110018f0000001f0500002900000016070000290000000001a1001900000ba70010009c000005790000213d000000400010043f000000200030008c000006070000413d00000bb40010009c000005790000213d00000000020a0433000000c003100039000000400030043f000000a00310003900000000002304350000008002100039000000000072043500000060021000390000001a03000029000000000032043500000040021000390000001b03000029000000000032043500000020021000390000001c0300002900000000003204350000000000510435000001200200043d0000001e03000029000000000032004b00001d6c0000a13d0000001d0200002900000140022000390000000000120435000001200100043d000000000031004b00001d6c0000a13d0000000103300039000000190030006c000007800000413d000000400100043d000001f40000013d0000001d0200002900000b860020009c00000b8602008041000000400220021000000b860010009c00000b8601008041000000c001100210000000000121019f00000b8a011001c700000020020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000001d05700029000009620000613d000000000801034f0000001d09000029000000008a08043c0000000009a90436000000000059004b0000095e0000c13d000000000006004b0000096f0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000009d90000613d0000001f01400039000000600210018f0000001d01200029000000000021004b0000000002000039000000010200403900000ba70010009c000005790000213d0000000100200190000005790000c13d000000400010043f000000200030008c000006070000413d0000001d02000029000000000202043300000baa0020009c000006070000213d0000001f04000029000000000604043300000ba70060009c000005790000213d00000005046002100000003f0540003900000ba805500197000000000515001900000ba70050009c000005790000213d000000400050043f0000000005610436000000000006004b000009a00000613d0000000006000019000000400700043d00000bc20070009c000005790000213d0000004008700039000000400080043f000000200870003900000000000804350000000000070435000000000865001900000000007804350000002006600039000000000046004b000009930000413d000000400400043d001400000004001d00000bc30040009c000005790000213d00000014050000290000006004500039000000400040043f0000004004500039001700000004001d000000000014043500000020010000290000000001150436001300000001001d00000000000104350000001f010000290000000001010433000000000001004b001c00000000001d000013fd0000c13d00000013040000290000001c0100002900000000001404350000002002000039000000400100043d00000000022104360000001403000029000000000303043300000baa03300197000000000032043500000000020404330000004003100039000000000023043500000017020000290000000002020433000000600310003900000060040000390000000000430435000000800310003900000000040204330000000000430435000000a003100039000000000004004b000009d70000613d000000000500001900000020022000390000000006020433000000007606043400000baa0660019700000000066304360000000007070433000000000076043500000040033000390000000105500039000000000045004b000009cc0000413d0000000002130049000002190000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000009e00000c13d000006630000013d0000000108000029000000006906043400000ba70090009c000006070000213d0000000009190019000000200c900039000000000ac2004900000bad00a0009c000006070000213d000000a000a0008c000006070000413d000000400a00043d00000be200a0009c000005790000213d000000a00ba000390000004000b0043f000000000d0c043300000ba700d0009c000006070000213d000000000ccd00190000001f0dc0003900000000002d004b000000000e00001900000bae0e00804100000bae0dd00197000000000f4d013f00000000004d004b000000000d00001900000bae0d00404100000bae00f0009c000000000d0ec01900000000000d004b000006070000c13d00000000dc0c043400000ba700c0009c000005790000213d0000001f0ec0003900000bff0ee001970000003f0ee0003900000bff0ee00197000000000ebe001900000ba700e0009c000005790000213d0000004000e0043f0000000000cb0435000000000edc001900000000002e004b000006070000213d000000c00ea0003900000000000c004b00000a200000613d000000000f0000190000000003ef00190000000005df001900000000050504330000000000530435000000200ff000390000000000cf004b00000a190000413d0000000003ec00190000000000030435000000000bba04360000004003900039000000000c03043300000baa00c0009c000006070000213d0000000000cb04350000006003900039000000000b03043300000baa00b0009c000006070000213d0000004003a000390000000000b30435000000800390003900000000030304330000006005a000390000000000350435000000a00390003900000000030304330000008005a0003900000000003504350000000008a80436000000000076004b000009e60000413d00000007010000290000000001010433000200000001001d00000ba70010009c0000052f0000a13d000005790000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900000a4a0000613d000000000709034f0000000008020019000000007107043c0000000008180436000000000048004b00000a460000c13d000000000005004b000006700000613d000000000169034f000006660000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000a550000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000a610000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000a6d0000c13d000006630000013d000000600e00003900000000040000190000001b0d000029000000400500043d00000bea0050009c000005790000213d000001a001500039000000400010043f00000180015000390000000000e10435000000e0015000390000000000e10435000000c0015000390000000000e10435000000a0015000390000000000e104350000000001e504360000016003500039000000000003043500000140035000390000000000030435000001200350003900000000000304350000010003500039000000000003043500000080035000390000000000030435000000600350003900000000000304350000004003500039000000000003043500000000000104350000000001d4001900000000005104350000002004400039000000000024004b00000a750000413d000000000200001900000007010000290000000001010433000800000002001d000000000021004b00001d6c0000a13d000000400200043d00000bea0020009c000005790000213d0005002d0000002d00000008010000290000000503100210000300000003001d00000001013000290000000004010433000001a001200039000000400010043f00000180012000390000000000e10435000000e0012000390000000000e10435000000c0012000390000000000e10435000000a0012000390000000000e104350000000001e20436000001600320003900000000000304350000014003200039000000000003043500000120032000390000000000030435000001000320003900000000000304350000008003200039000000000003043500000060032000390000000000030435000000400220003900000000000204350000000000010435000400000004001d0000004001400039000600000001001d0000000001010433000000400900043d00000bbc020000410000000000290435000000000400041400000baa02100197000000040020008c00000ae10000613d00000b860090009c001d00000009001d00000b86010000410000000001094019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c72e152e100000040f0000000003010019000000600330027000000b860030019d001f0b860030019b001e0000000103530002000000010355000000010020019000001e510000613d0000001b0d000029000000600e0000390000001d090000290000001f0800002900000bff0480019800000000024900190000001e0300035f00000aec0000613d000000000503034f0000000006090019000000005105043c0000000006160436000000000026004b00000ae80000c13d0000001f0580019000000af90000613d000000000143034f0000000303500210000000000402043300000000043401cf000000000434022f000000000101043b0000010003300089000000000131022f00000000013101cf000000000141019f00000000001204350000001f0180003900000bff0110019700000000030900190000000002910019000000000012004b00000000010000390000000101004039000b00000002001d00000ba70020009c000005790000213d0000000100100190000005790000c13d0000000b01000029000000400010043f0000001f0100002900000bad0010009c000006070000213d0000001f01000029000000200010008c000006070000413d000000000103043300000ba70010009c000006070000213d00000000040300190000001f0340002900000000014100190000001f02100039000000000032004b000000000400001900000bae0400804100000bae0220019700000bae05300197000000000652013f000000000052004b000000000200001900000bae0200404100000bae0060009c000000000204c019000000000002004b000006070000c13d0000000021010434000a00000001001d00000ba70010009c000005790000213d0000000a0100002900000005011002100000003f0410003900000ba8054001970000000b0450002900000ba70040009c000005790000213d000000400040043f0000000b040000290000000a060000290000000004640436000900000004001d0000000004210019000000000034004b000006070000213d000000000042004b00000b470000813d0000000b01000029000000002302043400000baa0030009c000006070000213d00000020011000390000000000310435000000000042004b00000b370000413d0000000b010000290000000001010433000a00000001001d00000ba70010009c000005790000213d0000000a0100002900000005011002100000003f0210003900000ba805200197000000400300043d0000000002530019001800000003001d000000000032004b0000000003000039000000010300403900000ba70020009c000005790000213d0000000100300190000005790000c13d000000400020043f00000018020000290000000a030000290000000002320436001700000002001d000000000003004b000010770000613d0000000002000019000000400300043d00000beb0030009c000005790000213d0000022004300039000000400040043f00000200043000390000000000040435000001e0043000390000000000040435000001c0043000390000000000040435000001a00430003900000000000404350000018004300039000000000004043500000160043000390000000000040435000001400430003900000000000404350000012004300039000000000004043500000100043000390000000000040435000000e0043000390000000000040435000000c0043000390000000000040435000000a0043000390000000000040435000000800430003900000000000404350000006004300039000000000004043500000040043000390000000000040435000000200430003900000000000404350000000000030435000000170420002900000000003404350000002002200039000000000012004b00000b590000413d00000000030000190000000b010000290000000001010433000000000031004b00001d6c0000a13d001a00000003001d000000400100043d00000beb0010009c000005790000213d0000001a02000029000000050320021000000009023000290000000002020433001f0baa0020019b0000022002100039000000400020043f00000200021000390000000000020435000001e0021000390000000000020435000001c0021000390000000000020435000001a00210003900000000000204350000018002100039000000000002043500000160021000390000000000020435000001400210003900000000000204350000012002100039000000000002043500000100021000390000000000020435000000e0021000390000000000020435000000c0021000390000000000020435000000a002100039000000000002043500000080021000390000000000020435000000600210003900000000000204350000004002100039000000000002043500000020021000390000000000020435000000000001043500000baa01000041000001000010043f000000400a00043d00000bec0100004100000000001a0435000001000100043d0000001f0210017f0000000001000414000000040020008c001600000003001d00000bc50000c13d0000000003000031000000200030008c0000002004000039000000000403401900000bf30000013d00000b8600a0009c00000b860300004100000000030a4019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000b8a011001c7001e0000000a001d2e152e100000040f0000001e0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000be00000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000bdc0000c13d0000001f0740019000000bed0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001d900000613d0000001f01400039000000600110018f00000000050a00190000000004a10019000000000014004b00000000020000390000000102004039001e00000004001d00000ba70040009c000005790000213d0000000100200190000005790000c13d0000001e02000029000000400020043f000000200030008c000006070000413d0000000002050433001500000002001d00000bed020000410000001e0a00002900000000002a0435000001000200043d0000001f0220017f0000000004000414000000040020008c00000c3c0000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c72e152e100000040f0000001e0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000c270000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000c230000c13d0000001f0740019000000c340000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001d9c0000613d0000001f01400039000000600110018f0000000001a10019001d00000001001d00000ba70010009c000005790000213d0000001d01000029000000400010043f000000200030008c000006070000413d0000001e010000290000000001010433001e00000001001d00000baa0010009c000006070000213d00000bee010000410000001d0a00002900000000041a0436000001000100043d0000001f0110017f0000000402a000390000000000120435000001000100043d0000001e0210017f0000000001000414000000040020008c001900000004001d00000c5a0000c13d000000400030008c0000004004000039000000000403401900000c870000013d00000b8600a0009c00000b860300004100000000030a4019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000bb6011001c72e152e100000040f0000001d0a0000290000000003010019000000600330027000000b8603300197000000400030008c00000040040000390000000004034019000000600640019000000000056a001900000c740000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000c700000c13d0000001f0740019000000c810000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001da80000613d0000001f01400039000000e00110018f0000000001a10019001c00000001001d00000ba70010009c000005790000213d0000001c01000029000000400010043f000000400030008c000006070000413d0000001d010000290000000002010433000000000002004b0000000001000039000000010100c039001400000002001d000000000012004b000006070000c13d00000019010000290000000001010433001300000001001d00000bb9010000410000001c0a00002900000000001a0435000001000100043d0000001f0210017f0000000001000414000000040020008c000000200400003900000cd20000613d00000b8600a0009c00000b860300004100000000030a4019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000b8a011001c72e152e100000040f0000001c0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000cbf0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000cbb0000c13d0000001f0740019000000ccc0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001db40000613d0000001f01400039000000600110018f0000000002a10019001d00000002001d00000ba70020009c000005790000213d0000001d02000029000000400020043f000000200030008c000006070000413d0000001c020000290000000002020433001900000002001d00000baa0020009c000006070000213d00000bef020000410000001d0a00002900000000002a0435000001000200043d000000190220017f0000000004000414000000040020008c00000d180000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c72e152e100000040f0000001d0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000d030000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000cff0000c13d0000001f0740019000000d100000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001dc00000613d0000001f01400039000000600110018f000000000aa10019000000c00000043f00000ba700a0009c000005790000213d0000004000a0043f000000200030008c000006070000413d0000001d010000290000000001010433000000ff0010008c000006070000213d000000c00010043f000000e00000043f000000000500001900000bf00100004100000000001a04350000002401a00039000001000200043d00000000005104350000001f0120017f0000000402a000390000000000120435000001000100043d0000001e0210017f0000000001000414000000040020008c000000200400003900000d640000613d001c00000005001d00000b8600a0009c00000b860300004100000000030a4019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000bbb011001c7001d0000000a001d2e152e100000040f0000001d0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000d500000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000d4c0000c13d0000001f0740019000000d5d0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e000039000014d30000613d0000001c050000290000001f01400039000000600110018f000000000ba1001900000000001b004b0000000002000039000000010200403900000ba700b0009c000005790000213d0000000100200190000005790000c13d0000004000b0043f000000200030008c000006070000413d00000000020a0433000000000002004b0000000004000039000000010400c039000000000042004b000006070000c13d00000000025201cf000000e00400043d000000000224019f000000e00020043f0000000102500039000000ff0520018f000000080050008c000000000a0b001900000d260000a13d00000bf10200004100000000002b0435000001000200043d0000001f0220017f0000000004000414000000040020008c00000db70000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c7001d0000000b001d2e152e100000040f0000001d0b0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056b001900000da20000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b00000d9e0000c13d0000001f0740019000000daf0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001dcc0000613d0000001f01400039000000600110018f0000000002b10019001d00000002001d00000ba70020009c000005790000213d0000001d02000029000000400020043f000000200030008c000006070000413d00000000020b0433001200000002001d00000bf2020000410000001d0a00002900000000002a0435000001000200043d0000001f0220017f0000000004000414000000040020008c00000df80000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c72e152e100000040f0000001d0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000de30000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000ddf0000c13d0000001f0740019000000df00000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001dd80000613d0000001f01400039000000600110018f0000000002a10019001c00000002001d00000ba70020009c000005790000213d0000001c02000029000000400020043f000000200030008c000006070000413d0000001d020000290000000002020433001100000002001d00000bf3020000410000001c0a00002900000000002a0435000001000200043d0000001f0220017f0000000004000414000000040020008c00000e3a0000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c72e152e100000040f0000001c0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000e250000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000e210000c13d0000001f0740019000000e320000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001de40000613d0000001f01400039000000600110018f0000000002a10019001d00000002001d00000ba70020009c000005790000213d0000001d02000029000000400020043f000000200030008c000006070000413d0000001c020000290000000002020433001000000002001d00000bf4020000410000001d0a00002900000000002a0435000001000200043d0000001f0220017f0000000404a000390000000000240435000001000200043d0000001e0220017f0000000004000414000000040020008c00000e800000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000bb6011001c72e152e100000040f0000001d0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000e6b0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000e670000c13d0000001f0740019000000e780000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001df00000613d0000001f01400039000000600110018f0000000002a10019001c00000002001d00000ba70020009c000005790000213d0000001c02000029000000400020043f000000200030008c000006070000413d0000001d020000290000000002020433000f00000002001d00000bf5020000410000001c0a00002900000000002a0435000001000200043d0000001f0220017f0000000404a000390000000000240435000001000200043d0000001e0220017f0000000004000414000000040020008c00000ec60000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000bb6011001c72e152e100000040f0000001c0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000eb10000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000ead0000c13d0000001f0740019000000ebe0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001dfc0000613d0000001f01400039000000600110018f0000000002a10019001e00000002001d00000ba70020009c000005790000213d0000001e02000029000000400020043f000000200030008c000006070000413d0000001c020000290000000002020433001c00000002001d00000bd0020000410000001e0a00002900000000002a0435000001000200043d0000001f0220017f0000000004000414000000040020008c00000f080000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c72e152e100000040f0000001e0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000ef30000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000eef0000c13d0000001f0740019000000f000000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001e080000613d0000001f01400039000000600110018f0000000002a10019001d00000002001d00000ba70020009c000005790000213d0000001d02000029000000400020043f000000200030008c000006070000413d0000001e020000290000000002020433000e00000002001d00000bf6020000410000001d0a00002900000000002a0435000001000200043d0000001f0220017f0000000004000414000000040020008c00000f4a0000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c72e152e100000040f0000001d0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000f350000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000f310000c13d0000001f0740019000000f420000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001e140000613d0000001f01400039000000600110018f0000000002a10019001e00000002001d00000ba70020009c000005790000213d0000001e02000029000000400020043f000000200030008c000006070000413d0000001d020000290000000002020433000d00000002001d00000bd7020000410000001e0a00002900000000002a0435000001000200043d0000001f0220017f0000000004000414000000040020008c00000f8c0000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c72e152e100000040f0000001e0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000f770000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000f730000c13d0000001f0740019000000f840000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001e200000613d0000001f01400039000000600110018f0000000002a10019001d00000002001d00000ba70020009c000005790000213d0000001d02000029000000400020043f000000200030008c000006070000413d0000001e020000290000000002020433000c00000002001d00000bf7020000410000001d0a00002900000000002a0435000001000200043d0000001f0220017f0000000004000414000000040020008c00000fce0000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c72e152e100000040f0000001d0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000fb90000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000fb50000c13d0000001f0740019000000fc60000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001e2c0000613d0000001f01400039000000600110018f0000000002a10019001e00000002001d00000ba70020009c000005790000213d0000001e02000029000000400020043f000000200030008c000006070000413d0000001d020000290000000002020433001d00000002001d00000bef020000410000001e0a00002900000000002a0435000001000200043d0000001f0220017f0000000004000414000000040020008c000010100000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c72e152e100000040f0000001e0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000ffb0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000ff70000c13d0000001f07400190000010080000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001b0d000029000000600e00003900001e380000613d0000001f01400039000000600110018f0000000001a10019000000800000043f00000ba70010009c000005790000213d000000400010043f000000200030008c000006070000413d0000001e020000290000000002020433000000ff0020008c000006070000213d000000800020043f000000a00010043f00000beb0010009c000005790000213d0000022002100039000000400020043f000001000200043d0000001f0220017f0000000000210435000000a00100043d000000200110003900000015020000290000000000210435000000a00100043d000000400110003900000012020000290000000000210435000000a00100043d000000600110003900000011020000290000000000210435000000a00100043d000000800110003900000010020000290000000000210435000000a00100043d000000a0011000390000000f020000290000000000210435000000a00100043d000000c0011000390000001c020000290000000000210435000000a00100043d000000e0011000390000000e020000290000000000210435000000a00100043d00000100011000390000000d020000290000000000210435000000a00100043d00000120011000390000000c020000290000000000210435000000a00100043d00000140011000390000001d020000290000000000210435000000a00100043d000001600110003900000014020000290000000000210435000000a00100043d000001800110003900000013020000290000000000210435000001000100043d000000190110017f000000a00200043d000001a0022000390000000000120435000000800100043d000000ff0110018f000000a00200043d000001c0022000390000000000120435000000c00100043d000000ff0110018f000000a00200043d000001e0022000390000000000120435000000a00100043d0000020001100039000000e00200043d0000000000210435000000180100002900000000010104330000001a03000029000000000031004b00001d6c0000a13d00000016020000290000001701200029000000a00200043d000000000021043500000018010000290000000001010433000000000031004b00001d6c0000a13d00000001033000390000000a0030006c00000b850000413d00000006010000290000000001010433000000400900043d00000bf802000041000000000029043500000baa01100197000000040290003900000000001204350000000001000414000000050200002900000baa02200197000000040020008c000010880000c13d00000002010003670000000008000031000000200700008a0000109e0000013d00000b860090009c001f00000009001d00000b86030000410000000003094019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000bb6011001c72e152e100000040f0000000003010019000000600330027000000b860030019d00000b86083001970002000000010355000000010020019000001e5e0000613d000000200700008a0000001b0d000029000000600e0000390000001f0900002900000000047801700000000002490019000010a70000613d000000000501034f0000000006090019000000005305043c0000000006360436000000000026004b000010a30000c13d0000001f05800190000010b40000613d000000000641034f0000000303500210000000000402043300000000043401cf000000000434022f000000000506043b0000010003300089000000000535022f00000000033501cf000000000343019f0000000000320435001e000000010353001f00000008001d0000001f01800039000000000171016f00000000030900190000000002910019000000000012004b0000000004000039000000010400403900000ba70020009c000005790000213d0000000100400190000005790000c13d000000400020043f0000001f0100002900000bad0010009c000006070000213d0000001f01000029000000200010008c000006070000413d000000000503043300000ba70050009c000006070000213d0000001f043000290000000005350019000000000654004900000bad0060009c000006070000213d000000600060008c000006070000413d00000bc30020009c000005790000213d0000006006200039000000400060043f000000008705043400000ba70070009c000006070000213d00000000095700190000001f01900039000000000041004b000000000300001900000bae0300804100000bae0110019700000bae07400197000000000a71013f000000000071004b000000000100001900000bae0100404100000bae00a0009c000000000103c019000000000001004b000006070000c13d00000000a909043400000ba70090009c000005790000213d0000001f0190003900000bff011001970000003f0110003900000bff01100197000000000b61001900000ba700b0009c000005790000213d0000004000b0043f00000000009604350000000001a90019000000000041004b000006070000213d000000800b200039000000000009004b000011020000613d000000000c0000190000000001bc00190000000003ac001900000000030304330000000000310435000000200cc0003900000000009c004b000010fb0000413d0000000001b9001900000000000104350000000006620436000000000808043300000ba70080009c000006070000213d00000000085800190000001f01800039000000000041004b000000000300001900000bae0300804100000bae01100197000000000971013f000000000071004b000000000100001900000bae0100404100000bae0090009c000000000103c019000000000001004b000006070000c13d000000009808043400000ba70080009c000005790000213d0000001f0180003900000bff011001970000003f0110003900000bff01100197000000400a00043d000000000b1a00190000000000ab004b000000000c000039000000010c00403900000ba700b0009c000005790000213d0000000100c00190000005790000c13d0000004000b0043f000000000b8a04360000000001980019000000000041004b000006070000213d000000000008004b000011350000613d000000000c0000190000000001bc001900000000039c001900000000030304330000000000310435000000200cc0003900000000008c004b0000112e0000413d00000000018b001900000000000104350000000000a604350000004001500039000000000801043300000ba70080009c000006070000213d00000000055800190000001f01500039000000000041004b000000000300001900000bae0300804100000bae01100197000000000871013f000000000071004b000000000100001900000bae0100404100000bae0080009c000000000103c019000000000001004b000006070000c13d000000007505043400000ba70050009c000005790000213d0000001f0150003900000bff011001970000003f0110003900000bff01100197000000400300043d0000000008130019001900000003001d000000000038004b0000000009000039000000010900403900000ba70080009c000005790000213d0000000100900190000005790000c13d000000400080043f000000190100002900000000085104360000000001750019000000000041004b000006070000213d000000000005004b0000116b0000613d000000000400001900000000018400190000000003740019000000000303043300000000003104350000002004400039000000000054004b000011640000413d000000000158001900000000000104350000004001200039000000190300002900000000003104350000000001020433001500000001001d0000000001060433001200000001001d000000040200002900000080012000390000000001010433001300000001001d00000060012000390000000001010433001400000001001d00000020012000390000000001010433001600000001001d0000000001020433001700000001001d00000006010000290000000001010433000000400300043d00000be502000041001a00000003001d0000000000230435000000000200041400000baa01100197001d00000001001d000000040010008c000011900000c13d0000001f01000029000000200010008c00000020040000390000000004014019000011bf0000013d0000001a0100002900000b860010009c00000b8601008041000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c70000001d020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c001f00000003001d0000002004000039000000000403401900000020064001900000001a05600029000011ab0000613d000000000701034f0000001a08000029000000007307043c0000000008380436000000000058004b000011a70000c13d0000001f07400190000011b80000613d000000000861034f0000000303700210000000000605043300000000063601cf000000000636022f000000000708043b0000010003300089000000000737022f00000000033701cf000000000363019f00000000003504350000001f0000002f001e0000000103530002000000010355000000010020019000001e7a0000613d0000001b0d000029000000600e0000390000001f01400039000000600210018f0000001a01200029000000000021004b00000000040000390000000104004039001c00000001001d00000ba70010009c000005790000213d0000000100400190000005790000c13d0000001c01000029000000400010043f0000001f01000029000000200010008c000006070000413d0000001a010000290000000001010433001100000001001d00000baa0010009c000006070000213d00000bf9010000410000001c03000029000000000013043500000000040004140000001d01000029000000040010008c0000120d0000613d00000b860030009c00000b86010000410000000001034019000000400110021000000b860040009c00000b8604008041000000c002400210000000000112019f00000b8a011001c70000001d020000292e152e100000040f0000001c080000290000000003010019000000600330027000000b8603300197000000200030008c001f00000003001d0000002004000039000000000403401900000020064001900000000005680019000011f60000613d000000000701034f000000007307043c0000000008380436000000000058004b000011f20000c13d0000001f07400190000012030000613d000000000861034f0000000303700210000000000605043300000000063601cf000000000636022f000000000708043b0000010003300089000000000737022f00000000033701cf000000000363019f00000000003504350000001f0000002f001e0000000103530002000000010355000000010020019000001e870000613d0000001f01400039000000600210018f0000001b0d000029000000600e0000390000001c030000290000000001320019001a00000001001d00000ba70010009c000005790000213d0000001a01000029000000400010043f0000001f01000029000000200010008c000006070000413d0000001c010000290000000001010433001000000001001d00000bfa010000410000001a03000029000000000013043500000000040004140000001d01000029000000040010008c000012520000613d00000b860030009c00000b86010000410000000001034019000000400110021000000b860040009c00000b8604008041000000c002400210000000000112019f00000b8a011001c70000001d020000292e152e100000040f0000001a080000290000000003010019000000600330027000000b8603300197000000200030008c001f00000003001d00000020040000390000000004034019000000200640019000000000056800190000123b0000613d000000000701034f000000007307043c0000000008380436000000000058004b000012370000c13d0000001f07400190000012480000613d000000000861034f0000000303700210000000000605043300000000063601cf000000000636022f000000000708043b0000010003300089000000000737022f00000000033701cf000000000363019f00000000003504350000001f0000002f001e0000000103530002000000010355000000010020019000001e940000613d0000001f01400039000000600210018f0000001b0d000029000000600e0000390000001a030000290000000001320019001c00000001001d00000ba70010009c000005790000213d0000001c01000029000000400010043f0000001f01000029000000200010008c000006070000413d0000001a010000290000000001010433001a00000001001d00000bfb010000410000001c03000029000000000013043500000000040004140000001d01000029000000040010008c000012970000613d00000b860030009c00000b86010000410000000001034019000000400110021000000b860040009c00000b8604008041000000c002400210000000000112019f00000b8a011001c70000001d020000292e152e100000040f0000001c080000290000000003010019000000600330027000000b8603300197000000200030008c001f00000003001d0000002004000039000000000403401900000020064001900000000005680019000012800000613d000000000701034f000000007307043c0000000008380436000000000058004b0000127c0000c13d0000001f074001900000128d0000613d000000000861034f0000000303700210000000000605043300000000063601cf000000000636022f000000000708043b0000010003300089000000000737022f00000000033701cf000000000363019f00000000003504350000001f0000002f001e0000000103530002000000010355000000010020019000001ea10000613d0000001f01400039000000600210018f0000001b0d000029000000600e0000390000001c03000029000000000232001900000ba70020009c000005790000213d000000400020043f0000001f01000029000000200010008c000006070000413d00000bea0020009c000005790000213d0000001c010000290000000001010433000001a003200039000000400030043f0000018003200039000000180400002900000000004304350000016003200039000000000013043500000140012000390000001a030000290000000000310435000001200120003900000010030000290000000000310435000001000120003900000011030000290000000000310435000000e00120003900000019030000290000000000310435000000c00120003900000012030000290000000000310435000000a0012000390000001503000029000000000031043500000080012000390000001303000029000000000031043500000060012000390000001403000029000000000031043500000040012000390000001d030000290000000000310435000000160100002900000baa01100197000000200320003900000000001304350000001701000029000000000012043500000020010000290000000001010433000000080010006c00001d6c0000a13d0000000301d00029000000000021043500000020010000290000000001010433000000080010006c00001d6c0000a13d00000008020000290000000102200039000000020020006c00000a980000413d0000002e02000029000005450000013d0000000007000019000012e00000013d00000000042400190000000107700039000000000037004b000005500000813d0000000008150049000000400880008a00000000008404350000002006200029002000000006001d000000000806043300000000c9080434000001a006000039000000000b65043600000000d9090434000001a00a50003900000000009a0435000001c00a500039000000000009004b000012f70000613d000000000e000019000000000fae00190000000006ed0019000000000606043300000000006f0435000000200ee0003900000000009e004b000012f00000413d0000000006a90019000000000006043500000000060c043300000baa0660019700000000006b04350000004006800039000000000606043300000baa06600197000000400b50003900000000006b043500000060068000390000000006060433000000600b50003900000000006b043500000080068000390000000006060433000000800b50003900000000006b04350000001f0690003900000bff066001970000000006a600190000000009560049000000a00a500039000000a00b800039000000000b0b043300000000009a043500000000ba0b04340000000009a6043600000000000a004b0000131d0000613d000000000c00001900000000069c0019000000000dcb0019000000000d0d04330000000000d60435000000200cc000390000000000ac004b000013160000413d00000000069a001900000000000604350000001f06a0003900000bff066001970000000006960019000000c0098000390000000009090433000000000a560049000000c00b5000390000000000ab043500000000ba0904340000000009a6043600000000000a004b000013330000613d000000000c00001900000000069c0019000000000dcb0019000000000d0d04330000000000d60435000000200cc000390000000000ac004b0000132c0000413d00000000069a001900000000000604350000001f06a0003900000bff066001970000000006960019000000e0098000390000000009090433000000000a560049000000e00b5000390000000000ab043500000000ba0904340000000009a6043600000000000a004b000013490000613d000000000c00001900000000069c0019000000000dcb0019000000000d0d04330000000000d60435000000200cc000390000000000ac004b000013420000413d00000000069a001900000000000604350000010006800039000000000606043300000baa06600197000001000b50003900000000006b043500000120068000390000000006060433000001200b50003900000000006b043500000140068000390000000006060433000001400b50003900000000006b043500000160068000390000000006060433000001600b50003900000000006b04350000001f06a0003900000bff0660019700000000069600190000000009560049000001800550003900000180088000390000000008080433000000000095043500000000090804330000000005960436000000000009004b000012dc0000613d000000000a0000190000002008800039000000000b08043300000000c60b043400000baa066001970000000006650436000000000c0c04330000000000c604350000004006b000390000000006060433000000400c50003900000000006c04350000006006b000390000000006060433000000600c50003900000000006c04350000008006b000390000000006060433000000800c50003900000000006c0435000000a006b000390000000006060433000000a00c50003900000000006c0435000000c006b000390000000006060433000000c00c50003900000000006c0435000000e006b000390000000006060433000000e00c50003900000000006c04350000010006b000390000000006060433000001000c50003900000000006c04350000012006b000390000000006060433000001200c50003900000000006c04350000014006b000390000000006060433000001400c50003900000000006c04350000016006b000390000000006060433000000000006004b0000000006000039000000010600c039000001600c50003900000000006c04350000018006b000390000000006060433000001800c50003900000000006c0435000001a006b00039000000000606043300000baa06600197000001a00c50003900000000006c0435000001c006b000390000000006060433000001c00c50003900000000006c0435000001e006b000390000000006060433000001e00c50003900000000006c04350000020006b000390000000006060433000002000b50003900000000006b04350000022005500039000000010aa0003900000000009a004b000013690000413d000012dc0000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000013bc0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000013c80000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000013d40000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000013e00000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000013ec0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000013f80000c13d000006630000013d00150baa0020019b0000001e01000029001601a00010003d001d00000000001d001c00000000001d000000400100043d001e00000001001d00000bc20010009c000005790000213d0000001e020000290000004001200039000000400010043f0000000001020436001b00000001001d00000000000104350000001f0100002900000000010104330000001d02000029000000000021004b00001d6c0000a13d0000000504200210001900000004001d0000001605400029000000000105043300000baa011001970000001e0400002900000000001404350000001f010000290000000001010433000000000021004b00001d6c0000a13d0000000002050433000000400a00043d00000be60100004100000000001a0435000000000100041400000baa02200197000000040020008c001a00000005001d000014290000c13d000000200030008c00000020040000390000000004034019000014550000013d00000b8600a0009c00000b860300004100000000030a4019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000b8a011001c700200000000a001d2e152e100000040f000000200a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000014440000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000014400000c13d0000001f07400190000014510000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001d780000613d0000001f01400039000000600110018f00000000060a00190000000005a10019000000000015004b00000000020000390000000102004039002000000005001d00000ba70050009c000005790000213d0000000100200190000005790000c13d0000002002000029000000400020043f000000200040008c000006070000413d0000001f0200002900000000020204330000001d0020006c0000001a0200002900001d6c0000a13d0000000004060433001800000004001d000000000202043300000be70400004100000020050000290000000000450435000000040450003900000baa02200197000000000024043500000000040004140000001502000029000000040020008c0000147c0000c13d000000000115001900000ba70010009c000005790000213d000000400010043f000014af0000013d00000b860050009c00000b86010000410000000001054019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000bb6011001c72e152e100000040f000000200a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000014960000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000014920000c13d0000001f07400190000014a30000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001d840000613d0000001f01400039000000600110018f0000000001a1001900000ba70010009c000005790000213d000000400010043f000000200030008c000006070000413d00000020010000290000000002010433000000180400002900000000014200a9000000000004004b0000001d05000029000014b90000613d00000000044100d9000000000024004b00001d720000c13d00000bd10110012a0000001b020000290000000000120435000000170100002900000000010104330000000002010433000000000052004b00001d6c0000a13d000000190210002900000020022000390000001e0400002900000000004204350000000001010433000000000051004b00001d6c0000a13d0000001b0100002900000000010104330000001c0010002a00001d720000413d001c001c0010002d001d00010050003d0000001f0100002900000000010104330000001d0010006b000014020000413d000009b30000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000014da0000c13d000006630000013d0028001c0000002d000000400400043d002700000004001d001900000004001d0000000004460019000000000064004b0000000005000039000000010500403900000ba70040009c000005790000213d0000000100500190000005790000c13d000000400040043f00000019040000290000000004240436000000000002004b000015030000613d00000060020000390000000005000019000000400600043d00000bbf0060009c000005790000213d0000008007600039000000400070043f0000006007600039000000000027043500000040076000390000000000070435000000200760003900000000000704350000000000060435000000000754001900000000006704350000002005500039000000000015004b000014f20000413d002600000000003d0000001c010000290000000001010433000000000001004b000015400000c13d000000400100043d00000020020000390000000002210436000000190300002900000000030304330000000000320435000000400410003900000005023002100000000002420019000000000003004b000002180000613d00000080050000390000000006000019000000190c0000290000151a0000013d0000000106600039000000000036004b000002180000813d0000000007120049000000400770008a0000000004740436000000200cc0003900000000070c0433000000009807043400000baa088001970000000008820436000000000909043300000baa09900197000000000098043500000040087000390000000008080433000000400920003900000000008904350000006007700039000000000707043300000060082000390000000000580435000000800920003900000000080704330000000000890435000000a002200039000000000008004b000015170000613d00000000090000190000002007700039000000000a07043300000000ba0a043400000baa0aa00197000000000aa20436000000000b0b04330000000000ba043500000040022000390000000109900039000000000089004b000015340000413d000015170000013d001f00000000001d000000400100043d001d00000001001d00000bbf0010009c000005790000213d0000001d020000290000008001200039000000400010043f00000060042000390000006001000039001800000004001d00000000001404350000004001200039001600000001001d00000000000104350000002001200039001700000001001d00000000000104350000000000020435002500000002001d0000001c0100002900000000010104330000001f0010006c00001d6c0000a13d0000001f0400002900000005014002100000001c0200002900000000011200190000002001100039001a00000001001d000000000101043300000baa011001970000001d0500002900000000001504350000000001020433000000000041004b00001d6c0000a13d0000001a010000290000000002010433000000400400043d00000bc001000041001b00000004001d0000000000140435000000000100041400000baa02200197000000040020008c000015730000c13d000000200030008c000000200400003900000000040340190000159d0000013d0000001b0300002900000b860030009c00000b8603008041000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000b8a011001c72e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000001b056000290000158c0000613d000000000701034f0000001b08000029000000007907043c0000000008980436000000000058004b000015880000c13d0000001f07400190000015990000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f9c0000613d0000001f01400039000000600110018f0000001b02100029000000000012004b0000000004000039000000010400403900000ba70020009c000005790000213d0000000100400190000005790000c13d000000400020043f000000200030008c000006070000413d0000001b02000029000000000202043300000baa0020009c000006070000213d000000170400002900000000002404350000001c0200002900000000020204330000001f0020006c00001d6c0000a13d0000001a020000290000000002020433000000400500043d00000bc1040000410000000000450435000000200400002900000baa04400197001b00000005001d00000004055000390000000000450435000000000400041400000baa02200197000000040020008c000015ee0000613d0000001b0100002900000b860010009c00000b8601008041000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000bb6011001c72e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000001b05600029000015db0000613d000000000701034f0000001b08000029000000007907043c0000000008980436000000000058004b000015d70000c13d0000001f07400190000015e80000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001fa80000613d0000001f01400039000000600110018f0000001b02100029000000000012004b0000000001000039000000010100403900000ba70020009c000005790000213d0000000100100190000005790000c13d000000400020043f000000200030008c000006070000413d0000001b010000290000000001010433000000160200002900000000001204350000001c0100002900000000010104330000001f0010006c00001d6c0000a13d0000001e01000029000000000501043300000ba70050009c000005790000213d00000005015002100000003f0210003900000ba802200197000000400600043d0000000004260019001300000006001d000000000064004b0000000002000039000000010200403900000ba70040009c000005790000213d0000000100200190000005790000c13d0000001a020000290000000002020433000000400040043f00000013040000290000000004540436000000000005004b000016270000613d0000000005000019000000400600043d00000bc20060009c000005790000213d0000004007600039000000400070043f000000200760003900000000000704350000000000060435000000000754001900000000006704350000002005500039000000000015004b0000161a0000413d0000001e010000290000000001010433000000000001004b00001d510000613d001f0baa0020019b001d00000000001d000000400100043d002000000001001d00000bc30010009c000005790000213d00000020020000290000006001200039000000400010043f0000004001200039001600000001001d00000000000104350000000001020436001c00000001001d0000000000010435000000400100043d001a00000001001d00000bc30010009c000005790000213d0000001a020000290000006001200039000000400010043f0000004001200039001400000001001d00000000000104350000000001020436001700000001001d000000000001043500000ba50100004100000000001004430000000001000412000000040010044300000020010000390000002400100443000000000100041400000b860010009c00000b8601008041000000c00110021000000bc4011001c700008005020000392e152e100000040f000000010020019000001e440000613d000000000101043b000000000001004b0000001d020000290019000500200218000016750000613d0000001e010000290000000001010433000000000021004b00001d6c0000a13d00000019020000290000001e012000290000002001100039001500000001001d0000000001010433000000400300043d00000bc5020000410000000002230436001800000002001d00000baa01100197001b00000003001d0000000402300039000000000012043500000000010004140000001f02000029000000040020008c0000168f0000c13d0000000003000031000000600030008c00000060040000390000000004034019000016ba0000013d0000001e010000290000000001010433000000000021004b00001d6c0000a13d00000019020000290000001e012000290000002001100039001500000001001d0000000001010433000000400300043d00000bc8020000410000000002230436001800000002001d00000baa01100197001b00000003001d0000000402300039000000000012043500000000010004140000001f02000029000000040020008c0000172a0000c13d0000000003000031000000600030008c00000060040000390000000004034019000017550000013d0000001b0200002900000b860020009c00000b8602008041000000400220021000000b860010009c00000b8601008041000000c001100210000000000121019f00000bb6011001c70000001f020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000600030008c0000006004000039000000000403401900000060064001900000001b05600029000016a90000613d000000000701034f0000001b08000029000000007907043c0000000008980436000000000058004b000016a50000c13d0000001f07400190000016b60000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f240000613d0000001f01400039000000e00110018f0000001b02100029000000000012004b0000000004000039000000010400403900000ba70020009c000005790000213d0000000100400190000005790000c13d000000400020043f000000600030008c000006070000413d0000001b02000029000000000202043300000bc60020009c000006070000213d000000180400002900000000040404330000001b0500002900000040055000390000000005050433000000160600002900000000005604350000001c050000290000000000450435000000200400002900000000002404350000001e0200002900000000020204330000001d0020006c00001d6c0000a13d00000015020000290000000002020433000000400a00043d00000bc70400004100000000044a0436001b00000004001d00000baa022001970000000404a00039000000000024043500000000020004140000001f04000029000000040040008c000017160000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bb6011001c70000001f0200002900180000000a001d2e152e100000040f0000000003010019000000600330027000000b8603300197000000600030008c000000600400003900000000040340190000006006400190000000180a0000290000001805600029000017030000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000016ff0000c13d0000001f07400190000017100000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f300000613d0000001f01400039000000e00110018f00000000040a00190000000002a10019000000000012004b0000000001000039000000010100403900000ba70020009c000005790000213d0000000100100190000005790000c13d000000400020043f000000600030008c000006070000413d000000000104043300000bc60010009c000006070000213d0000001b02000029000000000202043300000040044000390000000004040433000017cc0000013d0000001b0200002900000b860020009c00000b8602008041000000400220021000000b860010009c00000b8601008041000000c001100210000000000121019f00000bb6011001c70000001f020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000600030008c0000006004000039000000000403401900000060064001900000001b05600029000017440000613d000000000701034f0000001b08000029000000007907043c0000000008980436000000000058004b000017400000c13d0000001f07400190000017510000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f3c0000613d0000001f01400039000000e00110018f0000001b02100029000000000012004b0000000004000039000000010400403900000ba70020009c000005790000213d0000000100400190000005790000c13d000000400020043f000000600030008c000006070000413d0000001b02000029000000000202043300000bc60020009c000006070000213d0000001804000029000000000404043300000b860040009c000006070000213d0000001b050000290000004005500039000000000505043300000b860050009c000006070000213d000000160600002900000000005604350000001c050000290000000000450435000000200400002900000000002404350000001e0200002900000000020204330000001d0020006c00001d6c0000a13d00000015020000290000000002020433000000400500043d00000bc9040000410000000004450436001800000004001d00000baa02200197001b00000005001d0000000404500039000000000024043500000000020004140000001f04000029000000040040008c000017b40000613d0000001b0100002900000b860010009c00000b8601008041000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bb6011001c70000001f020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000600030008c0000006004000039000000000403401900000060064001900000001b05600029000017a10000613d000000000701034f0000001b08000029000000007907043c0000000008980436000000000058004b0000179d0000c13d0000001f07400190000017ae0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f480000613d0000001f01400039000000e00110018f0000001b02100029000000000012004b0000000001000039000000010100403900000ba70020009c000005790000213d0000000100100190000005790000c13d000000400020043f000000600030008c000006070000413d0000001b01000029000000000101043300000bc60010009c000006070000213d0000001802000029000000000202043300000b860020009c000006070000213d0000001b040000290000004004400039000000000404043300000b860040009c000006070000213d00000014050000290000000000450435000000170400002900000000002404350000001a0200002900000000001204350000001e0100002900000000010104330000001d0010006c00001d6c0000a13d00000019020000290000001e012000290000002001100039001800000001001d0000000002010433000000400500043d00000bca010000410000000000150435000000000100041400000baa02200197000000040020008c0000002004000039001500000005001d0000180f0000613d00000b860050009c00000b86030000410000000003054019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000b8a011001c72e152e100000040f00000015080000290000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000000005680019000017fd0000613d000000000701034f000000007907043c0000000008980436000000000058004b000017f90000c13d0000001f074001900000180a0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001ed00000613d00000015050000290000001f01400039000000600110018f0000000004510019000000000014004b00000000020000390000000102004039001b00000004001d00000ba70040009c000005790000213d0000000100200190000005790000c13d0000001b02000029000000400020043f000000200030008c000006070000413d0000001b0200002900000bcb0020009c000005790000213d000000150200002900000000020204330000001b050000290000002004500039000000400040043f00000000002504350000001e0200002900000000020204330000001d0020006c00001d6c0000a13d00000018020000290000000002020433000000400500043d00000bcc04000041000000000045043500000baa042001970000000402500039001200000004001d000000000042043500000000020004140000001f04000029000000040040008c001500000005001d000018670000613d00000b860050009c00000b86010000410000000001054019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bb6011001c70000001f020000292e152e100000040f00000015080000290000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000000005680019000018530000613d000000000701034f000000007907043c0000000008980436000000000058004b0000184f0000c13d0000001f07400190000018600000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001edc0000613d0000001f01400039000000600110018f00000015050000290000000002510019000000000012004b0000000001000039000000010100403900000ba70020009c000005790000213d0000000100100190000005790000c13d000000400020043f000000200030008c000006070000413d00000015010000290000000001010433001500000001001d00000ba50100004100000000001004430000000001000412000000040010044300000040010000390000002400100443000000000100041400000b860010009c00000b8601008041000000c00110021000000bc4011001c700008005020000392e152e100000040f000000010020019000001e440000613d000000000101043b000000010010008c0000188d0000613d000000020010008c00001e4b0000c13d00000bcf0100004100000000001004430000000001000414000018900000013d00000bcd010000410000000000100443000000000100041400000b860010009c00000b8601008041000000c00110021000000bce011001c70000800b020000392e152e100000040f000000010020019000001e440000613d00000016020000290000000004020433000000000101043b000000000041004b00000000020000390000000102002039000000000004004b0000000003000039000000010300c039000000000023017000000000040160190000001c010000290000000001010433001600000004001d001000000014005300001d720000413d0000001d02000029000019470000613d000000150000006b000019440000613d000000400200043d00000bd001000041001100000002001d000000000012043500000000010004140000001202000029000000040020008c000018b90000c13d0000000003000031000000200030008c00000020040000390000000004034019000018e40000013d000000110200002900000b860020009c00000b8602008041000000400220021000000b860010009c00000b8601008041000000c001100210000000000121019f00000b8a011001c700000012020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000001105600029000018d30000613d000000000701034f0000001108000029000000007907043c0000000008980436000000000058004b000018cf0000c13d0000001f07400190000018e00000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f6c0000613d0000001f01400039000000600210018f0000001101200029000000000021004b0000000002000039000000010200403900000ba70010009c000005790000213d0000000100200190000005790000c13d000000400010043f000000200030008c000006070000413d0000001102000029000000000302043300000bd1023000d1000000000003004b000018f90000613d00000000033200d900000bd10030009c00001d720000c13d0000001b030000290000000003030433000000000003004b00001e450000613d000000100500002900000015045000b900000000055400d9000000150050006c00001d720000c13d000000000023004b000019080000a13d00000bcb0010009c0000000002000019000019180000a13d000005790000013d00000bcb0010009c000005790000213d0000002005100039000000400050043f000000000001043500000bd2054000d1000000000004004b000019130000613d00000000014500d900000bd20010009c00001d720000c13d000000400100043d00000bcb0010009c000005790000213d00000000023200d900000000022500d90000002003100039000000400030043f0000000000210435000000400200043d00000bcb0020009c000005790000213d000000200300002900000000030304330000002004200039000000400040043f00000bc6033001970000000000320435000000400300043d00000bcb0030009c000005790000213d0000002004300039000000400040043f000000000003043500000000020204330000000001010433000000000021001a00001d720000413d000000400300043d00000bcb0030009c000005790000213d00000000022100190000002001300039000000400010043f0000000000230435000000400100043d00000bc20010009c000005790000213d0000004003100039000000400030043f000000200310003900000bd30400004100000000004304350000001303000039000000000031043500000bd40020009c00001ebd0000813d000000200100002900000000002104350000001d020000290000001c01000029000000160300002900000000003104350000001e010000290000000001010433000000000021004b00001d6c0000a13d00000018010000290000000001010433000000400300043d00000bd602000041000000000023043500000baa02100197001c00000003001d0000000401300039001500000002001d000000000021043500000000010004140000001f02000029000000040020008c0000195e0000c13d0000000003000031000000200030008c00000020040000390000000004034019000019890000013d0000001c0200002900000b860020009c00000b8602008041000000400220021000000b860010009c00000b8601008041000000c001100210000000000121019f00000bb6011001c70000001f020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000001c05600029000019780000613d000000000701034f0000001c08000029000000007907043c0000000008980436000000000058004b000019740000c13d0000001f07400190000019850000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001ee80000613d0000001f01400039000000600210018f0000001c01200029000000000021004b0000000002000039000000010200403900000ba70010009c000005790000213d0000000100200190000005790000c13d000000400010043f000000200030008c000006070000413d0000001c010000290000000001010433001c00000001001d00000ba50100004100000000001004430000000001000412000000040010044300000040010000390000002400100443000000000100041400000b860010009c00000b8601008041000000c00110021000000bc4011001c700008005020000392e152e100000040f000000010020019000001e440000613d000000000101043b000000010010008c000019b10000613d000000020010008c00001e4b0000c13d00000bcf0100004100000000001004430000000001000414000019b40000013d00000bcd010000410000000000100443000000000100041400000b860010009c00000b8601008041000000c00110021000000bce011001c70000800b020000392e152e100000040f000000010020019000001e440000613d00000014020000290000000004020433000000000101043b000000000041004b00000000020000390000000102002039000000000004004b0000000003000039000000010300c0390000000000230170000000000401601900000017010000290000000001010433001600000004001d000000000114004b00001d720000413d0000001d0200002900001a610000613d001200000001001d0000001c0000006b00001a5e0000613d000000400200043d00000bd701000041001400000002001d000000000012043500000000010004140000001502000029000000040020008c000019de0000c13d0000000003000031000000200030008c0000002004000039000000000403401900001a090000013d000000140200002900000b860020009c00000b8602008041000000400220021000000b860010009c00000b8601008041000000c001100210000000000121019f00000b8a011001c700000015020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000001405600029000019f80000613d000000000701034f0000001408000029000000007907043c0000000008980436000000000058004b000019f40000c13d0000001f0740019000001a050000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f780000613d0000001f01400039000000600210018f0000001401200029000000000021004b0000000002000039000000010200403900000ba70010009c000005790000213d0000000100200190000005790000c13d000000400010043f000000200030008c000006070000413d00000012020000290000001c032000b900000000022300d90000001c0020006c00001d720000c13d00000014020000290000000002020433000000000002004b00001a2f0000613d00000bcb0010009c000005790000213d0000002004100039000000400040043f000000000001043500000bd2043000d1000000000003004b00001a2a0000613d00000000013400d900000bd20010009c00001d720000c13d000000400100043d00000bcb0010009c000005790000213d00000000022400d900001a320000013d00000bcb0010009c0000000002000019000005790000213d0000002003100039000000400030043f0000000000210435000000400200043d00000bcb0020009c000005790000213d0000001a0300002900000000030304330000002004200039000000400040043f00000bc6033001970000000000320435000000400300043d00000bcb0030009c000005790000213d0000002004300039000000400040043f000000000003043500000000020204330000000001010433000000000021001a00001d720000413d000000400300043d00000bcb0030009c000005790000213d00000000022100190000002001300039000000400010043f0000000000230435000000400100043d00000bc20010009c000005790000213d0000004003100039000000400030043f000000200310003900000bd30400004100000000004304350000001303000039000000000031043500000bd40020009c00001ebd0000813d0000001a0100002900000000002104350000001d020000290000001701000029000000160300002900000000003104350000001e010000290000000001010433000000000021004b00001d6c0000a13d000000400100043d001700000001001d00000bcb0010009c000005790000213d0000001801000029000000000101043300000baa031001970000002001000029000000000101043300000017040000290000002002400039000000400020043f00000bc6011001970000000000140435000000400400043d00000bd801000041000000000014043500000004014000390000002a02000029001600000003001d0000000000310435001c00000004001d0000002401400039002000000002001d00000baa02200197001800000002001d000000000021043500000000010004140000001f02000029000000040020008c00001a890000c13d0000000003000031000000200030008c0000002004000039000000000403401900001ab40000013d0000001c0200002900000b860020009c00000b8602008041000000400220021000000b860010009c00000b8601008041000000c001100210000000000121019f00000bbb011001c70000001f020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000001c0560002900001aa30000613d000000000701034f0000001c08000029000000007907043c0000000008980436000000000058004b00001a9f0000c13d0000001f0740019000001ab00000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001ef40000613d0000001f01400039000000600110018f0000001c04100029000000000014004b00000000020000390000000102004039001e00000004001d00000ba70040009c000005790000213d0000000100200190000005790000c13d0000001e02000029000000400020043f000000200030008c000006070000413d0000001e0200002900000bcb0020009c000005790000213d0000001c0200002900000000020204330000001e050000290000002004500039000000400040043f0000000000250435000000400a00043d000000000002004b00001b5d0000c13d00000017020000290000000002020433001500000002001d00000bd90200004100000000002a043500000000020004140000001f04000029000000040040008c00001b070000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c70000001f02000029001c0000000a001d2e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000001c0a0000290000001c0560002900001af40000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00001af00000c13d0000001f0740019000001b010000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f540000613d0000001f01400039000000600110018f00000000040a00190000000005a10019000000000015004b00000000020000390000000102004039001c00000005001d00000ba70050009c000005790000213d0000000100200190000005790000c13d0000001c02000029000000400020043f000000200030008c000006070000413d000000000204043300000bc60020009c000006070000213d000000150020006b00001b1c0000813d0000001c0a00002900001b5d0000013d00000bd9020000410000001c04000029000000000024043500000000020004140000001f04000029000000040040008c00001b500000613d0000001c0100002900000b860010009c00000b8601008041000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c70000001f020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000001c0560002900001b3d0000613d000000000701034f0000001c08000029000000007907043c0000000008980436000000000058004b00001b390000c13d0000001f0740019000001b4a0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f840000613d0000001f01400039000000600110018f0000001c0110002900000ba70010009c000005790000213d000000400010043f000000200030008c000006070000413d0000001c01000029000000000101043300000bc60010009c000006070000213d0000001e020000290000000000120435000000400a00043d00000000010a001900000bcb00a0009c000005790000213d00000000020100190000002001200039000000400010043f00000000000204350000001e01000029000000000101043300000017020000290000000002020433000000000112004b00001d720000413d000000400200043d001e00000002001d00000bcb0020009c000005790000213d0000001e040000290000002002400039000000400020043f0000000000140435000000400500043d00000bda01000041000000000015043500000004015000390000001802000029000000000021043500000000010004140000001602000029000000040020008c0000002004000039001700000005001d00001ba90000613d00000b860050009c00000b86030000410000000003054019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000bb6011001c72e152e100000040f00000017080000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000002006400190000000000568001900001b970000613d000000000701034f000000007907043c0000000008980436000000000058004b00001b930000c13d0000001f0740019000001ba40000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f000000613d00000017050000290000001f01400039000000600110018f0000000004510019000000000014004b00000000020000390000000102004039001c00000004001d00000ba70040009c000005790000213d0000000100200190000005790000c13d0000001c02000029000000400020043f000000200030008c000006070000413d0000001702000029000000000402043300000bd1024000d1000000000004004b00001bc00000613d00000000044200d900000bd10040009c00001d720000c13d0000001b040000290000000004040433000000000004004b00001e450000613d0000001e05000029000000000505043300000000064200d900170000006500ad000000000024004b00001bcd0000213d00000017026000f9000000000052004b00001d720000c13d0000002902000029001e00000002001d00000000020204330000001d0020006c00001d6c0000a13d0000001c0200002900000bcb0020009c000005790000213d00000019020000290000002004200039001500000004001d0000001e02400029001600000002001d000000000202043300000baa062001970000001a0200002900000000020204330000001c050000290000002004500039000000400040043f00000bc6022001970000000000250435000000400500043d00000024025000390000001804000029000000000042043500000bdb0200004100000000002504350000000402500039001900000006001d000000000062043500000000020004140000001f04000029000000040040008c001a00000005001d00001c1f0000613d00000b860050009c00000b86010000410000000001054019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bbb011001c70000001f020000292e152e100000040f0000001a080000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000002006400190000000000568001900001c0b0000613d000000000701034f000000007907043c0000000008980436000000000058004b00001c070000c13d0000001f0740019000001c180000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f0c0000613d0000001f01400039000000600110018f0000001a050000290000000004510019000000000014004b00000000020000390000000102004039001b00000004001d00000ba70040009c000005790000213d0000000100200190000005790000c13d0000001b02000029000000400020043f000000200030008c000006070000413d0000001b0200002900000bcb0020009c000005790000213d0000001a0200002900000000020204330000001b050000290000002004500039000000400040043f0000000000250435000000400a00043d000000000002004b00001cc60000c13d0000001c020000290000000002020433001400000002001d00000bd90200004100000000002a043500000000020004140000001f04000029000000040040008c00001c700000613d00000b8600a0009c00000b860100004100000000010a4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c70000001f02000029001a0000000a001d2e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000001a0a0000290000001a0560002900001c5d0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00001c590000c13d0000001f0740019000001c6a0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f600000613d0000001f01400039000000600110018f00000000040a00190000000005a10019000000000015004b00000000020000390000000102004039001a00000005001d00000ba70050009c000005790000213d0000000100200190000005790000c13d0000001a02000029000000400020043f000000200030008c000006070000413d000000000204043300000bc60020009c000006070000213d000000140020006b00001c850000813d0000001a0a00002900001cc60000013d00000bd9020000410000001a04000029000000000024043500000000020004140000001f04000029000000040040008c00001cb90000613d0000001a0100002900000b860010009c00000b8601008041000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c70000001f020000292e152e100000040f0000000003010019000000600330027000000b8603300197000000200030008c0000002004000039000000000403401900000020064001900000001a0560002900001ca60000613d000000000701034f0000001a08000029000000007907043c0000000008980436000000000058004b00001ca20000c13d0000001f0740019000001cb30000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f900000613d0000001f01400039000000600110018f0000001a0110002900000ba70010009c000005790000213d000000400010043f000000200030008c000006070000413d0000001a01000029000000000101043300000bc60010009c000006070000213d0000001b020000290000000000120435000000400a00043d00000000010a001900000bcb00a0009c000005790000213d00000000020100190000002001200039000000400010043f00000000000204350000001b0100002900000000010104330000001c020000290000000002020433000000000112004b00001d720000413d000000400200043d001c00000002001d00000bcb0020009c000005790000213d0000001c040000290000002002400039000000400020043f0000000000140435000000400500043d00000bb501000041000000000015043500000004015000390000001802000029000000000021043500000000010004140000001902000029000000040020008c0000002004000039001b00000005001d00001d120000613d00000b860050009c00000b86030000410000000003054019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000bb6011001c72e152e100000040f0000001b080000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000002006400190000000000568001900001d000000613d000000000701034f000000007907043c0000000008980436000000000058004b00001cfc0000c13d0000001f0740019000001d0d0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001f180000613d0000001b050000290000001f01400039000000600210018f0000000001520019000000000021004b0000000002000039000000010200403900000ba70010009c000005790000213d0000000100200190000005790000c13d000000400010043f000000200030008c000006070000413d0000001c0200002900000000040204330000001b02000029000000000502043300000000025400a9000000000005004b00001d290000613d00000000055200d9000000000045004b00001d720000c13d00000bc20010009c000005790000213d0000004004100039000000400040043f000000000401043600000000000404350000001e0500002900000000050504330000001d07000029000000000075004b00001d6c0000a13d000000170500002900000bd20550012a00000bd20220012a0000001606000029000000000606043300000baa0660019700000000006104350000000002520019000000000024043500000013020000290000000002020433000000000072004b00001d6c0000a13d0000001304000029000000150240002900000000001204350000000001040433000000000071004b00001d6c0000a13d001d00010070003d0000001e0100002900000000010104330000001d0010006b0000162d0000413d001900270000002d001f00260000002d0000002501000029001d00000001001d001800600010003d000000130100002900000018020000290000000000120435000000190100002900000000010104330000001f0010006c00001d6c0000a13d0000001f0400002900000005014002100000001902000029000000000112001900000020011000390000001d0500002900000000005104350000000001020433000000000041004b00001d6c0000a13d0000001f02000029002600010020003d00000001022000390000002801000029001c00000001001d0000000001010433001f00000002001d000000000012004b000015410000413d000015080000013d00000bdc01000041000000000010043f0000003201000039000000040010043f00000bb60100004100002e170001043000000bdc01000041000000000010043f0000001101000039000000040010043f00000bb60100004100002e17000104300000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001d7f0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001d8b0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001d970000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001da30000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001daf0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001dbb0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001dc70000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001dd30000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001ddf0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001deb0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001df70000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e030000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e0f0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e1b0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e270000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e330000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e3f0000c13d000006630000013d000000000001042f00000bdc01000041000000000010043f0000001201000039000000040010043f00000bb60100004100002e170001043000000bdc01000041000000000010043f0000005101000039000000040010043f00000bb60100004100002e17000104300000001f010000290000001f0510018f00000b8806100198000000400200043d000000000462001900001ead0000613d0000001e0700035f0000000008020019000000007107043c0000000008180436000000000048004b00001e590000c13d00001ead0000013d000000000301034f0000001f0580018f000000000908001900000b8806800198000000400200043d000000000462001900001e6b0000613d000000000703034f0000000008020019000000007107043c0000000008180436000000000048004b00001e670000c13d000000000005004b00001e780000613d000000000163034f0000000303500210000000000504043300000000053501cf000000000535022f000000000101043b0000010003300089000000000131022f00000000013101cf000000000151019f00000000001404350000006001900210000006710000013d0000001f010000290000001f0510018f00000b8806100198000000400200043d000000000462001900001ead0000613d0000001e0700035f0000000008020019000000007107043c0000000008180436000000000048004b00001e820000c13d00001ead0000013d0000001f010000290000001f0510018f00000b8806100198000000400200043d000000000462001900001ead0000613d0000001e0700035f0000000008020019000000007107043c0000000008180436000000000048004b00001e8f0000c13d00001ead0000013d0000001f010000290000001f0510018f00000b8806100198000000400200043d000000000462001900001ead0000613d0000001e0700035f0000000008020019000000007107043c0000000008180436000000000048004b00001e9c0000c13d00001ead0000013d0000001f010000290000001f0510018f00000b8806100198000000400200043d000000000462001900001ead0000613d0000001e0700035f0000000008020019000000007107043c0000000008180436000000000048004b00001ea90000c13d000000000005004b00001eba0000613d0000001e0160035f0000000303500210000000000504043300000000053501cf000000000535022f000000000101043b0000010003300089000000000131022f00000000013101cf000000000151019f00000000001404350000001f010000290000006001100210000006710000013d000000400400043d002000000004001d00000bd502000041000000000024043500000004024000390000002003000039000000000032043500000024024000392e151fb40000040f0000002002000029000000000121004900000b860010009c00000b860100804100000b860020009c00000b860200804100000060011002100000004002200210000000000121019f00002e17000104300000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001ed70000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001ee30000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001eef0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001efb0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f070000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f130000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f1f0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f2b0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f370000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f430000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f4f0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f5b0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f670000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f730000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f7f0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f8b0000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f970000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001fa30000c13d000006630000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000006630000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001faf0000c13d000006630000013d00000000430104340000000001320436000000000003004b00001fc00000613d000000000200001900000000051200190000000006240019000000000606043300000000006504350000002002200039000000000032004b00001fb90000413d000000000213001900000000000204350000001f0230003900000bff022001970000000001210019000000000001042d000000004301043400000baa03300197000000000332043600000000040404330000000000430435000000400310003900000000030304330000004004200039000000000034043500000060031000390000000003030433000000600420003900000000003404350000008003100039000000000303043300000080042000390000000000340435000000a0031000390000000003030433000000a0042000390000000000340435000000c0031000390000000003030433000000c0042000390000000000340435000000e0031000390000000003030433000000e004200039000000000034043500000100031000390000000003030433000001000420003900000000003404350000012003100039000000000303043300000120042000390000000000340435000001400310003900000000030304330000014004200039000000000034043500000160031000390000000003030433000000000003004b0000000003000039000000010300c039000001600420003900000000003404350000018003100039000000000303043300000180042000390000000000340435000001a003100039000000000303043300000baa03300197000001a0042000390000000000340435000001c0031000390000000003030433000001c0042000390000000000340435000001e0031000390000000003030433000001e00420003900000000003404350000020002200039000002000110003900000000010104330000000000120435000000000001042d0000000053010434000001a0040000390000000006420436000001a00420003900000000730304340000000000340435000001c004200039000000000003004b0000201d0000613d00000000080000190000000009480019000000000a870019000000000a0a04330000000000a904350000002008800039000000000038004b000020160000413d00000000074300190000000000070435000000000505043300000baa0550019700000000005604350000004005100039000000000505043300000baa0550019700000040062000390000000000560435000000600510003900000000050504330000006006200039000000000056043500000080051000390000000005050433000000800620003900000000005604350000001f0530003900000bff0550019700000000044500190000000005240049000000a006200039000000a0071000390000000007070433000000000056043500000000650704340000000004540436000000000005004b000020430000613d000000000700001900000000084700190000000009760019000000000909043300000000009804350000002007700039000000000057004b0000203c0000413d000000000645001900000000000604350000001f0550003900000bff055001970000000004450019000000c00510003900000000050504330000000006240049000000c007200039000000000067043500000000650504340000000004540436000000000005004b000020590000613d000000000700001900000000084700190000000009760019000000000909043300000000009804350000002007700039000000000057004b000020520000413d000000000645001900000000000604350000001f0550003900000bff055001970000000004450019000000e00510003900000000050504330000000006240049000000e007200039000000000067043500000000650504340000000004540436000000000005004b0000206f0000613d000000000700001900000000084700190000000009760019000000000909043300000000009804350000002007700039000000000057004b000020680000413d000000000645001900000000000604350000010006100039000000000606043300000baa06600197000001000720003900000000006704350000012006100039000000000606043300000120072000390000000000670435000001400610003900000000060604330000014007200039000000000067043500000160061000390000000006060433000001600720003900000000006704350000001f0550003900000bff0350019700000000044300190000000003240049000001800520003900000180011000390000000002010433000000000035043500000000030204330000000001340436000000000003004b000020da0000613d000000000400001900000020022000390000000005020433000000007605043400000baa06600197000000000661043600000000070704330000000000760435000000400650003900000000060604330000004007100039000000000067043500000060065000390000000006060433000000600710003900000000006704350000008006500039000000000606043300000080071000390000000000670435000000a0065000390000000006060433000000a0071000390000000000670435000000c0065000390000000006060433000000c0071000390000000000670435000000e0065000390000000006060433000000e007100039000000000067043500000100065000390000000006060433000001000710003900000000006704350000012006500039000000000606043300000120071000390000000000670435000001400650003900000000060604330000014007100039000000000067043500000160065000390000000006060433000000000006004b0000000006000039000000010600c039000001600710003900000000006704350000018006500039000000000606043300000180071000390000000000670435000001a006500039000000000606043300000baa06600197000001a0071000390000000000670435000001c0065000390000000006060433000001c0071000390000000000670435000001e0065000390000000006060433000001e0071000390000000000670435000002000550003900000000050504330000020006100039000000000056043500000220011000390000000104400039000000000034004b0000208f0000413d000000000001042d000000003101043400000baa01100197000000000112043600000000020304330000000000210435000000000001042d000000004301043400000baa03300197000000000332043600000000040404330000000000430435000000400310003900000000030304330000004004200039000000000034043500000060031000390000000003030433000000600420003900000000003404350000008003100039000000000303043300000080042000390000000000340435000000a002200039000000a00110003900000000010104330000000000120435000000000001042d000d000000000002000600000002001d000400000001001d000000400100043d00000c000010009c0000242b0000813d000001a002100039000000400020043f000001800210003900000060030000390000000000320435000000e0021000390000000000320435000000c0021000390000000000320435000000a0021000390000000000320435000000000231043600000160031000390000000000030435000001400310003900000000000304350000012003100039000000000003043500000100031000390000000000030435000000800310003900000000000304350000006003100039000000000003043500000040011000390000000000010435000000000002043500000006010000290000004001100039000500000001001d0000000002010433000000400900043d00000bbc010000410000000000190435000000000100041400000baa02200197000000040020008c000021260000c13d00000002010003670000000003000031000021390000013d00000b860090009c000d00000009001d00000b86030000410000000003094019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000b8a011001c72e152e100000040f0000000003010019000000600330027000000b860030019d00000b860330019700020000000103550000000100200190000024330000613d0000000d0900002900000bff043001980000001f0530018f0000000002490019000021430000613d000000000601034f0000000007090019000000006806043c0000000007870436000000000027004b0000213f0000c13d000000000005004b000021500000613d000000000141034f0000000304500210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001204350000001f0130003900000bff011001970000000002910019000000000012004b00000000010000390000000101004039000900000002001d00000ba70020009c0000242b0000213d00000001001001900000242b0000c13d0000000901000029000000400010043f00000bad0030009c000024310000213d0000001f0030008c000024310000a13d000000000109043300000ba70010009c000024310000213d000000000293001900000000019100190000001f03100039000000000023004b000000000400001900000bae0400804100000bae0330019700000bae05200197000000000653013f000000000053004b000000000300001900000bae0300404100000bae0060009c000000000304c019000000000003004b000024310000c13d0000000013010434000a00000003001d00000ba70030009c0000242b0000213d0000000a0300002900000005033002100000003f0430003900000ba804400197000000090440002900000ba70040009c0000242b0000213d000000400040043f00000009040000290000000a050000290000000004540436000800000004001d0000000003130019000000000023004b000024310000213d000000000031004b000021960000813d0000000902000029000000001401043400000baa0040009c000024310000213d00000020022000390000000000420435000000000031004b0000218a0000413d00000009010000290000000001010433000a00000001001d00000ba70010009c0000242b0000213d0000000a0100002900000005011002100000003f0210003900000ba802200197000000400300043d0000000002230019000d00000003001d000000000032004b0000000003000039000000010300403900000ba70020009c0000242b0000213d00000001003001900000242b0000c13d000000400020043f0000000d020000290000000a030000290000000005320436000000000003004b000021f20000613d0000000002000019000000400300043d00000beb0030009c0000242b0000213d0000022004300039000000400040043f00000200043000390000000000040435000001e0043000390000000000040435000001c0043000390000000000040435000001a00430003900000000000404350000018004300039000000000004043500000160043000390000000000040435000001400430003900000000000404350000012004300039000000000004043500000100043000390000000000040435000000e0043000390000000000040435000000c0043000390000000000040435000000a0043000390000000000040435000000800430003900000000000404350000006004300039000000000004043500000040043000390000000000040435000000200430003900000000000404350000000000030435000000000452001900000000003404350000002002200039000000000012004b000021ab0000413d0000000003000019000700000005001d00000009010000290000000001010433000000000031004b000024250000a13d0000000502300210000b00000002001d0000000801200029000000000101043300000baa01100197000c00000003001d2e1525b60000040f0000000c0300002900000007050000290000000d020000290000000002020433000000000032004b000024250000a13d0000000b0250002900000000001204350000000d010000290000000001010433000000000031004b000024250000a13d00000001033000390000000a0030006c000021d80000413d00000005010000290000000001010433000000400900043d00000bf802000041000000000029043500000baa01100197000000040290003900000000001204350000000001000414000000040200002900000baa02200197000000040020008c000022020000c13d00000002010003670000000003000031000022150000013d00000b860090009c000c00000009001d00000b86030000410000000003094019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000bb6011001c72e152e100000040f0000000003010019000000600330027000000b860030019d00000b8603300197000200000001035500000001002001900000243f0000613d0000000c0900002900000bff043001980000001f0530018f00000000024900190000221f0000613d000000000601034f0000000007090019000000006806043c0000000007870436000000000027004b0000221b0000c13d000000000005004b0000222c0000613d000000000141034f0000000304500210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001204350000001f0130003900000bff021001970000000001920019000000000021004b0000000002000039000000010200403900000ba70010009c0000242b0000213d00000001002001900000242b0000c13d000000400010043f00000bad0030009c000024310000213d000000200030008c000024310000413d000000000409043300000ba70040009c000024310000213d00000000029300190000000004940019000000000542004900000bad0050009c000024310000213d000000600050008c000024310000413d00000bc30010009c0000242b0000213d0000006005100039000000400050043f000000007604043400000ba70060009c000024310000213d00000000084600190000001f06800039000000000026004b000000000900001900000bae0900804100000bae0a60019700000bae06200197000000000b6a013f00000000006a004b000000000a00001900000bae0a00404100000bae00b0009c000000000a09c01900000000000a004b000024310000c13d000000009808043400000ba70080009c0000242b0000213d0000001f0a80003900000bff0aa001970000003f0aa0003900000bff0aa00197000000000a5a001900000ba700a0009c0000242b0000213d0000004000a0043f0000000000850435000000000a98001900000000002a004b000024310000213d000000800a100039000000000008004b000022750000613d000000000b000019000000000cab0019000000000d9b0019000000000d0d04330000000000dc0435000000200bb0003900000000008b004b0000226e0000413d0000000008a8001900000000000804350000000005510436000000000707043300000ba70070009c000024310000213d00000000074700190000001f08700039000000000028004b000000000900001900000bae0900804100000bae08800197000000000a68013f000000000068004b000000000800001900000bae0800404100000bae00a0009c000000000809c019000000000008004b000024310000c13d000000008707043400000ba70070009c0000242b0000213d0000001f0970003900000bff099001970000003f0990003900000bff0a900197000000400900043d000000000aa9001900000000009a004b000000000b000039000000010b00403900000ba700a0009c0000242b0000213d0000000100b001900000242b0000c13d0000004000a0043f000000000a790436000000000b87001900000000002b004b000024310000213d000000000007004b000022a80000613d000000000b000019000000000cab0019000000000d8b0019000000000d0d04330000000000dc0435000000200bb0003900000000007b004b000022a10000413d00000000077a0019000000000007043500000000009504350000004007400039000000000707043300000ba70070009c000024310000213d00000000044700190000001f07400039000000000027004b000000000800001900000bae0800804100000bae07700197000000000967013f000000000067004b000000000600001900000bae0600404100000bae0090009c000000000608c019000000000006004b000024310000c13d000000006404043400000ba70040009c0000242b0000213d0000001f0740003900000bff077001970000003f0770003900000bff07700197000000400a00043d00000000077a00190000000000a7004b0000000008000039000000010800403900000ba70070009c0000242b0000213d00000001008001900000242b0000c13d000000400070043f00000000074a04360000000008640019000000000028004b000024310000213d000000000004004b000c0000000a001d000022dd0000613d000000000200001900000000087200190000000009620019000000000909043300000000009804350000002002200039000000000042004b000022d60000413d0000000002470019000000000002043500000040021000390000000000a204350000000001010433000800000001001d0000000001050433000300000001001d000000060200002900000080012000390000000001010433000400000001001d00000060012000390000000001010433000700000001001d00000020012000390000000001010433000900000001001d0000000001020433000a00000001001d00000005010000290000000002010433000000400c00043d00000be50100004100000000001c0435000000000100041400000baa05200197000000040050008c000b00000005001d000022ff0000c13d000000200030008c000000200400003900000000040340190000232f0000013d00000b8600c0009c00000b860200004100000000020c4019000000400220021000000b860010009c00000b8601008041000000c001100210000000000121019f00000b8a011001c7000000000205001900060000000c001d2e152e100000040f000000060c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c00190000231c0000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000023180000c13d000000000006004b000023290000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000000c0a0000290000244b0000613d0000000b050000290000001f01400039000000600110018f000000000bc1001900000000001b004b0000000002000039000000010200403900000ba700b0009c0000242b0000213d00000001002001900000242b0000c13d0000004000b0043f000000200030008c000024310000413d00000000020c0433000600000002001d00000baa0020009c000024310000213d00000bf90200004100000000002b04350000000002000414000000040050008c000023770000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c7000000000205001900050000000b001d2e152e100000040f000000050b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000023620000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000235e0000c13d000000000006004b0000236f0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000000c0a000029000024570000613d0000001f01400039000000600110018f0000000b05000029000000000cb1001900000ba700c0009c0000242b0000213d0000004000c0043f000000200030008c000024310000413d00000000020b0433000500000002001d00000bfa0200004100000000002c04350000000002000414000000040050008c000023b60000613d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c7000000000205001900020000000c001d2e152e100000040f000000020c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000023a10000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b0000239d0000c13d000000000006004b000023ae0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000000c0a000029000024630000613d0000001f01400039000000600110018f0000000b05000029000000000bc1001900000ba700b0009c0000242b0000213d0000004000b0043f000000200030008c000024310000413d00000000060c043300000bfb0200004100000000002b04350000000002000414000000040050008c000023f60000613d000100000006001d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c7000000000205001900020000000b001d2e152e100000040f000000020b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000023e00000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000023dc0000c13d000000000006004b000023ed0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000000c0a0000290000246f0000613d0000001f01400039000000600110018f0000000b0500002900000001060000290000000001b1001900000ba70010009c0000242b0000213d000000400010043f000000200030008c000024310000413d00000bea0010009c0000242b0000213d00000000020b0433000001a003100039000000400030043f00000180031000390000000d0400002900000000004304350000016003100039000000000023043500000140021000390000000000620435000001200210003900000005030000290000000000320435000001000210003900000006030000290000000000320435000000e0021000390000000000a20435000000c00210003900000003030000290000000000320435000000a0021000390000000803000029000000000032043500000080021000390000000403000029000000000032043500000060021000390000000703000029000000000032043500000040021000390000000000520435000000090200002900000baa02200197000000200310003900000000002304350000000a020000290000000000210435000000000001042d00000bdc01000041000000000010043f0000003201000039000000040010043f00000bb60100004100002e170001043000000bdc01000041000000000010043f0000004101000039000000040010043f00000bb60100004100002e1700010430000000000100001900002e17000104300000001f0530018f00000b8806300198000000400200043d00000000046200190000247a0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000243a0000c13d0000247a0000013d0000001f0530018f00000b8806300198000000400200043d00000000046200190000247a0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000024460000c13d0000247a0000013d0000001f0530018f00000b8806300198000000400200043d00000000046200190000247a0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000024520000c13d0000247a0000013d0000001f0530018f00000b8806300198000000400200043d00000000046200190000247a0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000245e0000c13d0000247a0000013d0000001f0530018f00000b8806300198000000400200043d00000000046200190000247a0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000246a0000c13d0000247a0000013d0000001f0530018f00000b8806300198000000400200043d00000000046200190000247a0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000024760000c13d000000000005004b000024870000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000b860020009c00000b86020080410000004002200210000000000121019f00002e17000104300002000000000002000000400200043d00000c010020009c000025680000813d0000004003200039000000400030043f00000020032000390000000000030435000000000002043500000bed02000041000000400c00043d00000000002c0435000000000200041400000baa05100197000000040050008c000200000005001d000024a30000c13d0000000003000031000000200030008c00000020040000390000000004034019000024d20000013d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c7000000000205001900010000000c001d2e152e100000040f000000010c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000024c00000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000024bc0000c13d000000000006004b000024cd0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000256e0000613d00000002050000290000001f01400039000000600110018f000000000bc1001900000000001b004b0000000002000039000000010200403900000ba700b0009c000025680000213d0000000100200190000025680000c13d0000004000b0043f0000001f0030008c000025660000a13d00000000020c043300000baa0020009c000025660000213d00000be50400004100000000004b04350000000004000414000000040020008c000025170000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c700010000000b001d2e152e100000040f000000010b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000025030000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000024ff0000c13d000000000006004b000025100000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000258c0000613d0000001f01400039000000600110018f0000000205000029000000000cb1001900000ba700c0009c000025680000213d0000004000c0043f000000200030008c000025660000413d00000000020b043300000baa0020009c000025660000213d00000be70400004100000000004c04350000000404c0003900000000005404350000000004000414000000040020008c000025570000613d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000bb6011001c700010000000c001d2e152e100000040f000000010c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000025430000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b0000253f0000c13d000000000006004b000025500000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000025980000613d0000001f01400039000000600110018f00000002050000290000000001c1001900000ba70010009c000025680000213d000000400010043f000000200030008c000025660000413d00000bc20010009c000025680000213d00000000020c04330000004003100039000000400030043f000000200310003900000000002304350000000000510435000000000001042d000000000100001900002e170001043000000bdc01000041000000000010043f0000004101000039000000040010043f00000bb60100004100002e17000104300000001f0530018f00000b8806300198000000400200043d0000000004620019000025790000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000025750000c13d000000000005004b000025860000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000b860020009c00000b86020080410000004002200210000000000112019f00002e17000104300000001f0530018f00000b8806300198000000400200043d0000000004620019000025a30000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000025930000c13d000025a30000013d0000001f0530018f00000b8806300198000000400200043d0000000004620019000025a30000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000259f0000c13d000000000005004b000025b00000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000b860020009c00000b86020080410000004002200210000000000121019f00002e1700010430000f0000000000020000000005010019000000400100043d00000c020010009c00002a6f0000813d0000022002100039000000400020043f00000200021000390000000000020435000001e0021000390000000000020435000001c0021000390000000000020435000001a00210003900000000000204350000018002100039000000000002043500000160021000390000000000020435000001400210003900000000000204350000012002100039000000000002043500000100021000390000000000020435000000e0021000390000000000020435000000c0021000390000000000020435000000a002100039000000000002043500000080021000390000000000020435000000600210003900000000000204350000004002100039000000000002043500000020021000390000000000020435000000000001043500000baa01000041000001000010043f00000bec01000041000000400b00043d00000000001b0435000001000100043d000000000251016f0000000001000414000000040020008c000c00000005001d000025ee0000c13d0000000003000031000000200030008c000000200400003900000000040340190000261c0000013d00000b8600b0009c00000b860300004100000000030b4019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000b8a011001c7000f0000000b001d2e152e100000040f0000000f0b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b00190000260a0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000026060000c13d000000000006004b000026170000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002a930000613d0000000c050000290000001f01400039000000600110018f000000000cb1001900000000001c004b0000000002000039000000010200403900000ba700c0009c00002a6f0000213d000000010020019000002a6f0000c13d0000004000c0043f0000001f0030008c00002a6d0000a13d00000000020b0433000a00000002001d00000bed0200004100000000002c0435000001000200043d000000000252016f0000000004000414000000040020008c000026620000613d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c7000f0000000c001d2e152e100000040f0000000f0c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c00190000264e0000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b0000264a0000c13d000000000006004b0000265b0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002a9f0000613d0000001f01400039000000600110018f0000000c05000029000000000bc1001900000ba700b0009c00002a6f0000213d0000004000b0043f000000200030008c00002a6d0000413d00000000010c0433000f00000001001d00000baa0010009c00002a6d0000213d00000bee0100004100000000061b0436000001000100043d000000000151016f0000000402b000390000000000120435000001000100043d0000000f0210017f0000000001000414000000040020008c0000267b0000c13d000000400030008c00000040040000390000000004034019000026ab0000013d000d00000006001d00000b8600b0009c00000b860300004100000000030b4019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000bb6011001c7000e0000000b001d2e152e100000040f0000000e0b0000290000000003010019000000600330027000000b8603300197000000400030008c000000400400003900000000040340190000001f0640018f000000600740019000000000057b0019000026980000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000026940000c13d000000000006004b000026a50000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002aab0000613d0000000c050000290000000d060000290000001f01400039000000e00110018f000000000cb1001900000ba700c0009c00002a6f0000213d0000004000c0043f000000400030008c00002a6d0000413d00000000020b0433000000000002004b0000000001000039000000010100c039000900000002001d000000000012004b00002a6d0000c13d0000000001060433000800000001001d00000bb90100004100000000001c0435000001000100043d000000000251016f0000000001000414000000040020008c000026c50000c13d0000002004000039000026f30000013d00000b8600c0009c00000b860300004100000000030c4019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000b8a011001c7000e0000000c001d2e152e100000040f0000000e0c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000026e10000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000026dd0000c13d000000000006004b000026ee0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002ab70000613d0000000c050000290000001f01400039000000600110018f000000000bc1001900000ba700b0009c00002a6f0000213d0000004000b0043f000000200030008c00002a6d0000413d00000000020c0433000b00000002001d00000baa0020009c00002a6d0000213d00000bef0200004100000000002b0435000001000200043d0000000b0220017f0000000004000414000000040020008c000027360000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c7000e0000000b001d2e152e100000040f0000000e0b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000027220000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000271e0000c13d000000000006004b0000272f0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002ac30000613d0000001f01400039000000600110018f0000000c05000029000000000ab10019000000c00000043f00000ba700a0009c00002a6f0000213d0000004000a0043f000000200030008c00002a6d0000413d00000000010b0433000000ff0010008c00002a6d0000213d000000c00010043f000000e00000043f00000bf0060000410000002007000039000000000800001900000000006a04350000002401a00039000001000200043d0000000000810435000000000152016f0000000402a000390000000000120435000001000100043d0000000f0210017f0000000001000414000000040020008c0000000004070019000027830000613d000d00000008001d00000b8600a0009c00000b860300004100000000030a4019000000400330021000000b860010009c00000b8601008041000000c001100210000000000131019f00000bbb011001c7000e0000000a001d2e152e100000040f0000000e0a0000290000000003010019000000600330027000000b8603300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000276e0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b0000276a0000c13d0000001f074001900000277b0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002a750000613d0000000c0500002900000bf00600004100000020070000390000000d080000290000001f01400039000000600110018f000000000ba1001900000000001b004b0000000002000039000000010200403900000ba700b0009c00002a6f0000213d000000010020019000002a6f0000c13d0000004000b0043f000000200030008c00002a6d0000413d00000000020a0433000000000002004b0000000004000039000000010400c039000000000042004b00002a6d0000c13d00000000028201cf000000e00400043d000000000224019f000000e00020043f0000000102800039000000ff0820018f000000080080008c000000000a0b0019000027450000a13d00000bf10200004100000000002b0435000001000200043d000000000252016f0000000004000414000000040020008c000027d60000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c7000e0000000b001d2e152e100000040f0000000e0b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000027c20000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000027be0000c13d000000000006004b000027cf0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002acf0000613d0000001f01400039000000600110018f0000000c05000029000000000cb1001900000ba700c0009c00002a6f0000213d0000004000c0043f000000200030008c00002a6d0000413d00000000020b0433000e00000002001d00000bf20200004100000000002c0435000001000200043d000000000252016f0000000004000414000000040020008c000028150000613d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c7000d0000000c001d2e152e100000040f0000000d0c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000028010000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000027fd0000c13d000000000006004b0000280e0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002adb0000613d0000001f01400039000000600110018f0000000c05000029000000000dc1001900000ba700d0009c00002a6f0000213d0000004000d0043f000000200030008c00002a6d0000413d00000000020c0433000d00000002001d00000bf30200004100000000002d0435000001000200043d000000000252016f0000000004000414000000040020008c000028540000613d00000b8600d0009c00000b860100004100000000010d4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c700070000000d001d2e152e100000040f000000070d0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057d0019000028400000613d000000000801034f00000000090d0019000000008a08043c0000000009a90436000000000059004b0000283c0000c13d000000000006004b0000284d0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002ae70000613d0000001f01400039000000600110018f0000000c05000029000000000bd1001900000ba700b0009c00002a6f0000213d0000004000b0043f000000200030008c00002a6d0000413d00000000020d0433000700000002001d00000bf40200004100000000002b0435000001000200043d000000000252016f0000000404b000390000000000240435000001000200043d0000000f0220017f0000000004000414000000040020008c000028970000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000bb6011001c700060000000b001d2e152e100000040f000000060b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000028830000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000287f0000c13d000000000006004b000028900000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002af30000613d0000001f01400039000000600110018f0000000c05000029000000000cb1001900000ba700c0009c00002a6f0000213d0000004000c0043f000000200030008c00002a6d0000413d00000000020b0433000600000002001d00000bf50200004100000000002c0435000001000200043d000000000252016f0000000404c000390000000000240435000001000200043d0000000f0220017f0000000004000414000000040020008c000028da0000613d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000bb6011001c7000f0000000c001d2e152e100000040f0000000f0c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000028c60000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000028c20000c13d000000000006004b000028d30000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002aff0000613d0000001f01400039000000600110018f0000000c05000029000000000bc1001900000ba700b0009c00002a6f0000213d0000004000b0043f000000200030008c00002a6d0000413d00000000020c0433000f00000002001d00000bd00200004100000000002b0435000001000200043d000000000252016f0000000004000414000000040020008c000029190000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c700050000000b001d2e152e100000040f000000050b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000029050000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000029010000c13d000000000006004b000029120000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002b0b0000613d0000001f01400039000000600110018f0000000c05000029000000000cb1001900000ba700c0009c00002a6f0000213d0000004000c0043f000000200030008c00002a6d0000413d00000000020b0433000500000002001d00000bf60200004100000000002c0435000001000200043d000000000252016f0000000004000414000000040020008c000029580000613d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c700040000000c001d2e152e100000040f000000040c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000029440000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000029400000c13d000000000006004b000029510000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002b170000613d0000001f01400039000000600110018f0000000c05000029000000000bc1001900000ba700b0009c00002a6f0000213d0000004000b0043f000000200030008c00002a6d0000413d00000000020c0433000400000002001d00000bd70200004100000000002b0435000001000200043d000000000252016f0000000004000414000000040020008c000029970000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c700030000000b001d2e152e100000040f000000030b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000029830000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000297f0000c13d000000000006004b000029900000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002b230000613d0000001f01400039000000600110018f0000000c05000029000000000cb1001900000ba700c0009c00002a6f0000213d0000004000c0043f000000200030008c00002a6d0000413d00000000020b0433000300000002001d00000bf70200004100000000002c0435000001000200043d000000000252016f0000000004000414000000040020008c000029d60000613d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c700020000000c001d2e152e100000040f000000020c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000029c20000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000029be0000c13d000000000006004b000029cf0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002b2f0000613d0000001f01400039000000600110018f0000000c05000029000000000bc1001900000ba700b0009c00002a6f0000213d0000004000b0043f000000200030008c00002a6d0000413d00000000060c043300000bef0200004100000000002b0435000001000200043d000000000252016f0000000004000414000000040020008c00002a160000613d000100000006001d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000b8a011001c700020000000b001d2e152e100000040f000000020b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900002a010000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000029fd0000c13d000000000006004b00002a0e0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002b3b0000613d0000001f01400039000000600110018f0000000c0500002900000001060000290000000001b10019000000800000043f00000ba70010009c00002a6f0000213d000000400010043f000000200030008c00002a6d0000413d00000000020b0433000000ff0020008c00002a6d0000213d000000800020043f000000a00010043f00000beb0010009c00002a6f0000213d0000022002100039000000400020043f000001000200043d000000000252016f0000000000210435000000a00100043d00000020011000390000000a020000290000000000210435000000a00100043d00000040011000390000000e020000290000000000210435000000a00100043d00000060011000390000000d020000290000000000210435000000a00100043d000000800110003900000007020000290000000000210435000000a00100043d000000a00110003900000006020000290000000000210435000000a00100043d000000c0011000390000000f020000290000000000210435000000a00100043d000000e00110003900000005020000290000000000210435000000a00100043d000001000110003900000004020000290000000000210435000000a00100043d000001200110003900000003020000290000000000210435000000a00100043d00000140011000390000000000610435000000a00100043d000001600110003900000009020000290000000000210435000000a00100043d000001800110003900000008020000290000000000210435000001000100043d0000000b0110017f000000a00200043d000001a0022000390000000000120435000000800100043d000000ff0110018f000000a00200043d000001c0022000390000000000120435000000c00100043d000000ff0110018f000000a00200043d000001e0022000390000000000120435000000a00100043d0000020001100039000000e00200043d0000000000210435000000a00100043d000000000001042d000000000100001900002e170001043000000bdc01000041000000000010043f0000004101000039000000040010043f00000bb60100004100002e17000104300000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002a7c0000c13d000000000005004b00002a8d0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000b860020009c00000b86020080410000004002200210000000000121019f00002e17000104300000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002a9a0000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002aa60000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002ab20000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002abe0000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002aca0000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002ad60000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002ae20000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002aee0000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002afa0000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002b060000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002b120000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002b1e0000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002b2a0000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002b360000c13d00002a800000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002a800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002b420000c13d00002a800000013d0007000000000002000000400300043d00000c030030009c00002cff0000813d000000c004300039000000400040043f000000a004300039000000000004043500000080043000390000000000040435000000600430003900000000000404350000004004300039000000000004043500000020043000390000000000040435000000000003043500000bb503000041000000400c00043d00000000003c043500000baa032001970000000402c00039000700000003001d0000000000320435000000000200041400000baa05100197000000040050008c000600000005001d00002b690000c13d0000000003000031000000200030008c0000002004000039000000000403401900002b980000013d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bb6011001c7000000000205001900050000000c001d2e152e100000040f000000050c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c001900002b860000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b00002b820000c13d000000000006004b00002b930000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002d070000613d00000006050000290000001f01400039000000600110018f000000000bc1001900000000001b004b0000000002000039000000010200403900000ba700b0009c00002cff0000213d000000010020019000002cff0000c13d0000004000b0043f0000001f0030008c00002d050000a13d00000000020c0433000500000002001d00000bb70200004100000000002b04350000000402b00039000000070400002900000000004204350000000002000414000000040050008c00002be00000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bb6011001c7000000000205001900040000000b001d2e152e0b0000040f000000040b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900002bcc0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00002bc80000c13d000000000006004b00002bd90000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002d130000613d0000001f01400039000000600110018f0000000605000029000000000cb1001900000ba700c0009c00002cff0000213d0000004000c0043f000000200030008c00002d050000413d00000000020b0433000400000002001d00000bb80200004100000000002c04350000000402c00039000000070400002900000000004204350000000002000414000000040050008c00002c210000613d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000bb6011001c7000000000205001900030000000c001d2e152e0b0000040f000000030c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c001900002c0d0000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b00002c090000c13d000000000006004b00002c1a0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002d1f0000613d0000001f01400039000000600110018f0000000605000029000000000bc1001900000ba700b0009c00002cff0000213d0000004000b0043f000000200030008c00002d050000413d00000000020c0433000300000002001d00000bb90200004100000000002b04350000000002000414000000040050008c00002c5f0000613d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860020009c00000b8602008041000000c002200210000000000112019f00000b8a011001c7000000000205001900020000000b001d2e152e100000040f000000020b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900002c4b0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00002c470000c13d000000000006004b00002c580000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002d2b0000613d0000001f01400039000000600110018f0000000605000029000000000cb1001900000ba700c0009c00002cff0000213d0000004000c0043f000000200030008c00002d050000413d00000000020b043300000baa0020009c00002d050000213d00000bb50400004100000000004c04350000000406c00039000000070400002900000000004604350000000004000414000000040020008c00002ca20000613d00000b8600c0009c00000b860100004100000000010c4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000bb6011001c7000100000002001d00020000000c001d2e152e100000040f000000020c0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c001900002c8d0000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b00002c890000c13d000000000006004b00002c9a0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002d370000613d0000001f01400039000000600110018f00000006050000290000000102000029000000000bc1001900000ba700b0009c00002cff0000213d0000004000b0043f000000200030008c00002d050000413d00000000070c04330000002404b00039000000000054043500000bba0400004100000000004b04350000000406b00039000000070400002900000000004604350000000004000414000000040020008c00002ce50000613d000200000007001d00000b8600b0009c00000b860100004100000000010b4019000000400110021000000b860040009c00000b8604008041000000c003400210000000000113019f00000bbb011001c700070000000b001d2e152e100000040f000000070b0000290000000003010019000000600330027000000b8603300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900002cd00000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00002ccc0000c13d000000000006004b00002cdd0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002d430000613d0000001f01400039000000600110018f000000060500002900000002070000290000000001b1001900000ba70010009c00002cff0000213d000000400010043f000000200030008c00002d050000413d00000bb40010009c00002cff0000213d00000000020b0433000000c003100039000000400030043f000000a0031000390000000000230435000000800210003900000000007204350000006002100039000000030300002900000000003204350000004002100039000000040300002900000000003204350000002002100039000000050300002900000000003204350000000000510435000000000001042d00000bdc01000041000000000010043f0000004101000039000000040010043f00000bb60100004100002e1700010430000000000100001900002e17000104300000001f0530018f00000b8806300198000000400200043d000000000462001900002d4e0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d0e0000c13d00002d4e0000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002d4e0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d1a0000c13d00002d4e0000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002d4e0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d260000c13d00002d4e0000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002d4e0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d320000c13d00002d4e0000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002d4e0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d3e0000c13d00002d4e0000013d0000001f0530018f00000b8806300198000000400200043d000000000462001900002d4e0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d4a0000c13d000000000005004b00002d5b0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000b860020009c00000b86020080410000004002200210000000000121019f00002e17000104300007000000000002000400000001001d0000000021010434000300000002001d000500000001001d00000bfd0010009c00002dca0000813d000000050100002900000005011002100000003f0210003900000ba802200197000000400500043d0000000002250019000000000052004b0000000003000039000000010300403900000ba70020009c00002dca0000213d000000010030019000002dca0000c13d000000400020043f00000005020000290000000006250436000000000002004b00002dc20000613d0000000002000019000000400300043d00000beb0030009c00002dca0000213d0000022004300039000000400040043f00000200043000390000000000040435000001e0043000390000000000040435000001c0043000390000000000040435000001a00430003900000000000404350000018004300039000000000004043500000160043000390000000000040435000001400430003900000000000404350000012004300039000000000004043500000100043000390000000000040435000000e0043000390000000000040435000000c0043000390000000000040435000000a0043000390000000000040435000000800430003900000000000404350000006004300039000000000004043500000040043000390000000000040435000000200430003900000000000404350000000000030435000000000426001900000000003404350000002002200039000000000012004b00002d7b0000413d0000000003000019000200000005001d000100000006001d00000004010000290000000001010433000000000031004b00002dc40000a13d0000000502300210000600000002001d0000000301200029000000000101043300000baa01100197000700000003001d2e1525b60000040f0000000703000029000000010600002900000002050000290000000002050433000000000032004b00002dc40000a13d000000060260002900000000001204350000000001050433000000000031004b00002dc40000a13d0000000103300039000000050030006c00002da90000413d0000000001050019000000000001042d00000bdc01000041000000000010043f0000003201000039000000040010043f00000bb60100004100002e170001043000000bdc01000041000000000010043f0000004101000039000000040010043f00000bb60100004100002e1700010430000000010010008c00002dd80000613d000000020010008c00002de60000c13d00000bcf010000410000000000100443000000000100041400002ddb0000013d00000bcd010000410000000000100443000000000100041400000b860010009c00000b8601008041000000c00110021000000bce011001c70000800b020000392e152e100000040f000000010020019000002de50000613d000000000101043b000000000001042d000000000001042f00000bdc01000041000000000010043f0000005101000039000000040010043f00000bb60100004100002e1700010430000000000001042f00000000050100190000000000200443000000050030008c00002dfb0000413d000000040100003900000000020000190000000506200210000000000664001900000005066002700000000006060031000000000161043a0000000102200039000000000031004b00002df30000413d00000b860030009c00000b86030080410000006001300210000000000200041400000b860020009c00000b8602008041000000c002200210000000000112019f00000c04011001c700000000020500192e152e100000040f000000010020019000002e0a0000613d000000000101043b000000000001042d000000000001042f00002e0e002104210000000102000039000000000001042d0000000002000019000000000001042d00002e13002104230000000102000039000000000001042d0000000002000019000000000001042d00002e150000043200002e160001042e00002e170001043000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000000ffffffe009c8f7ec0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000001e13380ae0fcab3000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000100000001000000000000000000000000000000000000000000000000000000000000000000000000007c51b64100000000000000000000000000000000000000000000000000000000c7ad089400000000000000000000000000000000000000000000000000000000e0a67f1000000000000000000000000000000000000000000000000000000000e0a67f1100000000000000000000000000000000000000000000000000000000e1d146fb00000000000000000000000000000000000000000000000000000000c7ad089500000000000000000000000000000000000000000000000000000000d77ebf9600000000000000000000000000000000000000000000000000000000aa5dbd2200000000000000000000000000000000000000000000000000000000aa5dbd2300000000000000000000000000000000000000000000000000000000b3124239000000000000000000000000000000000000000000000000000000007c51b642000000000000000000000000000000000000000000000000000000007c84e3b30000000000000000000000000000000000000000000000000000000047d86a80000000000000000000000000000000000000000000000000000000006857249b000000000000000000000000000000000000000000000000000000006857249c000000000000000000000000000000000000000000000000000000007a27db570000000000000000000000000000000000000000000000000000000047d86a810000000000000000000000000000000000000000000000000000000055dd951500000000000000000000000000000000000000000000000000000000345954db00000000000000000000000000000000000000000000000000000000345954dc000000000000000000000000000000000000000000000000000000003e3e399c000000000000000000000000000000000000000000000000000000000d3ae318000000000000000000000000000000000000000000000000000000001f884fdf310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e0000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000000000000000000000000000000000fffffffffffffedf000000000000000000000000fffffffffffffffffffffffffffffffffffffffff36dba380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000012000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000120000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffe1f000000000000000000000000000000000000000000000000ffffffffffffff3f70a0823100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000017bfdfbc000000000000000000000000000000000000000000000000000000003af9e669000000000000000000000000000000000000000000000000000000006f307dc300000000000000000000000000000000000000000000000000000000dd62ed3e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044000000000000000000000000b0772d0b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000120000000000000000061252fd100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff7ff7c618c1000000000000000000000000000000000000000000000000000000001627ee8900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffbf000000000000000000000000000000000000000000000000ffffffffffffff9f02000002000000000000000000000000000000440000000000000000000000008f693ec70000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff81814945000000000000000000000000000000000000000000000000000000002c427b570000000000000000000000000000000000000000000000000000000092a1823500000000000000000000000000000000000000000000000000000000aa5af0fd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffdf7c05a7c500000000000000000000000000000000000000000000000000000000796b89b91644bc98cd93958e4c9038275d622183e25ac5af08cc6b5d95539132020000020000000000000000000000000000000400000000000000000000000042cbb15ccdc3cad6266b0e7a08c0454b23bf29dc2df74b6f3c209e9336465bd147bd3718000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000c097ce7bc90715b34b9f10000000006e657720696e646578206f766572666c6f777300000000000000000000000000000000010000000000000000000000000000000000000000000000000000000008c379a00000000000000000000000000000000000000000000000000000000074c4c1cc0000000000000000000000000000000000000000000000000000000018160ddd000000000000000000000000000000000000000000000000000000006dfd08ca00000000000000000000000000000000000000000000000000000000160c3a030000000000000000000000000000000000000000000000000000000095dd919300000000000000000000000000000000000000000000000000000000552c0971000000000000000000000000000000000000000000000000000000004e487b7100000000000000000000000000000000000000000000000000000000266e0a7f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000440000012000000000000000007aee632d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000002c00000000000000000000000000000000000000000000000000000000000000000fffffffffffffd3f000000000000000000000000000000000000000000000000ffffffffffffff5f0000000000000000000000000000000000000004000001800000000000000000000000000000000000000000000000000000000000000000fffffffffffffe7f7dc0d1d000000000000000000000000000000000000000000000000000000000bbcac55700000000000000000000000000000000000000000000000000000000fc57d4df00000000000000000000000000000000000000000000000000000000d88ff1f40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fffffffffffffffe0000000000000000000000000000000000000000000000000fffffffffffffe5f000000000000000000000000000000000000000000000000fffffffffffffddf182df0f5000000000000000000000000000000000000000000000000000000005fe3b567000000000000000000000000000000000000000000000000000000008e8f294b00000000000000000000000000000000000000000000000000000000313ce56700000000000000000000000000000000000000000000000000000000e85a296000000000000000000000000000000000000000000000000000000000ae9d70b000000000000000000000000000000000000000000000000000000000f8f9da2800000000000000000000000000000000000000000000000000000000173b99040000000000000000000000000000000000000000000000000000000002c3bcbb000000000000000000000000000000000000000000000000000000004a584432000000000000000000000000000000000000000000000000000000008f840ddd000000000000000000000000000000000000000000000000000000003b1d21a200000000000000000000000000000000000000000000000000000000a3aefa2c00000000000000000000000000000000000000000000000000000000e8755446000000000000000000000000000000000000000000000000000000004ada90af00000000000000000000000000000000000000000000000000000000db5c65de00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffe9f0000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000fffffffffffffe3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000000000000000000000000000000000fffffffffffffe60000000000000000000000000000000000000000000000000ffffffffffffffc0000000000000000000000000000000000000000000000000fffffffffffffde0000000000000000000000000000000000000000000000000ffffffffffffff4002000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de74f27c00b5ac0ab41c9ffac27b97334e20a0fbe8993556965b047b8b013894" + "0x00030000000000020036000000000002000000000301034f0000000001030019000000600110027000000dae04100197000200000043035500010000000303550000000100200190000000320000c13d0000008009000039000000400090043f000000040040008c0000005b0000413d000000000543034f000000000203043b000000e00220027000000db70020009c0000005d0000a13d00000db80020009c000000a10000a13d00000db90020009c0000013a0000a13d00000dba0020009c000002f40000613d00000dbb0020009c000001b20000613d00000dbc0020009c0000005b0000c13d0000000001000416000000000001004b0000005b0000c13d0000000001000412001f00000001001d001e00400000003d0000800501000039000000440300003900000000040004150000001f0440008a000000050440021000000dcf0200004136b5368d0000040f36b536700000040f000000400200043d000000000012043500000dae0020009c00000dae02008041000000400120021000000dd0011001c7000036b60001042e0000000001000416000000000001004b0000005b0000c13d0000001f0140003900000daf011001970000010001100039000000400010043f0000001f0240018f00000db0054001980000010001500039000000430000613d0000010006000039000000000703034f000000007807043c0000000006860436000000000016004b0000003f0000c13d000000000002004b000000500000613d000000000353034f0000000302200210000000000501043300000000052501cf000000000525022f000000000303043b0000010002200089000000000323022f00000000022301cf000000000252019f0000000000210435000000600040008c0000005b0000413d000001000100043d000000000001004b0000000002000039000000010200c039000000000021004b0000005b0000c13d000001400200043d00000db10020009c000000dd0000a13d0000000001000019000036b70001043000000dc40020009c000000ba0000213d00000dca0020009c000001000000213d00000dcd0020009c000002420000613d00000dce0020009c0000005b0000c13d000000240040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000101043b00000dd10010009c0000005b0000213d0000002302100039000000000042004b0000005b0000813d0000000402100039000000000223034f000000000202043b001a00000002001d00000dd10020009c0000005b0000213d001900240010003d0000001a0100002900000005021002100000001901200029000000000041004b0000005b0000213d0000003f0120003900000dd20310019700000dd30030009c000006870000213d0000008001300039000000400010043f0000001a04000029000000800040043f000000000004004b0000065e0000c13d00000020020000390000000003210436000000800200043d00000000002304350000004003100039000000000002004b0000009f0000613d000000800400003900000000050000190000000006010019000000000703001900000020044000390000000003040433000000008303043400000db103300197000000000037043500000060036000390000000006080433000000000063043500000040037000390000000105500039000000000025004b0000000006070019000000910000413d00000000021300490000023a0000013d00000dbf0020009c000000e50000213d00000dc20020009c000001540000613d00000dc30020009c0000005b0000c13d000000240040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000101043b00000db10010009c0000005b0000213d36b52d7c0000040f000000400200043d001d00000002001d36b5293c0000040f0000001d0100002900000dae0010009c00000dae01008041000000400110021000000def011001c7000036b60001042e00000dc50020009c0000011d0000213d00000dc80020009c000002aa0000613d00000dc90020009c0000005b0000c13d000000640040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000201043b00000db10020009c0000005b0000213d0000002401300370000000000101043b00000db10010009c0000005b0000213d0000004403300370000000000303043b00000db10030009c0000005b0000213d00000e1404000041000000800040043f000000840010043f000000a40030043f0000000001000414000000040020008c000005f10000c13d0000000003000031000000200030008c00000020040000390000000004034019000006170000013d000001200300043d000000000001004b0000014f0000613d000000000003004b0000031d0000c13d00000db4030000410000000104000039000003260000013d00000dc00020009c0000019f0000613d00000dc10020009c0000005b0000c13d000000440040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000101043b00000db10010009c0000005b0000213d0000002402300370000000000202043b00000db10020009c0000005b0000213d36b534560000040f000000400200043d001d00000002001d36b529420000040f0000001d0100002900000dae0010009c00000dae01008041000000400110021000000ded011001c7000036b60001042e00000dcb0020009c000002d20000613d00000dcc0020009c0000005b0000c13d000000240040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000101043b001600000001001d00000db10010009c0000005b0000213d000000e009000039000000400090043f000000800000043f000000a00000043f0000006001000039000000c00010043f00000df601000041000000e00010043f00000000010004140000001602000029000000040020008c000003ba0000c13d0000000003000031000000000105034f000003c70000013d00000dc60020009c000002e40000613d00000dc70020009c0000005b0000c13d0000000001000416000000000001004b0000005b0000c13d000000440040008c0000005b0000413d0000000401300370000000000201043b00000db10020009c0000005b0000213d0000002401300370000000000101043b001600000001001d00000db10010009c0000005b0000213d002c0db100000045002d00000002001d00000df601000041000000800010043f00000000010004140000001602000029000000040020008c0000056c0000c13d0000000003000031000000000105034f000005780000013d00000dbd0020009c0000030a0000613d00000dbe0020009c0000005b0000c13d0000000001000416000000000001004b0000005b0000c13d0000000001000412002100000001001d002000600000003d000080050100003900000044030000390000000004000415000000210440008a000000050440021000000dcf0200004136b5368d0000040f00000db101100197000000800010043f00000dec01000041000036b60001042e000000000003004b000003250000c13d000000400100043d00000db2020000410000031f0000013d000000440040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000101043b00000dd10010009c0000005b0000213d0000002302100039000000000042004b0000005b0000813d0000000402100039000000000223034f000000000202043b001600000002001d00000dd10020009c0000005b0000213d001500240010003d000000160100002900000005021002100000001501200029000000000041004b0000005b0000213d0000002401300370000000000301043b00000db10030009c0000005b0000213d0000003f0120003900000dd20410019700000dd30040009c000006870000213d0000008001400039000000400010043f0000001605000029000000800050043f000000000005004b0000066f0000c13d00000020020000390000000002210436000000800300043d00000000003204350000004002100039000000000003004b000002390000613d0000008004000039000000000500001900000020044000390000000006040433000000008706043400000db107700197000000000772043600000000080804330000000000870435000000400760003900000000070704330000004008200039000000000078043500000060076000390000000007070433000000600820003900000000007804350000008007600039000000000707043300000080082000390000000000780435000000a0066000390000000006060433000000a0072000390000000000670435000000c0022000390000000105500039000000000035004b000001830000413d000002390000013d000000240040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000101043b00000db10010009c0000005b0000213d36b52e930000040f000000400200043d001d00000002001d36b528240000040f0000001d0100002900000dae0010009c00000dae01008041000000400110021000000dee011001c7000036b60001042e000000240040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000101043b00000dd10010009c0000005b0000213d0000002302100039000000000042004b0000005b0000813d0000000402100039000000000223034f000000000502043b00000dd10050009c000006870000213d00000005025002100000003f0620003900000dd20660019700000dd30060009c000006870000213d0000008006600039000000400060043f000000800050043f00000024011000390000000002120019000000000042004b0000005b0000213d000000000005004b0000000004000019000006240000c13d000a00000004001d00000005014002100000003f0210003900000dd4032001970000000002630019000000000032004b0000000003000039000000010300403900000dd10020009c000006870000213d0000000100300190000006870000c13d000000400020043f0000000a020000290000000005260436000000000002004b001900000006001d0000068d0000c13d000000400100043d00000020020000390000000002210436000000000306043300000000003204350000004002100039000000000003004b000002390000613d0000000004000019000000190800002900000020088000390000000005080433000000007605043400000db106600197000000000662043600000000070704330000000000760435000000400650003900000000060604330000004007200039000000000067043500000060065000390000000006060433000000600720003900000000006704350000008006500039000000000606043300000080072000390000000000670435000000a0065000390000000006060433000000a0072000390000000000670435000000c0065000390000000006060433000000c0072000390000000000670435000000e0065000390000000006060433000000e007200039000000000067043500000100065000390000000006060433000001000720003900000000006704350000012006500039000000000606043300000120072000390000000000670435000001400650003900000000060604330000014007200039000000000067043500000160065000390000000006060433000000000006004b0000000006000039000000010600c039000001600720003900000000006704350000018006500039000000000606043300000180072000390000000000670435000001a006500039000000000606043300000db106600197000001a0072000390000000000670435000001c0065000390000000006060433000001c0072000390000000000670435000001e0065000390000000006060433000001e0072000390000000000670435000002000550003900000000050504330000020006200039000000000056043500000220022000390000000104400039000000000034004b000001ee0000413d000000000212004900000dae0020009c00000dae02008041000000600220021000000dae0010009c00000dae010080410000004001100210000000000112019f000036b60001042e000000440040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000101043b00000db10010009c0000005b0000213d0000002402300370000000000602043b00000dd10060009c0000005b0000213d000000000264004900000dea0020009c0000005b0000213d000000a40020008c0000005b0000413d0000012002000039000000400020043f0000000405600039000000000753034f000000000707043b00000dd10070009c0000005b0000213d00000000076700190000002306700039000000000046004b0000005b0000813d0000000408700039000000000683034f000000000606043b00000dd10060009c000006870000213d0000001f0a60003900000e250aa001970000003f0aa0003900000e250aa0019700000e2400a0009c000006870000213d000001200aa000390000004000a0043f000001200060043f00000000076700190000002407700039000000000047004b0000005b0000213d0000002004800039000000000743034f00000e25086001980000001f0960018f00000140048000390000027d0000613d000001400a000039000000000b07034f00000000bc0b043c000000000aca043600000000004a004b000002790000c13d000000000009004b0000028a0000613d000000000787034f0000000308900210000000000904043300000000098901cf000000000989022f000000000707043b0000010008800089000000000787022f00000000078701cf000000000797019f000000000074043500000140046000390000000000040435000000800020043f0000002002500039000000000423034f000000000404043b00000db10040009c0000005b0000213d000000a00040043f0000002002200039000000000423034f000000000404043b00000db10040009c0000005b0000213d000000c00040043f0000002004200039000000000443034f000000000404043b000000e00040043f0000004002200039000000000223034f000000000202043b000001000020043f000000800200003936b529580000040f0000000002010019000000400100043d001d00000001001d36b5286a0000040f0000001d020000290000000001210049000005260000013d000000440040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000101043b001d00000001001d00000db10010009c0000005b0000213d0000002401300370000000000201043b00000db10020009c0000005b0000213d0000022009000039000000400090043f0000006001000039000000800010043f000000a00000043f000000c00000043f000000e00000043f000001000000043f000001200010043f000001400010043f000001600010043f000001800000043f000001a00000043f000001c00000043f000001e00000043f000002000010043f00000e1601000041000002200010043f000002240020043f00000000010004140000001d02000029000000040020008c0000043c0000c13d0000000003000031000000000105034f000004490000013d000000240040008c0000005b0000413d0000000002000416000000000002004b0000005b0000c13d0000000402300370000000000202043b003600000002001d00000db10020009c0000005b0000213d00000e1e03000041000000800030043f0000000003000414000000040020008c0000033a0000c13d000000000a000031000000000105034f000003460000013d0000000001000416000000000001004b0000005b0000c13d0000000001000412002f00000001001d002e00000000003d0000800501000039000000440300003900000000040004150000002f0440008a000000050440021000000dcf0200004136b5368d0000040f000000800010043f00000dec01000041000036b60001042e000000440040008c0000005b0000413d0000000001000416000000000001004b0000005b0000c13d0000000401300370000000000201043b00000db10020009c0000005b0000213d0000002401300370000000000301043b00000db10030009c0000005b0000213d00000de801000041000000800010043f000000840030043f0000000003000414000000040020008c000004bc0000c13d0000000003000031000000000105034f000004c90000013d0000000001000416000000000001004b0000005b0000c13d0000000001000412002300000001001d002200200000003d000080050100003900000044030000390000000004000415000000230440008a000000050440021000000dcf0200004136b5368d0000040f000000000001004b0000000001000039000000010100c039000000800010043f00000dec01000041000036b60001042e000000400100043d00000db502000041000000000021043500000dae0010009c00000dae01008041000000400110021000000db3011001c7000036b7000104300000000204000039000000a00010043f000000800030043f000000c00040043f000000e00020043f0000014000000443000001600030044300000020030000390000018000300443000001a0001004430000004001000039000001c000100443000001e00040044300000060010000390000020000100443000002200020044300000100003004430000000401000039000001200010044300000db601000041000036b60001042e00000dae0030009c00000dae03008041000000c00130021000000df7011001c736b536b00000040f0000000003010019000000600330027000000dae0030019d00000dae0a300197000200000001035500000001002001900000052e0000613d00000e2504a001980000001f05a0018f0000008002400039000003500000613d0000008006000039000000000701034f000000007807043c0000000006860436000000000026004b0000034c0000c13d000000000005004b0000035d0000613d000000000441034f0000000305500210000000000602043300000000065601cf000000000656022f000000000404043b0000010005500089000000000454022f00000000045401cf000000000464019f0000000000420435001c000000010353001d0000000a001d0000001f02a0003900000e250220019700000dd30020009c000006870000213d0000008001200039001b00000001001d000000400010043f0000001d0100002900000dea0010009c0000005b0000213d0000001d01000029000000200010008c0000005b0000413d000000800700043d00000dd10070009c0000005b0000213d0000001d0100002900000080041000390000009f02700039000000000042004b000000000600001900000deb0600804100000deb0540019700000deb02200197000000000852013f000000000052004b000000000200001900000deb0200404100000deb0080009c000000000206c019000000000002004b0000005b0000c13d0000008001700039000000000901043300000dd10090009c000006870000213d00000005029002100000003f0820003900000dd2088001970000001b0880002900000dd10080009c000006870000213d000000400080043f0000001b030000290000000000930435000000a0077000390000000008720019000000000048004b0000005b0000213d000000000009004b00000e850000c13d0035001b0000002d0000000001000415000000340110008a00010005001002180000000001000415000000330110008a0002000500100218003400000000003d000000000600001900000005046002100000003f0140003900000dd401100197000000400200043d0000000005210019000000000015004b0000000007000039000000010700403900000dd10050009c000006870000213d0000000100700190000006870000c13d000000400050043f0000000005620436000000000006004b00000ffd0000c13d00000002010000290000000501100270000000000102001f000000400100043d0000002003000039000000000431043600000000030204330000000000340435000000400410003900000005053002100000000005450019000000000003004b000019bb0000c13d00000000021500490000023a0000013d00000dae0010009c00000dae01008041000000c00110021000000e19011001c736b536b00000040f0000000003010019000000600330027000000dae0030019d00000dae0330019700020000000103550000000100200190000005480000613d000000e00900003900000e25053001980000001f0630018f000000e004500039000003d00000613d000000000701034f000000007807043c0000000009890436000000000049004b000003cc0000c13d000000000006004b000003dd0000613d000000000151034f0000000305600210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000001f0130003900000e2501100197001d00000001001d00000e1a0010009c000006870000213d0000001d01000029000000e007100039000000400070043f00000dea0030009c0000005b0000213d000000200030008c0000005b0000413d000000e00100043d00000dd10010009c0000005b0000213d000000e002300039000000ff03100039000000000023004b000000000400001900000deb0400804100000deb0520019700000deb03300197000000000653013f000000000053004b000000000300001900000deb0300404100000deb0060009c000000000304c019000000000003004b0000005b0000c13d000000e003100039000000000403043300000dd10040009c000006870000213d00000005034002100000003f0530003900000dd205500197000000000575001900000dd10050009c000006870000213d000000400050043f000000000047043500000100011000390000000003130019000000000023004b0000005b0000213d000000000004004b000004150000613d0000000002070019000000001401043400000db10040009c0000005b0000213d00000020022000390000000000420435000000000031004b0000040e0000413d001900000007001d00000dcf0100004100000000001004430000000001000412000000040010044300000060010000390000002400100443000000000100041400000dae0010009c00000dae01008041000000c00110021000000df8011001c7000080050200003936b536b00000040f0000000100200190000026890000613d000000000101043b00000db101100197000000160010006b0000042f0000613d00000019050000290000000006050433000000000006004b000000000700001900000f770000c13d0000000000750435000000400200043d00000e1b01000041001d00000002001d000000000012043500000000010004140000001602000029000000040020008c00000ee70000c13d0000000003000031000000200030008c0000002004000039000000000403401900000f130000013d00000dae0010009c00000dae01008041000000c00110021000000e17011001c736b536b00000040f0000000003010019000000600330027000000dae0030019d00000dae0330019700020000000103550000000100200190000005540000613d000002200900003900000e25043001980000001f0630018f0000022002400039000004520000613d000000000701034f000000007807043c0000000009890436000000000029004b0000044e0000c13d000000000006004b0000045f0000613d000000000141034f0000000304600210000000000602043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f00000000001204350000001f0130003900000e250110019700000dd50010009c000006870000213d0000022002100039000000400020043f00000dea0030009c0000005b0000213d000000200030008c0000005b0000413d000002200400043d00000dd10040009c0000005b0000213d00000220063000390000022007400039000000000376004900000dea0030009c0000005b0000213d000000a00030008c0000005b0000413d00000e180020009c000006870000213d000002c003100039000000400030043f000000000807043300000dd10080009c0000005b0000213d00000000077800190000001f08700039000000000068004b000000000900001900000deb0900804100000deb0880019700000deb0a600197000000000ba8013f0000000000a8004b000000000800001900000deb0800404100000deb00b0009c000000000809c019000000000008004b0000005b0000c13d000000008707043400000dd10070009c000006870000213d0000001f0970003900000e25099001970000003f0990003900000e2505900197000000000535001900000dd10050009c000006870000213d000000400050043f00000000007304350000000005870019000000000065004b0000005b0000213d000002e005100039000000000007004b000004a30000613d00000000060000190000000009560019000000000a860019000000000a0a04330000000000a904350000002006600039000000000076004b0000049c0000413d0000000005570019000000000005043500000000003204350000024003400039000000000303043300000db10030009c0000005b0000213d000002400510003900000000003504350000026003400039000000000303043300000db10030009c0000005b0000213d000002600510003900000000003504350000028003400039000000000303043300000280051000390000000000350435000002a001100039000002a003400039000000000303043300000000003104350000001d01000029000002a20000013d00000dae0030009c00000dae03008041000000c00130021000000de9011001c736b536b00000040f0000000003010019000000600330027000000dae0030019d00000dae0330019700020000000103550000000100200190000005600000613d000000800900003900000e25053001980000001f0630018f0000008004500039000004d20000613d000000000701034f000000007807043c0000000009890436000000000049004b000004ce0000c13d000000000006004b000004df0000613d000000000151034f0000000305600210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000001f0130003900000e250110019700000dd30010009c000006870000213d0000008001100039000000400010043f00000dea0030009c0000005b0000213d000000200030008c0000005b0000413d000000800200043d00000dd10020009c0000005b0000213d00000080033000390000009f04200039000000000034004b000000000500001900000deb0500804100000deb0630019700000deb04400197000000000764013f000000000064004b000000000400001900000deb0400404100000deb0070009c000000000405c019000000000004004b0000005b0000c13d0000008004200039000000000504043300000dd10050009c000006870000213d00000005045002100000003f0640003900000dd206600197000000000616001900000dd10060009c000006870000213d000000400060043f0000000000510435000000a0022000390000000004240019000000000034004b0000005b0000213d000000000005004b000005150000613d0000000003010019000000002502043400000db10050009c0000005b0000213d00000020033000390000000000530435000000000042004b0000050e0000413d000000400200043d00000020030000390000000003320436000000000401043300000000004304350000004003200039000000000004004b000005250000613d00000000050000190000002001100039000000000601043300000db10660019700000000036304360000000105500039000000000045004b0000051e0000413d000000000123004900000dae0010009c00000dae01008041000000600110021000000dae0020009c00000dae020080410000004002200210000000000121019f000036b60001042e0000001f05a0018f00000db006a00198000000400200043d0000000004620019000005390000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000005350000c13d000000000005004b000005460000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000006001a00210000006590000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000054f0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000055b0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000005670000c13d0000064b0000013d00000dae0010009c00000dae01008041000000c00110021000000df7011001c736b536b00000040f0000000003010019000000600330027000000dae0030019d00000dae0330019700020000000103550000000100200190000006340000613d00000e25043001980000001f0530018f0000008002400039000005820000613d0000008006000039000000000701034f000000007807043c0000000006860436000000000026004b0000057e0000c13d000000000005004b0000058f0000613d000000000141034f0000000304500210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001204350000001f0130003900000e2501100197001c00000001001d00000dd30010009c000006870000213d0000001c010000290000008001100039001d00000001001d000000400010043f00000dea0030009c0000005b0000213d000000200030008c0000005b0000413d000000800100043d00000dd10010009c0000005b0000213d00000080023000390000009f03100039000000000023004b000000000400001900000deb0400804100000deb0520019700000deb03300197000000000653013f000000000053004b000000000300001900000deb0300404100000deb0060009c000000000304c019000000000003004b0000005b0000c13d0000008003100039000000000403043300000dd10040009c000006870000213d00000005034002100000003f0530003900000dd2055001970000001d0550002900000dd10050009c000006870000213d000000400050043f0000001d050000290000000000450435000000a0011000390000000003130019000000000023004b0000005b0000213d000000000004004b000005c90000613d0000001d02000029000000001401043400000db10040009c0000005b0000213d00000020022000390000000000420435000000000031004b000005c20000413d00000dcf0100004100000000001004430000000001000412000000040010044300000060010000390000002400100443000000000100041400000dae0010009c00000dae01008041000000c00110021000000df8011001c7000080050200003936b536b00000040f0000000100200190000026890000613d000000000101043b00000db101100197000000160010006b000005e30000613d0000001d010000290000000005010433000000000005004b000000000600001900001a940000c13d0000001d010000290000000000610435002b001d0000002d002a00400000003d00000dfa01000041000000400200043d001d00000002001d0000000000120435002900040000003d00000000010004140000001602000029000000040020008c000019480000c13d000000020100036700000000030000310000195a0000013d00000dae0010009c00000dae01008041000000c00110021000000e15011001c736b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000080057001bf000006060000613d0000008008000039000000000901034f000000009a09043c0000000008a80436000000000058004b000006020000c13d000000000006004b000006130000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000006400000613d0000001f01400039000000600110018f00000080011001bf000000400010043f000000200030008c0000005b0000413d000000800200043d00000db10020009c0000005b0000213d0000000000210435000000400110021000000dd0011001c7000036b60001042e000000a004000039000000000513034f000000000505043b00000db10050009c0000005b0000213d00000000045404360000002001100039000000000021004b000006250000413d000000800200043d000000000102001900000dd10020009c000006870000213d000000400600043d0000000004010019000001d20000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000063b0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000006470000c13d000000000005004b000006580000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000dae0020009c00000dae020080410000004002200210000000000112019f000036b70001043000000df10030009c000006870000213d00000000030000190000004004100039000000400040043f000000200410003900000000000404350000000000010435000000a00430003900000000001404350000002003300039000000000023004b00000bd10000813d000000400100043d00000dfd0010009c000006610000a13d000006870000013d00000df00040009c000006870000213d0000000004000019000000c005100039000000400050043f000000a0051000390000000000050435000000800510003900000000000504350000006005100039000000000005043500000040051000390000000000050435000000200510003900000000000504350000000000010435000000a00540003900000000001504350000002004400039000000000024004b00000cbc0000813d000000400100043d00000df10010009c000006720000a13d00000e1301000041000000000010043f0000004101000039000000040010043f00000dd901000041000036b7000104300000000002000019000000400300043d00000dd50030009c000006870000213d0000022004300039000000400040043f00000200043000390000000000040435000001e0043000390000000000040435000001c0043000390000000000040435000001a00430003900000000000404350000018004300039000000000004043500000160043000390000000000040435000001400430003900000000000404350000012004300039000000000004043500000100043000390000000000040435000000e0043000390000000000040435000000c0043000390000000000040435000000a0043000390000000000040435000000800430003900000000000404350000006004300039000000000004043500000040043000390000000000040435000000200430003900000000000404350000000000030435000000000452001900000000003404350000002002200039000000000012004b0000068e0000413d0000000003000019001800000005001d000000800100043d000000000031004b0000268a0000a13d001500000003001d000000400100043d00000dd50010009c000006870000213d00000015020000290000000502200210001400000002001d000000a002200039000000000202043300000db1072001970000022002100039000000400020043f00000200021000390000000000020435000001e0021000390000000000020435000001c0021000390000000000020435000001a00210003900000000000204350000018002100039000000000002043500000160021000390000000000020435000001400210003900000000000204350000012002100039000000000002043500000100021000390000000000020435000000e0021000390000000000020435000000c0021000390000000000020435000000a0021000390000000000020435000000800210003900000000000204350000006002100039000000000002043500000040021000390000000000020435000000200210003900000000000204350000000000010435000000400a00043d00000dd60100004100000000001a04350000000001000414000000040070008c001a00000007001d000006f70000c13d0000000003000031000000200030008c00000020040000390000000004034019000007270000013d00000dae00a0009c00000dae0200004100000000020a4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c70000000002070019001d0000000a001d36b536b00000040f0000001d0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000007130000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b0000070f0000c13d0000001f07400190000007200000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001b6f0000613d000000190600002900000018050000290000001a070000290000001f01400039000000600110018f000000000ba1001900000000001b004b0000000002000039000000010200403900000dd100b0009c000006870000213d0000000100200190000006870000c13d0000004000b0043f000000200030008c0000005b0000413d00000000020a0433001300000002001d00000dd70200004100000000002b04350000000002000414000000040070008c0000076d0000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000000002070019001d0000000b001d36b536b00000040f0000001d0b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b0019000007570000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b000007530000c13d0000001f07400190000007640000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001b7b0000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a07000029000000000ab1001900000dd100a0009c000006870000213d0000004000a0043f000000200030008c0000005b0000413d00000000090b043300000db10090009c0000005b0000213d00000dd80100004100000000081a04360000000401a0003900000000007104350000000001000414000000040090008c001700000009001d000007820000c13d000000400030008c00000040040000390000000004034019000007b50000013d001c00000008001d00000dae00a0009c00000dae0200004100000000020a4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000dd9011001c70000000002090019001d0000000a001d36b536b00000040f0000001d0a0000290000000003010019000000600330027000000dae03300197000000400030008c00000040040000390000000004034019000000600640019000000000056a00190000079f0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b0000079b0000c13d0000001f07400190000007ac0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000170900002900001b870000613d000000190600002900000018050000290000001a070000290000001c080000290000001f01400039000000e00110018f000000000ba1001900000dd100b0009c000006870000213d0000004000b0043f000000400030008c0000005b0000413d00000000020a0433000000000002004b0000000001000039000000010100c039001200000002001d000000000012004b0000005b0000c13d0000000001080433001100000001001d00000dda0100004100000000001b04350000000001000414000000040070008c0000002004000039000007fd0000613d00000dae00b0009c00000dae0200004100000000020b4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c70000000002070019001d0000000b001d36b536b00000040f0000001d0b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b0019000007e80000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b000007e40000c13d0000001f07400190000007f50000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000170900002900001b930000613d000000190600002900000018050000290000001a070000290000001f01400039000000600110018f000000000ab1001900000dd100a0009c000006870000213d0000004000a0043f000000200030008c0000005b0000413d00000000020b0433001600000002001d00000db10020009c0000005b0000213d00000ddb0200004100000000002a043500000000020004140000001604000029000000040040008c000008420000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000001602000029001d0000000a001d36b536b00000040f0000001d0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000082b0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000008270000c13d0000001f07400190000008380000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000170900002900001b9f0000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000000004a1001900000dd10040009c000006870000213d000000400040043f000000200030008c0000005b0000413d00000000010a0433001000000001001d000000ff0010008c0000005b0000213d000000040090008c000008680000c13d000000000100001900000000080000190000002402400039000000000012043500000ddc02000041000000000b2404360000000402400039000000000072043500000dde0040009c000006870000213d0000004000b0043f0000000002040433000000000002004b0000000004000039000000010400c039000000000042004b0000005b0000c13d00000000021201cf000000000882019f0000000101100039000000ff0110018f000000090010008c00000000040b0019000008500000413d0000002001000039000008c00000013d00000000020000190000000008000019001c00000004001d001d00000008001d0000002401400039001b00000002001d000000000021043500000ddc0100004100000000001404350000000401400039000000000071043500000dae0040009c00000dae0100004100000000010440190000004001100210000000000200041400000dae0020009c00000dae02008041000000c002200210000000000112019f00000ddd011001c7000000000209001936b536b00000040f0000001c0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000088f0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b0000088b0000c13d0000001f074001900000089c0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000170900002900000fe50000613d0000001f01400039000000600110018f000000000ba1001900000000001b004b0000000002000039000000010200403900000dd100b0009c000000190600002900000018050000290000001a070000290000001d08000029000006870000213d0000000100200190000006870000c13d0000004000b0043f000000200030008c0000005b0000413d00000000020a0433000000000002004b0000000004000039000000010400c039000000000042004b0000005b0000c13d0000001b0400002900000000024201cf000000000882019f0000000102400039000000ff0220018f000000080020008c00000000040b00190000086a0000a13d00000ddf0200004100000000002b04350000000002000414000000040070008c001d00000008001d000008fa0000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000000002070019001c0000000b001d36b536b00000040f0000001c0b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b0019000008e20000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b000008de0000c13d0000001f07400190000008ef0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000170900002900001bab0000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000001d08000029000000000ab1001900000dd100a0009c000006870000213d0000004000a0043f000000200030008c0000005b0000413d00000000020b0433000000000002004b000009460000613d00000de00200004100000000002a04350000000002000414000000040070008c0000093c0000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000000002070019001b0000000a001d36b536b00000040f0000001b0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000009240000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000009200000c13d0000001f07400190000009310000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000170900002900001c2f0000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000001d080000290000000001a1001900000dd10010009c000006870000213d000000400010043f000000200030008c0000005b0000413d00000000020a0433001c00000002001d000000000a010019000009470000013d001c00000000001d00000de10100004100000000001a04350000000001000414000000040070008c00000020040000390000097f0000613d00000dae00a0009c00000dae0200004100000000020a4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c70000000002070019001b0000000a001d36b536b00000040f0000001b0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000009690000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000009650000c13d0000001f07400190000009760000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000170900002900001bb70000613d000000190600002900000018050000290000001a070000290000001d080000290000001f01400039000000600110018f000000000ba1001900000dd100b0009c000006870000213d0000004000b0043f000000200030008c0000005b0000413d00000000020a0433001b00000002001d00000de20200004100000000002b04350000000002000414000000040070008c000009c20000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000000002070019000f0000000b001d36b536b00000040f0000000f0b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b0019000009aa0000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b000009a60000c13d0000001f07400190000009b70000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000170900002900001bc30000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000001d08000029000000000ab1001900000dd100a0009c000006870000213d0000004000a0043f000000200030008c0000005b0000413d00000000020b0433000f00000002001d00000de30200004100000000002a04350000000402a0003900000000007204350000000002000414000000040090008c00000a050000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c70000000002090019000e0000000a001d36b536b00000040f0000000e0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000009ed0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000009e90000c13d0000001f07400190000009fa0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000170900002900001bcf0000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000001d08000029000000000ba1001900000dd100b0009c000006870000213d0000004000b0043f000000200030008c0000005b0000413d00000000020a0433001700000002001d00000de40200004100000000002b04350000000402b0003900000000007204350000000002000414000000040090008c00000a470000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c70000000002090019000e0000000b001d36b536b00000040f0000000e0b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b001900000a300000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b00000a2c0000c13d0000001f0740019000000a3d0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001bdb0000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000001d08000029000000000ab1001900000dd100a0009c000006870000213d0000004000a0043f000000200030008c0000005b0000413d00000000020b0433000e00000002001d00000de50200004100000000002a04350000000002000414000000040070008c00000a870000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000000002070019000d0000000a001d36b536b00000040f0000000d0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000a700000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000a6c0000c13d0000001f0740019000000a7d0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001be70000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000001d08000029000000000ba1001900000dd100b0009c000006870000213d0000004000b0043f000000200030008c0000005b0000413d00000000020a0433000d00000002001d00000de60200004100000000002b04350000000002000414000000040070008c00000ac70000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000000002070019000c0000000b001d36b536b00000040f0000000c0b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b001900000ab00000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b00000aac0000c13d0000001f0740019000000abd0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001bf30000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000001d08000029000000000ab1001900000dd100a0009c000006870000213d0000004000a0043f000000200030008c0000005b0000413d00000000020b0433000c00000002001d00000ddf0200004100000000002a04350000000002000414000000040070008c00000b070000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000000002070019000b0000000a001d36b536b00000040f0000000b0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000af00000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000aec0000c13d0000001f0740019000000afd0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001bff0000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000001d08000029000000000ba1001900000dd100b0009c000006870000213d0000004000b0043f000000200030008c0000005b0000413d00000000020a0433000b00000002001d00000de70200004100000000002b04350000000002000414000000040070008c00000b470000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000207001900090000000b001d36b536b00000040f000000090b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b001900000b300000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b00000b2c0000c13d0000001f0740019000000b3d0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001c0b0000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000001d08000029000000000ab1001900000dd100a0009c000006870000213d0000004000a0043f000000200030008c0000005b0000413d00000000090b043300000ddb0200004100000000002a04350000000002000414000000040070008c00000b880000613d000900000009001d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000207001900080000000a001d36b536b00000040f000000080a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000b700000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000b6c0000c13d0000001f0740019000000b7d0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000090900002900001c170000613d0000001f01400039000000600110018f000000190600002900000018050000290000001a070000290000001d080000290000000001a1001900000dd10010009c000006870000213d000000400010043f000000200030008c0000005b0000413d00000000020a0433000000ff0020008c0000005b0000213d00000dd50010009c000006870000213d0000022003100039000000400030043f000002000310003900000000008304350000001003000029000000ff0330018f000001e0041000390000000000340435000001c0031000390000000000230435000001a002100039000000160300002900000000003204350000018002100039000000110300002900000000003204350000016002100039000000120300002900000000003204350000014002100039000000000092043500000120021000390000000b03000029000000000032043500000100021000390000000c030000290000000000320435000000e0021000390000000d030000290000000000320435000000c0021000390000000e030000290000000000320435000000a0021000390000001703000029000000000032043500000080021000390000000f03000029000000000032043500000060021000390000001b03000029000000000032043500000040021000390000001c030000290000000000320435000000200210003900000013030000290000000000320435000000000071043500000000020604330000001503000029000000000032004b0000268a0000a13d000000140250002900000000001204350000000001060433000000000031004b0000268a0000a13d00000001033000390000000a0030006c000006bb0000413d000001e40000013d0000000003000019001c00000003001d0000000502300210001b00000002001d00000019012000290000000101100367000000000501043b00000db10050009c0000005b0000213d000000400100043d00000dfd0010009c000006870000213d0000004002100039000000400020043f000000200210003900000000000204350000000000010435000000400b00043d00000dd70100004100000000001b04350000000001000414000000040050008c001d00000005001d00000bee0000c13d0000000003000031000000200030008c0000002004000039000000000403401900000c1c0000013d00000dae00b0009c00000dae0200004100000000020b4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c7000000000205001900180000000b001d36b536b00000040f000000180b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b001900000c0a0000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b00000c060000c13d0000001f0740019000000c170000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000019240000613d0000001d050000290000001f01400039000000600110018f000000000ab1001900000000001a004b0000000002000039000000010200403900000dd100a0009c000006870000213d0000000100200190000006870000c13d0000004000a0043f000000200030008c0000005b0000413d00000000020b043300000db10020009c0000005b0000213d00000e1b0400004100000000004a04350000000004000414000000040020008c00000c600000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000db3011001c700180000000a001d36b536b00000040f000000180a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000c4c0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000c480000c13d0000001f0740019000000c590000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000019300000613d0000001f01400039000000600110018f0000001d05000029000000000ba1001900000dd100b0009c000006870000213d0000004000b0043f000000200030008c0000005b0000413d00000000020a043300000db10020009c0000005b0000213d00000e1d0400004100000000004b04350000000404b0003900000000005404350000000004000414000000040020008c00000c9f0000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000dd9011001c700180000000b001d36b536b00000040f000000180b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b001900000c8b0000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b00000c870000c13d0000001f0740019000000c980000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000193c0000613d0000001f01400039000000600110018f0000001d050000290000000001b1001900000dd10010009c000006870000213d000000400010043f000000200030008c0000005b0000413d00000dfd0010009c000006870000213d00000000020b04330000004003100039000000400030043f000000200310003900000000002304350000000000510435000000800200043d0000001c03000029000000000032004b0000268a0000a13d0000001b02000029000000a0022000390000000000120435000000800100043d000000000031004b0000268a0000a13d00000001033000390000001a0030006c00000bd20000413d000000400100043d000000870000013d001d0db10030019b0000000003000019001b00000003001d0000000502300210001a00000002001d00000015012000290000000101100367000000000501043b00000db10050009c0000005b0000213d000000400100043d00000df10010009c000006870000213d000000c002100039000000400020043f000000a0021000390000000000020435000000800210003900000000000204350000006002100039000000000002043500000040021000390000000000020435000000200210003900000000000204350000000000010435000000400b00043d00000df20100004100000000001b04350000000401b000390000001d0200002900000000002104350000000001000414000000040050008c001c00000005001d00000ce50000c13d0000000003000031000000200030008c0000002004000039000000000403401900000d130000013d00000dae00b0009c00000dae0200004100000000020b4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000dd9011001c7000000000205001900190000000b001d36b536b00000040f000000190b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b001900000d010000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b00000cfd0000c13d0000001f0740019000000d0e0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001b0f0000613d0000001c050000290000001f01400039000000600110018f000000000ab1001900000000001a004b0000000002000039000000010200403900000dd100a0009c000006870000213d0000000100200190000006870000c13d0000004000a0043f000000200030008c0000005b0000413d00000000020b0433001900000002001d00000df30200004100000000002a04350000000402a000390000001d0400002900000000004204350000000002000414000000040050008c00000d5a0000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c7000000000205001900180000000a001d36b536ab0000040f000000180a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000d460000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000d420000c13d0000001f0740019000000d530000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001b1b0000613d0000001f01400039000000600110018f0000001c05000029000000000ba1001900000dd100b0009c000006870000213d0000004000b0043f000000200030008c0000005b0000413d00000000020a0433001800000002001d00000df40200004100000000002b04350000000402b000390000001d0400002900000000004204350000000002000414000000040050008c00000d9a0000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c7000000000205001900170000000b001d36b536ab0000040f000000170b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b001900000d860000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b00000d820000c13d0000001f0740019000000d930000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001b270000613d0000001f01400039000000600110018f0000001c05000029000000000ab1001900000dd100a0009c000006870000213d0000004000a0043f000000200030008c0000005b0000413d00000000020b0433001700000002001d00000dda0200004100000000002a04350000000002000414000000040050008c00000dd70000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900140000000a001d36b536b00000040f000000140a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000dc30000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000dbf0000c13d0000001f0740019000000dd00000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001b330000613d0000001f01400039000000600110018f0000001c05000029000000000ba1001900000dd100b0009c000006870000213d0000004000b0043f000000200030008c0000005b0000413d00000000060a043300000db10060009c0000005b0000213d00000df20200004100000000002b04350000000402b000390000001d0400002900000000004204350000000002000414000000040060008c00000e1a0000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c7001300000006001d000000000206001900140000000b001d36b536b00000040f000000140b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b001900000e050000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b00000e010000c13d0000001f0740019000000e120000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001b3f0000613d0000001f01400039000000600110018f0000001c050000290000001306000029000000000ab1001900000dd100a0009c000006870000213d0000004000a0043f000000200030008c0000005b0000413d00000000070b04330000002402a00039000000000052043500000df50200004100000000002a04350000000402a000390000001d0400002900000000004204350000000002000414000000040060008c00000e5d0000613d001300000007001d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000ddd011001c7000000000206001900140000000a001d36b536b00000040f000000140a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900000e480000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00000e440000c13d0000001f0740019000000e550000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001b4b0000613d0000001f01400039000000600110018f0000001c0500002900000013070000290000000001a1001900000dd10010009c000006870000213d000000400010043f000000200030008c0000005b0000413d00000df10010009c000006870000213d00000000020a0433000000c003100039000000400030043f000000a0031000390000000000230435000000800210003900000000007204350000006002100039000000170300002900000000003204350000004002100039000000180300002900000000003204350000002002100039000000190300002900000000003204350000000000510435000000800200043d0000001b03000029000000000032004b0000268a0000a13d0000001a02000029000000a0022000390000000000120435000000800100043d000000000031004b0000268a0000a13d0000000103300039000000160030006c00000cbe0000413d000000400100043d0000017a0000013d0000001b09000029000000007207043400000dd10020009c0000005b0000213d000000000a120019000000200da000390000000002d4004900000dea0020009c0000005b0000213d000000a00020008c0000005b0000413d000000400b00043d00000e1800b0009c000006870000213d000000a00cb000390000004000c0043f00000000020d043300000dd10020009c0000005b0000213d000000000dd200190000001f02d00039000000000042004b000000000e00001900000deb0e00804100000deb02200197000000000f52013f000000000052004b000000000200001900000deb0200404100000deb00f0009c00000000020ec019000000000002004b0000005b0000c13d00000000ed0d043400000dd100d0009c000006870000213d0000001f02d0003900000e25022001970000003f0220003900000e25022001970000000002c2001900000dd10020009c000006870000213d000000400020043f0000000000dc04350000000002ed0019000000000042004b0000005b0000213d000000c00fb0003900000000000d004b00000ec00000613d00000000020000190000000003f200190000000006e200190000000006060433000000000063043500000020022000390000000000d2004b00000eb90000413d0000000002fd001900000000000204350000000002cb04360000004003a00039000000000c03043300000db100c0009c0000005b0000213d0000000000c204350000006002a00039000000000202043300000db10020009c0000005b0000213d00000020099000390000004003b0003900000000002304350000008002a0003900000000020204330000006003b000390000000000230435000000a002a0003900000000020204330000008003b0003900000000002304350000000000b90435000000000087004b00000e860000413d0000001b010000290000000006010433003500000001001d0000000001000415000000320110008a00010005001002180000000001000415000000310110008a0002000500100218003200000006001d00000dd10060009c0000039b0000a13d000006870000013d0000001d0200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c7000000160200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000001d0570002900000f020000613d000000000801034f0000001d09000029000000008a08043c0000000009a90436000000000059004b00000efe0000c13d000000000006004b00000f0f0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000000ff10000613d0000001f01400039000000600210018f0000001d01200029000000000021004b0000000002000039000000010200403900000dd10010009c0000001909000029000006870000213d0000000100200190000006870000c13d000000400010043f000000200030008c0000005b0000413d0000001d02000029000000000202043300000db10020009c0000005b0000213d000000000609043300000dd10060009c000006870000213d00000005046002100000003f0540003900000dd205500197000000000515001900000dd10050009c000006870000213d000000400050043f0000000005610436000000000006004b00000f400000613d0000000006000019000000400700043d00000dfd0070009c000006870000213d0000004008700039000000400080043f000000200870003900000000000804350000000000070435000000000865001900000000007804350000002006600039000000000046004b00000f330000413d000000400400043d001200000004001d00000dfe0040009c000006870000213d00000012050000290000006004500039000000400040043f0000004004500039001400000004001d000000000014043500000016010000290000000001150436001100000001001d00000000000104350000000001090433000000000001004b001a00000000001d00001c3b0000c13d00000011040000290000001a0100002900000000001404350000002002000039000000400100043d00000000022104360000001203000029000000000303043300000db103300197000000000032043500000000020404330000004003100039000000000023043500000014020000290000000002020433000000600310003900000060040000390000000000430435000000800310003900000000040204330000000000430435000000a003100039000000000004004b0000009f0000613d000000000500001900000020022000390000000006020433000000007606043400000db10660019700000000066304360000000007070433000000000076043500000040033000390000000105500039000000000045004b00000f6b0000413d0000009f0000013d0000001d01000029000001000810003900000df909000041000000000a0000190000000007000019001800000006001d001700000008001d00000f820000013d000000010aa0003900000000006a004b0000042e0000813d00000000010504330000000000a1004b0000268a0000a13d0000000501a00210000000000b81001900000000020b0433000000400c00043d00000000009c0435000000000100041400000db102200197000000040020008c00000f930000c13d0000000003000031000000200030008c0000002004000039000000000403401900000fc90000013d001c0000000b001d001d0000000a001d001a00000007001d00000dae00c0009c00000dae0300004100000000030c4019000000400330021000000dae0010009c00000dae01008041000000c001100210000000000131019f00000db3011001c7001b0000000c001d36b536b00000040f0000001b0c0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056c001900000fb10000613d000000000701034f00000000080c0019000000007907043c0000000008980436000000000058004b00000fad0000c13d0000001f0740019000000fbe0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000190500002900000df9090000410000001d0a0000290000001c0b00002900001b570000613d00000018060000290000001a0700002900000017080000290000001f01400039000000600210018f0000000001c20019000000000021004b0000000002000039000000010200403900000dd10010009c000006870000213d0000000100200190000006870000c13d000000400010043f000000200030008c0000005b0000413d00000000010c0433000000000001004b00000f7f0000613d00000000010504330000000000a1004b0000268a0000a13d000000000071004b0000268a0000a13d0000000501700210000000000181001900000000020b043300000db1022001970000000000210435000000010770003900000f7f0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000fec0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000ff80000c13d0000064b0000013d000000600d0000390000000006000019000000400700043d00000e1f0070009c000006870000213d000001a001700039000000400010043f00000180017000390000000000d10435000000e0017000390000000000d10435000000c0017000390000000000d10435000000a0017000390000000000d104350000000001d70436000001600370003900000000000304350000014003700039000000000003043500000120037000390000000000030435000001000370003900000000000304350000008003700039000000000003043500000060037000390000000000030435000000400370003900000000000304350000000000010435000000000165001900000000007104350000002006600039000000000046004b00000fff0000413d00000002010000290000000501100270000000000102001f003000000000003d000000000400001900000035050000290000000001050433000000000041004b0000268a0000a13d000000400200043d00000e1f0020009c000006870000213d00000005014002100000000001510019000400360000002d00000020011000390000000004010433000001a001200039000000400010043f00000180012000390000000000d10435000000e0012000390000000000d10435000000c0012000390000000000d10435000000a0012000390000000000d104350000000001d20436000001600320003900000000000304350000014003200039000000000003043500000120032000390000000000030435000001000320003900000000000304350000008003200039000000000003043500000060032000390000000000030435000000400220003900000000000204350000000000010435000300000004001d0000004001400039000500000001001d0000000001010433000000400900043d00000df6020000410000000000290435000000000200041400000db101100197001a00000001001d000000040010008c0000001c0100035f0000001d080000290000106f0000613d00000dae0090009c001d00000009001d00000dae010000410000000001094019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000001a0200002936b536b00000040f0000000003010019000000600330027000000dae0030019d00000dae0830019700020000000103550000000100200190000026960000613d000000600d0000390000001d0900002900000e25048001980000000002490019000010780000613d000000000501034f0000000006090019000000005305043c0000000006360436000000000026004b000010740000c13d0000001f05800190000010850000613d000000000141034f0000000303500210000000000402043300000000043401cf000000000434022f000000000101043b0000010003300089000000000131022f00000000013101cf000000000141019f000000000012043500000000030800190000001f0180003900000e250110019700000000040900190000000002910019000000000012004b00000000010000390000000101004039001400000002001d00000dd10020009c000006870000213d0000000100100190000006870000c13d0000001401000029000000400010043f00000dea0030009c0000005b0000213d000000200030008c0000005b0000413d000000000104043300000dd10010009c0000005b0000213d000000000243001900000000014100190000001f03100039000000000023004b000000000400001900000deb0400804100000deb0330019700000deb05200197000000000653013f000000000053004b000000000300001900000deb0300404100000deb0060009c000000000304c019000000000003004b0000005b0000c13d000000001301043400000dd10030009c000006870000213d00000005043002100000003f0540003900000dd205500197000000140550002900000dd10050009c000006870000213d000000400050043f00000014050000290000000003350436000600000003001d0000000003140019000000000023004b0000005b0000213d000000000031004b000010c50000813d0000001402000029000000001401043400000db10040009c0000005b0000213d00000020022000390000000000420435000000000031004b000010be0000413d00000dcf010000410000000000100443000000000100041200000004001004430000002400d00443000000000100041400000dae0010009c00000dae01008041000000c00110021000000df8011001c7000080050200003936b536b00000040f0000000100200190000026890000613d00000014020000290000000004020433000000000101043b00000db1011001970000001a0010006b000010dc0000c13d0000000003040019000000600d000039000011520000013d000000000004004b000000600d0000390000114f0000613d00000000050000190000000003000019001b00000004001d000010e70000013d0000001d050000290000000105500039000000000045004b000011500000813d00000014010000290000000001010433000000000051004b0000268a0000a13d001600000003001d00000005015002100000000601100029001c00000001001d0000000002010433000000400a00043d00000df90100004100000000001a0435000000000100041400000db102200197000000040020008c001d00000005001d000010fd0000c13d0000000003000031000000200030008c000000200400003900000000040340190000112a0000013d00000dae00a0009c00000dae0300004100000000030a4019000000400330021000000dae0010009c00000dae01008041000000c001100210000000000131019f00000db3011001c7001a0000000a001d36b536b00000040f0000001a0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000011180000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000011140000c13d0000001f07400190000011250000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001e4a0000613d0000001f01400039000000600210018f00000000040a00190000000001a20019000000000021004b0000000002000039000000010200403900000dd10010009c000006870000213d0000000100200190000006870000c13d000000400010043f000000200030008c0000005b0000413d0000000001040433000000000001004b00000016030000290000001b04000029000010e30000613d000000140100002900000000010104330000001d05000029000000000051004b0000268a0000a13d000000000031004b0000268a0000a13d000000050130021000000006011000290000001c02000029000000000202043300000db102200197000000000021043500000001033000390000000105500039000000000045004b000010e70000413d000011500000013d000000000300001900000014010000290000000000310435001600000003001d00000dd10030009c000006870000213d000000160100002900000005011002100000003f0210003900000dd202200197000000400300043d0000000002230019001500000003001d000000000032004b0000000003000039000000010300403900000dd10020009c000006870000213d0000000100300190000006870000c13d000000400020043f000000150200002900000016030000290000000002320436001300000002001d000000000003004b000000200700008a000016c40000613d0000000002000019000000400300043d00000dd50030009c000006870000213d0000022004300039000000400040043f00000200043000390000000000040435000001e0043000390000000000040435000001c0043000390000000000040435000001a00430003900000000000404350000018004300039000000000004043500000160043000390000000000040435000001400430003900000000000404350000012004300039000000000004043500000100043000390000000000040435000000e0043000390000000000040435000000c0043000390000000000040435000000a0043000390000000000040435000000800430003900000000000404350000006004300039000000000004043500000040043000390000000000040435000000200430003900000000000404350000000000030435000000130420002900000000003404350000002002200039000000000012004b0000116c0000413d000000000400001900000014010000290000000001010433000000000041004b0000268a0000a13d001700000004001d000000400100043d00000dd50010009c000006870000213d00000017020000290000000503200210001200000003001d0000000602300029000000000202043300000db1052001970000022002100039000000400020043f00000200021000390000000000020435000001e0021000390000000000020435000001c0021000390000000000020435000001a00210003900000000000204350000018002100039000000000002043500000160021000390000000000020435000001400210003900000000000204350000012002100039000000000002043500000100021000390000000000020435000000e0021000390000000000020435000000c0021000390000000000020435000000a0021000390000000000020435000000800210003900000000000204350000006002100039000000000002043500000040021000390000000000020435000000200210003900000000000204350000000000010435000000400a00043d00000dd60100004100000000001a04350000000001000414000000040050008c001a00000005001d000011d50000c13d0000000003000031000000200030008c00000020040000390000000004034019000012040000013d00000dae00a0009c00000dae0200004100000000020a4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c70000000002050019001d0000000a001d36b536b00000040f0000001d0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000011f10000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000011ed0000c13d0000001f07400190000011fe0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001d8a0000613d0000001a050000290000001f01400039000000600110018f00000000060a00190000000004a10019000000000014004b00000000020000390000000102004039001d00000004001d00000dd10040009c000006870000213d0000000100200190000006870000c13d0000001d02000029000000400020043f000000200030008c0000005b0000413d0000000002060433001100000002001d00000dd7020000410000001d0a00002900000000002a04350000000002000414000000040050008c0000124c0000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001936b536b00000040f0000001d0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000012370000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000012330000c13d0000001f07400190000012440000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001d720000613d0000001f01400039000000600110018f0000001a050000290000000001a10019001c00000001001d00000dd10010009c000006870000213d0000001c01000029000000400010043f000000200030008c0000005b0000413d0000001d010000290000000001010433001900000001001d00000db10010009c0000005b0000213d00000dd8010000410000001c0a00002900000000011a0436001b00000001001d0000000401a00039000000000051043500000000010004140000001902000029000000040020008c000012670000c13d000000400030008c00000040040000390000000004034019000012940000013d00000dae00a0009c00000dae0300004100000000030a4019000000400330021000000dae0010009c00000dae01008041000000c001100210000000000131019f00000dd9011001c736b536b00000040f0000001c0a0000290000000003010019000000600330027000000dae03300197000000400030008c00000040040000390000000004034019000000600640019000000000056a0019000012810000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b0000127d0000c13d0000001f074001900000128e0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001d960000613d0000001a050000290000001f01400039000000e00110018f0000000001a10019001d00000001001d00000dd10010009c000006870000213d0000001d01000029000000400010043f000000400030008c0000005b0000413d0000001c010000290000000002010433000000000002004b0000000001000039000000010100c039001000000002001d000000000012004b0000005b0000c13d0000001b010000290000000001010433000f00000001001d00000dda010000410000001d0a00002900000000001a04350000000001000414000000040050008c0000002004000039000012de0000613d00000dae00a0009c00000dae0200004100000000020a4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c7000000000205001936b536b00000040f0000001d0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000012cb0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000012c70000c13d0000001f07400190000012d80000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001d7e0000613d0000001a050000290000001f01400039000000600110018f0000000002a10019001c00000002001d00000dd10020009c000006870000213d0000001c02000029000000400020043f000000200030008c0000005b0000413d0000001d020000290000000002020433001800000002001d00000db10020009c0000005b0000213d00000ddb020000410000001c0a00002900000000002a043500000000020004140000001804000029000000040040008c000013240000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000180200002936b536b00000040f0000001c0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000130f0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b0000130b0000c13d0000001f074001900000131c0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001da20000613d0000001f01400039000000600110018f0000001a050000290000000004a1001900000dd10040009c000006870000213d000000400040043f000000200030008c0000005b0000413d0000001c010000290000000001010433000e00000001001d000000ff0010008c0000005b0000213d0000001901000029000000040010008c0000134c0000c13d000000000100001900000000060000190000002402400039000000000012043500000ddc02000041000000000a2404360000000402400039000000000052043500000dde0040009c000006870000213d0000004000a0043f0000000002040433000000000002004b0000000004000039000000010400c039000000000042004b0000005b0000c13d00000000021201cf000000000662019f0000000101100039000000ff0110018f000000090010008c00000000040a0019000013340000413d0000002001000039000013a20000013d00000000020000190000000006000019001c00000004001d001d00000006001d0000002401400039001b00000002001d000000000021043500000ddc0100004100000000001404350000000401400039000000000051043500000dae0040009c00000dae0100004100000000010440190000004001100210000000000200041400000dae0020009c00000dae02008041000000c002200210000000000112019f00000ddd011001c7000000190200002936b536b00000040f0000001c0b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b0019000013730000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b0000136f0000c13d0000001f07400190000000600d000039000013810000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000001b630000613d0000001f01400039000000600110018f000000000ab1001900000000001a004b0000000002000039000000010200403900000dd100a0009c0000001a050000290000001d06000029000006870000213d0000000100200190000006870000c13d0000004000a0043f000000200030008c0000005b0000413d00000000020b0433000000000002004b0000000004000039000000010400c039000000000042004b0000005b0000c13d0000001b0400002900000000024201cf000000000662019f0000000102400039000000ff0220018f000000080020008c00000000040a00190000134e0000a13d00000ddf0200004100000000002a04350000000002000414000000040050008c001d00000006001d000013da0000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000000002050019001c0000000a001d36b536b00000040f0000001c0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000013c40000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000013c00000c13d0000001f07400190000013d10000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001dea0000613d0000001f01400039000000600110018f0000001a050000290000001d060000290000000002a10019001c00000002001d00000dd10020009c000006870000213d0000001c02000029000000400020043f000000200030008c0000005b0000413d00000000020a0433000000000002004b000014270000613d00000de0020000410000001c0a00002900000000002a04350000000002000414000000040050008c0000141c0000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001936b536b00000040f0000001c0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000014060000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000014020000c13d0000001f07400190000014130000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001e260000613d0000001f01400039000000600110018f0000001a050000290000001d060000290000000001a1001900000dd10010009c000006870000213d000000400010043f000000200030008c0000005b0000413d0000001c020000290000000002020433000d00000002001d000000000a010019000014290000013d000d00000000001d0000001c0a00002900000de10100004100000000001a04350000000001000414000000040050008c00000020040000390000145f0000613d00000dae00a0009c00000dae0200004100000000020a4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c70000000002050019001c0000000a001d36b536b00000040f0000001c0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000144b0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000014470000c13d0000001f07400190000014580000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001df60000613d0000001a050000290000001d060000290000001f01400039000000600110018f00000000020a00190000000004a10019001c00000004001d00000dd10040009c000006870000213d0000001c04000029000000400040043f000000200030008c0000005b0000413d0000000002020433000c00000002001d00000de2020000410000001c0a00002900000000002a04350000000002000414000000040050008c000014a30000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001936b536b00000040f0000001c0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000148d0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000014890000c13d0000001f074001900000149a0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001dae0000613d0000001f01400039000000600110018f0000001a050000290000001d060000290000000002a10019001b00000002001d00000dd10020009c000006870000213d0000001b02000029000000400020043f000000200030008c0000005b0000413d0000001c020000290000000002020433000b00000002001d00000de3020000410000001b0a00002900000000002a04350000000402a00039000000000052043500000000040004140000001902000029000000040020008c000014e70000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000dd9011001c736b536b00000040f0000001b0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000014d10000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000014cd0000c13d0000001f07400190000014de0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001e020000613d0000001f01400039000000600110018f0000001a050000290000001d060000290000000002a10019001c00000002001d00000dd10020009c000006870000213d0000001c02000029000000400020043f000000200030008c0000005b0000413d0000001b020000290000000002020433000a00000002001d00000de4020000410000001c0a00002900000000002a04350000000402a00039000000000052043500000000040004140000001902000029000000040020008c0000152b0000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000dd9011001c736b536b00000040f0000001c0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000015150000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000015110000c13d0000001f07400190000015220000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001dba0000613d0000001f01400039000000600110018f0000001a050000290000001d060000290000000002a10019001b00000002001d00000dd10020009c000006870000213d0000001b02000029000000400020043f000000200030008c0000005b0000413d0000001c020000290000000002020433001900000002001d00000de5020000410000001b0a00002900000000002a04350000000002000414000000040050008c0000156d0000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001936b536b00000040f0000001b0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000015570000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000015530000c13d0000001f07400190000015640000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001e0e0000613d0000001f01400039000000600110018f0000001a050000290000001d060000290000000002a10019001c00000002001d00000dd10020009c000006870000213d0000001c02000029000000400020043f000000200030008c0000005b0000413d0000001b020000290000000002020433000900000002001d00000de6020000410000001c0a00002900000000002a04350000000002000414000000040050008c000015af0000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001936b536b00000040f0000001c0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000015990000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000015950000c13d0000001f07400190000015a60000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001dc60000613d0000001f01400039000000600110018f0000001a050000290000001d060000290000000002a10019001b00000002001d00000dd10020009c000006870000213d0000001b02000029000000400020043f000000200030008c0000005b0000413d0000001c020000290000000002020433000800000002001d00000ddf020000410000001b0a00002900000000002a04350000000002000414000000040050008c000015f10000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001936b536b00000040f0000001b0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000015db0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000015d70000c13d0000001f07400190000015e80000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001e1a0000613d0000001f01400039000000600110018f0000001a050000290000001d060000290000000002a10019001c00000002001d00000dd10020009c000006870000213d0000001c02000029000000400020043f000000200030008c0000005b0000413d0000001b020000290000000002020433000700000002001d00000de7020000410000001c0a00002900000000002a04350000000002000414000000040050008c000016330000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001936b536b00000040f0000001c0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000161d0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000016190000c13d0000001f074001900000162a0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001dd20000613d0000001f01400039000000600110018f0000001a050000290000001d060000290000000002a10019001b00000002001d00000dd10020009c000006870000213d0000001b02000029000000400020043f000000200030008c0000005b0000413d0000001c020000290000000002020433001c00000002001d00000ddb020000410000001b0a00002900000000002a04350000000002000414000000040050008c000016750000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001936b536b00000040f0000001b0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a00190000165f0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b0000165b0000c13d0000001f074001900000166c0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000600d00003900001dde0000613d0000001f01400039000000600110018f0000001a050000290000001d060000290000000001a1001900000dd10010009c000006870000213d000000400010043f000000200030008c0000005b0000413d0000001b020000290000000002020433000000ff0020008c0000005b0000213d00000dd50010009c000006870000213d0000022003100039000000400030043f000002000310003900000000006304350000000e03000029000000ff0330018f000001e0041000390000000000340435000001c0031000390000000000230435000001a0021000390000001803000029000000000032043500000180021000390000000f03000029000000000032043500000160021000390000001003000029000000000032043500000140021000390000001c030000290000000000320435000001200210003900000007030000290000000000320435000001000210003900000008030000290000000000320435000000e00210003900000009030000290000000000320435000000c00210003900000019030000290000000000320435000000a0021000390000000a03000029000000000032043500000080021000390000000b03000029000000000032043500000060021000390000000c03000029000000000032043500000040021000390000000d0300002900000000003204350000002002100039000000110300002900000000003204350000000000510435000000150200002900000000020204330000001704000029000000000042004b000000200700008a00000016030000290000268a0000a13d00000012050000290000001302500029000000000012043500000015010000290000000001010433000000000041004b0000268a0000a13d0000000104400039000000000034004b000011980000413d00000005010000290000000001010433000000400900043d00000e2002000041000000000029043500000db101100197000000040290003900000000001204350000000001000414000000040200002900000db102200197000000040020008c000016d40000c13d00000002010003670000000008000031000016e90000013d00000dae0090009c001d00000009001d00000dae030000410000000003094019000000400330021000000dae0010009c00000dae01008041000000c001100210000000000131019f00000dd9011001c736b536b00000040f0000000003010019000000600330027000000dae0030019d00000dae0830019700020000000103550000000100200190000026a40000613d000000200700008a000000600d0000390000001d0900002900000000047801700000000002490019000016f20000613d000000000501034f0000000006090019000000005305043c0000000006360436000000000026004b000016ee0000c13d0000001f05800190000016ff0000613d000000000641034f0000000303500210000000000402043300000000043401cf000000000434022f000000000506043b0000010003300089000000000535022f00000000033501cf000000000343019f0000000000320435001c000000010353001d00000008001d0000001f01800039000000000171016f00000000030900190000000002910019000000000012004b0000000004000039000000010400403900000dd10020009c000006870000213d0000000100400190000006870000c13d000000400020043f0000001d0100002900000dea0010009c0000005b0000213d0000001d01000029000000200010008c0000005b0000413d000000000503043300000dd10050009c0000005b0000213d0000001d043000290000000005350019000000000654004900000dea0060009c0000005b0000213d000000600060008c0000005b0000413d00000dfe0020009c000006870000213d0000006006200039000000400060043f000000008705043400000dd10070009c0000005b0000213d00000000095700190000001f01900039000000000041004b000000000300001900000deb0300804100000deb0110019700000deb07400197000000000a71013f000000000071004b000000000100001900000deb0100404100000deb00a0009c000000000103c019000000000001004b0000005b0000c13d00000000a909043400000dd10090009c000006870000213d0000001f0190003900000e25011001970000003f0110003900000e2501100197000000000b61001900000dd100b0009c000006870000213d0000004000b0043f00000000009604350000000001a90019000000000041004b0000005b0000213d000000800b200039000000000009004b0000174d0000613d000000000c0000190000000001bc00190000000003ac001900000000030304330000000000310435000000200cc0003900000000009c004b000017460000413d0000000001b9001900000000000104350000000006620436000000000808043300000dd10080009c0000005b0000213d00000000085800190000001f01800039000000000041004b000000000300001900000deb0300804100000deb01100197000000000971013f000000000071004b000000000100001900000deb0100404100000deb0090009c000000000103c019000000000001004b0000005b0000c13d000000009808043400000dd10080009c000006870000213d0000001f0180003900000e25011001970000003f0110003900000e2501100197000000400a00043d000000000b1a00190000000000ab004b000000000c000039000000010c00403900000dd100b0009c000006870000213d0000000100c00190000006870000c13d0000004000b0043f000000000b8a04360000000001980019000000000041004b0000005b0000213d000000000008004b000017800000613d000000000c0000190000000001bc001900000000039c001900000000030304330000000000310435000000200cc0003900000000008c004b000017790000413d00000000018b001900000000000104350000000000a604350000004001500039000000000801043300000dd10080009c0000005b0000213d00000000055800190000001f01500039000000000041004b000000000300001900000deb0300804100000deb01100197000000000871013f000000000071004b000000000100001900000deb0100404100000deb0080009c000000000103c019000000000001004b0000005b0000c13d000000007505043400000dd10050009c000006870000213d0000001f0150003900000e25011001970000003f0110003900000e2501100197000000400300043d0000000008130019001800000003001d000000000038004b0000000009000039000000010900403900000dd10080009c000006870000213d0000000100900190000006870000c13d000000400080043f000000180100002900000000085104360000000001750019000000000041004b0000005b0000213d000000000005004b000017b60000613d000000000400001900000000018400190000000003740019000000000303043300000000003104350000002004400039000000000054004b000017af0000413d000000000158001900000000000104350000004001200039000000180300002900000000003104350000000001020433001400000001001d0000000001060433001100000001001d000000030200002900000080012000390000000001010433001200000001001d00000060012000390000000001010433001300000001001d00000020012000390000000001010433001600000001001d0000000001020433001700000001001d00000005010000290000000001010433000000400a00043d00000e1b0200004100000000002a0435000000000300041400000db102100197000000040020008c0000001d01000029001b00000002001d000017da0000c13d000000200010008c00000020040000390000000004014019000018090000013d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0030009c00000dae03008041000000c003300210000000000113019f00000db3011001c7001a0000000a001d36b536b00000040f0000001a0a0000290000000003010019000000600330027000000dae09300197000000200090008c00000020040000390000000004094019000000200640019000000000056a0019000017f50000613d000000000701034f00000000080a0019000000007307043c0000000008380436000000000058004b000017f10000c13d0000001f07400190000018020000613d000000000861034f0000000303700210000000000605043300000000063601cf000000000636022f000000000708043b0000010003300089000000000737022f00000000033701cf000000000363019f0000000000350435000000000009001f001c00000001035300020000000103550000000100200190000000600d000039000026c00000613d001d00000009001d0000001f01400039000000600310018f00000000020a00190000000001a30019000000000031004b00000000040000390000000104004039001a00000001001d00000dd10010009c000006870000213d0000000100400190000006870000c13d0000001a01000029000000400010043f0000001d01000029000000200010008c0000005b0000413d0000000001020433001000000001001d00000db10010009c0000005b0000213d00000e21010000410000001a0a00002900000000001a043500000000040004140000001b02000029000000040020008c000018550000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000db3011001c736b536b00000040f0000001a0a0000290000000003010019000000600330027000000dae09300197000000200090008c00000020040000390000000004094019000000200640019000000000056a00190000183f0000613d000000000701034f00000000080a0019000000007307043c0000000008380436000000000058004b0000183b0000c13d0000001f074001900000184c0000613d000000000861034f0000000303700210000000000605043300000000063601cf000000000636022f000000000708043b0000010003300089000000000737022f00000000033701cf000000000363019f0000000000350435001d00000009001d000000000009001f001c00000001035300020000000103550000000100200190000000600d000039000026d90000613d0000001f01400039000000600310018f0000000001a30019001900000001001d00000dd10010009c000006870000213d0000001901000029000000400010043f0000001d01000029000000200010008c0000005b0000413d0000001a010000290000000001010433000f00000001001d00000e2201000041000000190a00002900000000001a043500000000040004140000001b02000029000000040020008c000018980000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000db3011001c736b536b00000040f000000190a0000290000000003010019000000600330027000000dae09300197000000200090008c00000020040000390000000004094019000000200640019000000000056a0019000018820000613d000000000701034f00000000080a0019000000007307043c0000000008380436000000000058004b0000187e0000c13d0000001f074001900000188f0000613d000000000861034f0000000303700210000000000605043300000000063601cf000000000636022f000000000708043b0000010003300089000000000737022f00000000033701cf000000000363019f0000000000350435001d00000009001d000000000009001f001c00000001035300020000000103550000000100200190000000600d000039000026e60000613d0000001f01400039000000600310018f0000000001a30019001a00000001001d00000dd10010009c000006870000213d0000001a01000029000000400010043f0000001d01000029000000200010008c0000005b0000413d00000019010000290000000001010433001900000001001d00000e23010000410000001a0a00002900000000001a043500000000040004140000001b02000029000000040020008c000018db0000613d00000dae00a0009c00000dae0100004100000000010a4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000db3011001c736b536b00000040f0000001a0a0000290000000003010019000000600330027000000dae09300197000000200090008c00000020040000390000000004094019000000200640019000000000056a0019000018c50000613d000000000701034f00000000080a0019000000007307043c0000000008380436000000000058004b000018c10000c13d0000001f07400190000018d20000613d000000000861034f0000000303700210000000000605043300000000063601cf000000000636022f000000000708043b0000010003300089000000000737022f00000000033701cf000000000363019f0000000000350435001d00000009001d000000000009001f001c00000001035300020000000103550000000100200190000000600d000039000026f30000613d0000001f01400039000000600310018f0000000004a3001900000dd10040009c000006870000213d000000400040043f0000001d01000029000000200010008c0000005b0000413d00000e1f0040009c000006870000213d0000001a010000290000000001010433000001a002400039000000400020043f0000018002400039000000150300002900000000003204350000016002400039000000000012043500000140014000390000001902000029000000000021043500000120014000390000000f020000290000000000210435000001000140003900000010020000290000000000210435000000e00140003900000018020000290000000000210435000000c00140003900000011020000290000000000210435000000a0014000390000001402000029000000000021043500000080014000390000001202000029000000000021043500000060014000390000001302000029000000000021043500000040014000390000001b020000290000000000210435000000160100002900000db101100197000000200240003900000000001204350000001701000029000000000014043500000002010000290000000501100270000000000201003100000000010204330000003005000029000000000051004b0000268a0000a13d00000005015002100000000001120019000000200110003900000000004104350000000001020433000000000051004b0000268a0000a13d003000010050003d0000000104500039000000010100002900000005011002700000000001010031000000000014004b000010260000413d000003ae0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000192b0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000019370000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000019430000c13d0000064b0000013d0000001d0200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c7000000160200002936b536b00000040f0000000003010019000000600330027000000dae0030019d00000dae033001970002000000010355000000010020019000001b030000613d00000e25043001980000001f0530018f0000001d02400029000019640000613d000000000601034f0000001d07000029000000006806043c0000000007870436000000000027004b000019600000c13d000000000005004b000019710000613d000000000141034f0000000304500210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001204350000001f0130003900000e25011001970000001d02100029000000000012004b00000000010000390000000101004039001c00000002001d00000dd10020009c000006870000213d0000000100100190000006870000c13d0000001c01000029000000400010043f00000dea0030009c0000005b0000213d000000200030008c0000005b0000413d0000001d01000029000000000101043300000dd10010009c0000005b0000213d0000001d053000290000001d011000290000001f02100039000000000052004b000000000300001900000deb0300804100000deb0220019700000deb04500197000000000642013f000000000042004b000000000200001900000deb0200404100000deb0060009c000000000203c019000000000002004b0000005b0000c13d000000003201043400000dd10020009c000006870000213d00000005012002100000003f0410003900000dd2044001970000001c0640002900000dd10060009c000006870000213d000000400060043f0000001c0600002900000000002604350000000006310019000000000056004b0000005b0000213d000000000063004b00001d0c0000813d0000001c01000029000000003203043400000db10020009c0000005b0000213d00000020011000390000000000210435000000000063004b000019a80000413d0000001c010000290000000002010433002600000001001d00000dd10020009c000006870000213d0000000001000415000000280110008a000800050010021800000005012002100000003f0310003900000dd20430019700001d100000013d0000000007000019000019c00000013d0000000107700039000000000037004b000003b80000813d0000000008150049000000400880008a00000000048404360000002002200039000000000802043300000000c9080434000001a006000039000000000b650436000001a00a50003900000000d909043400000000009a0435000001c00a500039000000000009004b000019d60000613d000000000e000019000000000fae00190000000006ed0019000000000606043300000000006f0435000000200ee0003900000000009e004b000019cf0000413d0000000006a90019000000000006043500000000060c043300000db10660019700000000006b04350000004006800039000000000606043300000db106600197000000400b50003900000000006b043500000060068000390000000006060433000000600b50003900000000006b043500000080068000390000000006060433000000800b50003900000000006b04350000001f0690003900000e25066001970000000006a600190000000009560049000000a00a500039000000a00b800039000000000b0b043300000000009a043500000000ba0b04340000000009a6043600000000000a004b000019fc0000613d000000000c00001900000000069c0019000000000dcb0019000000000d0d04330000000000d60435000000200cc000390000000000ac004b000019f50000413d00000000069a001900000000000604350000001f06a0003900000e25066001970000000006960019000000c0098000390000000009090433000000000a560049000000c00b5000390000000000ab043500000000ba0904340000000009a6043600000000000a004b00001a120000613d000000000c00001900000000069c0019000000000dcb0019000000000d0d04330000000000d60435000000200cc000390000000000ac004b00001a0b0000413d00000000069a001900000000000604350000001f06a0003900000e25066001970000000006960019000000e0098000390000000009090433000000000a560049000000e00b5000390000000000ab043500000000ba0904340000000009a6043600000000000a004b00001a280000613d000000000c00001900000000069c0019000000000dcb0019000000000d0d04330000000000d60435000000200cc000390000000000ac004b00001a210000413d00000000069a001900000000000604350000010006800039000000000606043300000db106600197000001000b50003900000000006b043500000120068000390000000006060433000001200b50003900000000006b043500000140068000390000000006060433000001400b50003900000000006b043500000160068000390000000006060433000001600b50003900000000006b04350000001f06a0003900000e250660019700000000069600190000000009560049000001800550003900000180088000390000000008080433000000000095043500000000090804330000000005960436000000000009004b000019bd0000613d000000000a0000190000002008800039000000000b08043300000000c60b043400000db1066001970000000006650436000000000c0c04330000000000c604350000004006b000390000000006060433000000400c50003900000000006c04350000006006b000390000000006060433000000600c50003900000000006c04350000008006b000390000000006060433000000800c50003900000000006c0435000000a006b000390000000006060433000000a00c50003900000000006c0435000000c006b000390000000006060433000000c00c50003900000000006c0435000000e006b000390000000006060433000000e00c50003900000000006c04350000010006b000390000000006060433000001000c50003900000000006c04350000012006b000390000000006060433000001200c50003900000000006c04350000014006b000390000000006060433000001400c50003900000000006c04350000016006b000390000000006060433000000000006004b0000000006000039000000010600c039000001600c50003900000000006c04350000018006b000390000000006060433000001800c50003900000000006c0435000001a006b00039000000000606043300000db106600197000001a00c50003900000000006c0435000001c006b000390000000006060433000001c00c50003900000000006c0435000001e006b000390000000006060433000001e00c50003900000000006c04350000020006b000390000000006060433000002000b50003900000000006b04350000022005500039000000010aa0003900000000009a004b00001a480000413d000019bd0000013d0000001c01000029000000a00710003900000df90800004100000000090000190000000006000019001800000005001d001700000007001d00001a9f0000013d0000000109900039000000000059004b000005e10000813d0000001d010000290000000001010433000000000091004b0000268a0000a13d0000000501900210000000000a71001900000000020a0433000000400b00043d00000000008b0435000000000100041400000db102200197000000040020008c00001ab10000c13d0000000003000031000000200030008c0000002004000039000000000403401900001ae60000013d001b0000000a001d001c00000009001d001900000006001d00000dae00b0009c00000dae0300004100000000030b4019000000400330021000000dae0010009c00000dae01008041000000c001100210000000000131019f00000db3011001c7001a0000000b001d36b536b00000040f0000001a0b0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056b001900001acf0000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b00001acb0000c13d0000001f0740019000001adc0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000001c090000290000001b0a00002900001c230000613d00000018050000290000001906000029000000170700002900000df9080000410000001f01400039000000600210018f0000000001b20019000000000021004b0000000002000039000000010200403900000dd10010009c000006870000213d0000000100200190000006870000c13d000000400010043f000000200030008c0000005b0000413d00000000010b0433000000000001004b00001a9c0000613d0000001d010000290000000001010433000000000091004b0000268a0000a13d000000000061004b0000268a0000a13d0000000501600210000000000171001900000000020a043300000db1022001970000000000210435000000010660003900001a9c0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b0a0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b160000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b220000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b2e0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b3a0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b460000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b520000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b5e0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b6a0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b760000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b820000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b8e0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001b9a0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001ba60000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001bb20000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001bbe0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001bca0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001bd60000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001be20000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001bee0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001bfa0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001c060000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001c120000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001c1e0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001c2a0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001c360000c13d0000064b0000013d00130db10020019b001b00000000001d001a00000000001d000000400100043d001c00000001001d00000dfd0010009c000006870000213d0000001c020000290000004001200039000000400010043f0000000001020436001800000001001d000000000001043500000000010904330000001b02000029000000000021004b0000268a0000a13d0000000501200210001600200010003d0000001605900029000000000105043300000db1011001970000001c0400002900000000001404350000000001090433000000000021004b0000268a0000a13d0000000002050433000000400a00043d00000e1c0100004100000000001a0435000000000100041400000db102200197000000040020008c001700000005001d00001c630000c13d000000200030008c0000002004000039000000000403401900001c900000013d00000dae00a0009c00000dae0300004100000000030a4019000000400330021000000dae0010009c00000dae01008041000000c001100210000000000131019f00000db3011001c7001d0000000a001d36b536b00000040f0000001d0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900001c7e0000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00001c7a0000c13d0000001f0740019000001c8b0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000190900002900001e320000613d0000001f01400039000000600110018f00000000060a00190000000005a10019000000000015004b00000000020000390000000102004039001d00000005001d00000dd10050009c000006870000213d0000000100200190000006870000c13d0000001d02000029000000400020043f000000200040008c0000005b0000413d00000000020904330000001b0020006c00000017020000290000268a0000a13d0000000004060433001500000004001d000000000202043300000e1d040000410000001d050000290000000000450435000000040450003900000db102200197000000000024043500000000040004140000001302000029000000040020008c00001cb60000c13d000000000115001900000dd10010009c000006870000213d000000400010043f00001cea0000013d00000dae0040009c00000dae04008041000000c00140021000000dae0050009c00000dae0300004100000000030540190000004003300210000000000113019f00000dd9011001c736b536b00000040f0000001d0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900001cd00000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00001ccc0000c13d0000001f0740019000001cdd0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000000190900002900001e3e0000613d0000001f01400039000000600110018f0000000001a1001900000dd10010009c000006870000213d000000400010043f000000200030008c0000005b0000413d0000001d010000290000000002010433000000150400002900000000014200a9000000000004004b0000001b0500002900001cf40000613d00000000044100d9000000000024004b000026900000c13d00000e090110012a00000018020000290000000000120435000000140100002900000000010104330000000002010433000000000052004b0000268a0000a13d00000016021000290000001c0400002900000000004204350000000001010433000000000051004b0000268a0000a13d000000180100002900000000010104330000001a0010002a000026900000413d001a001a0010002d001b00010050003d00000000010904330000001b0010006b00001c3e0000413d00000f520000013d0026001c0000002d0000000003000415000000250330008a0008000500300218000000400500043d0000000003450019001600000005001d000000000053004b0000000004000039000000010400403900000dd10030009c000006870000213d0000000100400190000006870000c13d000000400030043f00000016030000290000000003230436000000000002004b00001d320000613d00000000020000190000006006000039000000400400043d00000dd30040009c000006870000213d0000008005400039000000400050043f0000006005400039000000000065043500000040054000390000000000050435000000200540003900000000000504350000000000040435000000000523001900000000004504350000002002200039000000000012004b00001d210000413d00000008010000290000000501100270000000160100002f002700000000003d0000001c010000290000000001010433000000000001004b00001e560000c13d000000400100043d00000020020000390000000002210436000000160300002900000000030304330000000000320435000000400410003900000005023002100000000002420019000000000003004b000002390000613d00000080050000390000000006000019000000160c00002900001d4c0000013d0000000106600039000000000036004b000002390000813d0000000007120049000000400770008a0000000004740436000000200cc0003900000000070c0433000000009807043400000db1088001970000000008820436000000000909043300000db109900197000000000098043500000040087000390000000008080433000000400920003900000000008904350000006007700039000000000707043300000060082000390000000000580435000000800920003900000000080704330000000000890435000000a002200039000000000008004b00001d490000613d00000000090000190000002007700039000000000a07043300000000ba0a043400000db10aa00197000000000aa20436000000000b0b04330000000000ba043500000040022000390000000109900039000000000089004b00001d660000413d00001d490000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001d790000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001d850000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001d910000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001d9d0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001da90000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001db50000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001dc10000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001dcd0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001dd90000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001de50000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001df10000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001dfd0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e090000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e150000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e210000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e2d0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e390000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e450000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e510000c13d0000064b0000013d001d00000000001d000000400100043d001a00000001001d00000dd30010009c000006870000213d0000001a020000290000008001200039000000400010043f00000060032000390000006001000039001400000003001d0000000000130435000000400120003900000000000104350000002001200039001500000001001d00000000000104350000000000020435002400000002001d0000001c0100002900000000010104330000001d0010006c0000268a0000a13d0000001d0300002900000005013002100000001c0200002900000000011200190000002001100039001900000001001d000000000101043300000db1011001970000001a0400002900000000001404350000000001020433000000000031004b0000268a0000a13d000000190100002900000000020104330000002a01000029001700000001001d000000000301043300000dfb01000041001b00000003001d0000000000130435001800290000002d000000000100041400000db102200197000000040020008c00001e8c0000c13d0000000003000031000000200030008c0000002004000039000000000403401900001eba0000013d0000001b0300002900000dae0030009c00000dae030080410000004003300210000000180400002900000dae0040009c00000dae040080410000006004400210000000000334019f00000dae0010009c00000dae01008041000000c001100210000000000113019f36b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001b0560002900001ea90000613d000000000701034f0000001b08000029000000007907043c0000000008980436000000000058004b00001ea50000c13d0000001f0740019000001eb60000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027fa0000613d0000001f01400039000000600110018f0000001b02100029000000000012004b0000000004000039000000010400403900000dd10020009c000006870000213d0000000100400190000006870000c13d000000400020043f000000200030008c0000005b0000413d0000001b02000029000000000202043300000db10020009c0000005b0000213d0000002c0220017f000000150400002900000000002404350000001c0200002900000000020204330000001d0020006c0000268a0000a13d000000190200002900000000020204330000001704000029000000000504043300000dfc040000410000000000450435001b00000005001d000000180450002900000db1050000410000002d0550017f001500000005001d0000000000540435000000000400041400000db102200197000000040020008c00001f130000613d0000001b0100002900000dae0010009c00000dae0100804100000040011002100000001803000029000000200330003900000dae0030009c00000dae030080410000006003300210000000000131019f00000dae0040009c00000dae04008041000000c003400210000000000113019f36b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001b0560002900001f000000613d000000000701034f0000001b08000029000000007907043c0000000008980436000000000058004b00001efc0000c13d0000001f0740019000001f0d0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000028060000613d0000001f01400039000000600110018f0000001b02100029000000000012004b0000000001000039000000010100403900000dd10020009c000006870000213d0000000100100190000006870000c13d000000400020043f000000200030008c0000005b0000413d00000017020000290000001a012000290000001b02000029000000000202043300000000002104350000001c0100002900000000010104330000001d0010006c0000268a0000a13d0000002b01000029001b00000001001d0000000012010434000d00000001001d00000dd10020009c000006870000213d00000005012002100000003f0310003900000dd203300197000000400400043d0000000003340019000f00000004001d000000000043004b0000000004000039000000010400403900000dd10030009c000006870000213d0000000100400190000006870000c13d00000019040000290000000004040433001c00000004001d000000400030043f0000000f030000290000000003230436000e00000003001d000000000002004b00001f510000613d0000000002000019000000400300043d00000dfd0030009c000006870000213d0000004004300039000000400040043f0000002004300039000000000004043500000000000304350000000e0420002900000000003404350000002002200039000000000012004b00001f440000413d00000dcf0100004100000000001004430000000001000412000000040010044300000020010000390000002400100443000000000100041400000dae0010009c00000dae01008041000000c00110021000000df8011001c7000080050200003936b536b00000040f0000000100200190000026890000613d0000001b020000290000000002020433000000000002004b0000266e0000613d0000001c02000029001c0db10020019b000000000101043b000900000001001d001d00000000001d000000400100043d001900000001001d00000dfe0010009c000006870000213d00000019020000290000006001200039000000400010043f0000004001200039001100000001001d00000000000104350000000001020436001300000001001d0000000000010435000000400100043d001600000001001d00000dfe0010009c000006870000213d00000016020000290000006001200039000000400010043f0000004001200039001000000001001d00000000000104350000000001020436001200000001001d00000000000104350000001b010000290000000001010433000000090000006b0000001d02000029001400050020021800001fa00000613d0000001d0010006c0000268a0000a13d00000014020000290000000d01200029001700000001001d0000000001010433000000400300043d00000dff020000410000000002230436001800000002001d00000db101100197001a00000003001d0000000402300039000000000012043500000000010004140000001c02000029000000040020008c00001fb70000c13d0000000003000031000000600030008c0000006004000039000000000403401900001fe20000013d0000001d0010006c0000268a0000a13d00000014020000290000000d01200029001700000001001d0000000001010433000000400300043d00000e02020000410000000002230436001800000002001d00000db101100197001a00000003001d0000000402300039000000000012043500000000010004140000001c02000029000000040020008c000020520000c13d0000000003000031000000600030008c000000600400003900000000040340190000207d0000013d0000001a0200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000dd9011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000600030008c0000006004000039000000000403401900000060064001900000001a0560002900001fd10000613d000000000701034f0000001a08000029000000007907043c0000000008980436000000000058004b00001fcd0000c13d0000001f0740019000001fde0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027820000613d0000001f01400039000000e00110018f0000001a02100029000000000012004b0000000004000039000000010400403900000dd10020009c000006870000213d0000000100400190000006870000c13d000000400020043f000000600030008c0000005b0000413d0000001a02000029000000000202043300000e000020009c0000005b0000213d000000180400002900000000040404330000001a05000029000000400550003900000000050504330000001106000029000000000056043500000013050000290000000000450435000000190400002900000000002404350000001b0200002900000000020204330000001d0020006c0000268a0000a13d00000017020000290000000002020433000000400500043d00000e01040000410000000004450436001800000004001d00000db102200197001a00000005001d0000000404500039000000000024043500000000020004140000001c04000029000000040040008c0000203d0000613d0000001a0100002900000dae0010009c00000dae01008041000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000600030008c0000006004000039000000000403401900000060064001900000001a056000290000202a0000613d000000000701034f0000001a08000029000000007907043c0000000008980436000000000058004b000020260000c13d0000001f07400190000020370000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000278e0000613d0000001f01400039000000e00110018f0000001a02100029000000000012004b0000000001000039000000010100403900000dd10020009c000006870000213d0000000100100190000006870000c13d000000400020043f000000600030008c0000005b0000413d0000001a01000029000000000101043300000e000010009c0000005b0000213d0000001a020000290000004002200039000000000402043300000018020000290000000002020433000020f40000013d0000001a0200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000dd9011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000600030008c0000006004000039000000000403401900000060064001900000001a056000290000206c0000613d000000000701034f0000001a08000029000000007907043c0000000008980436000000000058004b000020680000c13d0000001f07400190000020790000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000279a0000613d0000001f01400039000000e00110018f0000001a02100029000000000012004b0000000004000039000000010400403900000dd10020009c000006870000213d0000000100400190000006870000c13d000000400020043f000000600030008c0000005b0000413d0000001a02000029000000000202043300000e000020009c0000005b0000213d0000001804000029000000000404043300000dae0040009c0000005b0000213d0000001a050000290000004005500039000000000505043300000dae0050009c0000005b0000213d0000001106000029000000000056043500000013050000290000000000450435000000190400002900000000002404350000001b0200002900000000020204330000001d0020006c0000268a0000a13d00000017020000290000000002020433000000400500043d00000e03040000410000000004450436001800000004001d00000db102200197001a00000005001d0000000404500039000000000024043500000000020004140000001c04000029000000040040008c000020dc0000613d0000001a0100002900000dae0010009c00000dae01008041000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000600030008c0000006004000039000000000403401900000060064001900000001a05600029000020c90000613d000000000701034f0000001a08000029000000007907043c0000000008980436000000000058004b000020c50000c13d0000001f07400190000020d60000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027a60000613d0000001f01400039000000e00110018f0000001a02100029000000000012004b0000000001000039000000010100403900000dd10020009c000006870000213d0000000100100190000006870000c13d000000400020043f000000600030008c0000005b0000413d0000001a01000029000000000101043300000e000010009c0000005b0000213d0000001802000029000000000202043300000dae0020009c0000005b0000213d0000001a040000290000004004400039000000000404043300000dae0040009c0000005b0000213d0000001005000029000000000045043500000012040000290000000000240435000000160200002900000000001204350000001b0100002900000000010104330000001d0010006c0000268a0000a13d00000014020000290000000d01200029001a00000001001d0000000002010433000000400400043d00000e0401000041001700000004001d0000000000140435000000000100041400000db102200197000000040020008c0000002004000039000021350000613d000000170300002900000dae0030009c00000dae03008041000000400330021000000dae0010009c00000dae01008041000000c001100210000000000131019f00000db3011001c736b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001705600029000021240000613d000000000701034f0000001708000029000000007907043c0000000008980436000000000058004b000021200000c13d0000001f07400190000021310000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000272e0000613d0000001f01400039000000600110018f0000001704100029000000000014004b00000000020000390000000102004039001800000004001d00000dd10040009c000006870000213d0000000100200190000006870000c13d0000001802000029000000400020043f000000200030008c0000005b0000413d000000180200002900000dde0020009c000006870000213d0000001702000029000000000202043300000018050000290000002004500039000000400040043f00000000002504350000001b0200002900000000020204330000001d0020006c0000268a0000a13d0000001a020000290000000002020433000000400500043d00000e0504000041000000000045043500000db104200197001700000005001d0000000402500039000c00000004001d000000000042043500000000020004140000001c04000029000000040040008c0000218c0000613d000000170100002900000dae0010009c00000dae01008041000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001705600029000021790000613d000000000701034f0000001708000029000000007907043c0000000008980436000000000058004b000021750000c13d0000001f07400190000021860000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000273a0000613d0000001f01400039000000600110018f0000001702100029000000000012004b0000000001000039000000010100403900000dd10020009c000006870000213d0000000100100190000006870000c13d000000400020043f000000200030008c0000005b0000413d00000017010000290000000001010433001700000001001d00000dcf0100004100000000001004430000000001000412000000040010044300000040010000390000002400100443000000000100041400000dae0010009c00000dae01008041000000c00110021000000df8011001c7000080050200003936b536b00000040f0000000100200190000026890000613d000000000101043b000000010010008c000021b20000613d000000020010008c000027150000c13d00000e080100004100000000001004430000000001000414000021b50000013d00000e06010000410000000000100443000000000100041400000dae0010009c00000dae01008041000000c00110021000000e07011001c70000800b0200003936b536b00000040f0000000100200190000026890000613d00000011020000290000000004020433000000000101043b000000000041004b00000000020000390000000102002039000000000004004b0000000003000039000000010300c0390000000000230170000000000401601900000013010000290000000001010433001100000004001d000a000000140053000026900000413d0000226a0000613d000000170000006b000022670000613d000000400200043d00000de501000041000b00000002001d000000000012043500000000010004140000000c02000029000000040020008c000021dd0000c13d0000000003000031000000200030008c00000020040000390000000004034019000022080000013d0000000b0200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c70000000c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000000b05600029000021f70000613d000000000701034f0000000b08000029000000007907043c0000000008980436000000000058004b000021f30000c13d0000001f07400190000022040000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027ca0000613d0000001f01400039000000600210018f0000000b01200029000000000021004b0000000002000039000000010200403900000dd10010009c000006870000213d0000000100200190000006870000c13d000000400010043f000000200030008c0000005b0000413d0000000b02000029000000000302043300000e09023000d1000000000003004b0000221d0000613d00000000033200d900000e090030009c000026900000c13d00000018030000290000000003030433000000000003004b0000270f0000613d0000000a0500002900000017045000b900000000055400d9000000170050006c000026900000c13d000000000023004b0000222c0000a13d00000dde0010009c00000000020000190000223c0000a13d000006870000013d00000dde0010009c000006870000213d0000002005100039000000400050043f000000000001043500000e0a054000d1000000000004004b000022370000613d00000000014500d900000e0a0010009c000026900000c13d000000400100043d00000dde0010009c000006870000213d00000000023200d900000000022500d90000002003100039000000400030043f0000000000210435000000400200043d00000dde0020009c000006870000213d000000190300002900000000030304330000002004200039000000400040043f00000e00033001970000000000320435000000400300043d00000dde0030009c000006870000213d0000002004300039000000400040043f000000000003043500000000020204330000000001010433000000000021001a000026900000413d000000400300043d00000dde0030009c000006870000213d00000000022100190000002001300039000000400010043f0000000000230435000000400100043d00000dfd0010009c000006870000213d0000004003100039000000400030043f000000200310003900000e0b0400004100000000004304350000001303000039000000000031043500000e0c0020009c0000271b0000813d000000190100002900000000002104350000001301000029000000110200002900000000002104350000001b0100002900000000010104330000001d0010006c0000268a0000a13d0000001a010000290000000001010433000000400300043d00000e0e02000041000000000023043500000db102100197001700000003001d0000000401300039001100000002001d000000000021043500000000010004140000001c02000029000000040020008c000022810000c13d0000000003000031000000200030008c00000020040000390000000004034019000022ac0000013d000000170200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000dd9011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000017056000290000229b0000613d000000000701034f0000001708000029000000007907043c0000000008980436000000000058004b000022970000c13d0000001f07400190000022a80000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027460000613d0000001f01400039000000600210018f0000001701200029000000000021004b0000000002000039000000010200403900000dd10010009c000006870000213d0000000100200190000006870000c13d000000400010043f000000200030008c0000005b0000413d00000017010000290000000001010433001700000001001d00000dcf0100004100000000001004430000000001000412000000040010044300000040010000390000002400100443000000000100041400000dae0010009c00000dae01008041000000c00110021000000df8011001c7000080050200003936b536b00000040f0000000100200190000026890000613d000000000101043b000000010010008c000022d40000613d000000020010008c000027150000c13d00000e080100004100000000001004430000000001000414000022d70000013d00000e06010000410000000000100443000000000100041400000dae0010009c00000dae01008041000000c00110021000000e07011001c70000800b0200003936b536b00000040f0000000100200190000026890000613d00000010020000290000000004020433000000000101043b000000000041004b00000000020000390000000102002039000000000004004b0000000003000039000000010300c0390000000000230170000000000401601900000012010000290000000001010433001300000004001d000c000000140053000026900000413d000023810000613d000000170000006b0000237e0000613d000000400200043d00000ddf01000041001000000002001d000000000012043500000000010004140000001102000029000000040020008c000022ff0000c13d0000000003000031000000200030008c000000200400003900000000040340190000232a0000013d000000100200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c7000000110200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001005600029000023190000613d000000000701034f0000001008000029000000007907043c0000000008980436000000000058004b000023150000c13d0000001f07400190000023260000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027d60000613d0000001f01400039000000600210018f0000001001200029000000000021004b0000000002000039000000010200403900000dd10010009c000006870000213d0000000100200190000006870000c13d000000400010043f000000200030008c0000005b0000413d0000000c0200002900000017032000b900000000022300d9000000170020006c000026900000c13d00000010020000290000000002020433000000000002004b000023500000613d00000dde0010009c000006870000213d0000002004100039000000400040043f000000000001043500000e0a043000d1000000000003004b0000234b0000613d00000000013400d900000e0a0010009c000026900000c13d000000400100043d00000dde0010009c000006870000213d00000000022400d9000023530000013d00000dde0010009c0000000002000019000006870000213d0000002003100039000000400030043f0000000000210435000000400200043d00000dde0020009c000006870000213d000000160300002900000000030304330000002004200039000000400040043f00000e00033001970000000000320435000000400300043d00000dde0030009c000006870000213d0000002004300039000000400040043f000000000003043500000000020204330000000001010433000000000021001a000026900000413d000000400300043d00000dde0030009c000006870000213d00000000022100190000002001300039000000400010043f0000000000230435000000400100043d00000dfd0010009c000006870000213d0000004003100039000000400030043f000000200310003900000e0b0400004100000000004304350000001303000039000000000031043500000e0c0020009c0000271b0000813d000000160100002900000000002104350000001201000029000000130200002900000000002104350000001b0100002900000000010104330000001d0010006c0000268a0000a13d000000400100043d001300000001001d00000dde0010009c000006870000213d0000001a01000029000000000101043300000db1031001970000001901000029000000000101043300000013040000290000002002400039000000400020043f00000e00011001970000000000140435000000400400043d00000024014000390000001502000029000000000021043500000e0f010000410000000000140435001700000004001d0000000401400039001200000003001d000000000031043500000000010004140000001c02000029000000040020008c000023a60000c13d0000000003000031000000200030008c00000020040000390000000004034019000023d10000013d000000170200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000ddd011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001705600029000023c00000613d000000000701034f0000001708000029000000007907043c0000000008980436000000000058004b000023bc0000c13d0000001f07400190000023cd0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027520000613d0000001f01400039000000600110018f0000001704100029000000000014004b00000000020000390000000102004039001900000004001d00000dd10040009c000006870000213d0000000100200190000006870000c13d0000001902000029000000400020043f000000200030008c0000005b0000413d000000190200002900000dde0020009c000006870000213d0000001702000029000000000202043300000019050000290000002004500039000000400040043f0000000000250435000000400400043d001700000004001d000000000002004b0000247b0000c13d00000013020000290000000002020433001000000002001d00000e10020000410000001704000029000000000024043500000000020004140000001c04000029000000040040008c000024240000613d000000170100002900000dae0010009c00000dae01008041000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001705600029000024110000613d000000000701034f0000001708000029000000007907043c0000000008980436000000000058004b0000240d0000c13d0000001f074001900000241e0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027b20000613d0000001f01400039000000600110018f0000001704100029000000000014004b00000000020000390000000102004039001100000004001d00000dd10040009c000006870000213d0000000100200190000006870000c13d0000001102000029000000400020043f000000200030008c0000005b0000413d0000001702000029000000000202043300000e000020009c0000005b0000213d000000100020006b000024390000813d00000011010000290000247a0000013d00000e10020000410000001104000029000000000024043500000000020004140000001c04000029000000040040008c0000246d0000613d000000110100002900000dae0010009c00000dae01008041000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000011056000290000245a0000613d000000000701034f0000001108000029000000007907043c0000000008980436000000000058004b000024560000c13d0000001f07400190000024670000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027e20000613d0000001f01400039000000600110018f000000110110002900000dd10010009c000006870000213d000000400010043f000000200030008c0000005b0000413d0000001101000029000000000101043300000e000010009c0000005b0000213d00000019020000290000000000120435000000400100043d001700000001001d000000170100002900000dde0010009c000006870000213d00000017020000290000002001200039000000400010043f00000000000204350000001901000029000000000101043300000013020000290000000002020433000000000112004b000026900000413d000000400200043d001300000002001d00000dde0020009c000006870000213d00000013040000290000002002400039000000400020043f0000000000140435000000400200043d00000e11010000410000000000120435001700000002001d00000004012000390000001502000029000000000021043500000000010004140000001202000029000000040020008c0000002004000039000024c70000613d000000170200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000dd9011001c7000000120200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001705600029000024b60000613d000000000701034f0000001708000029000000007907043c0000000008980436000000000058004b000024b20000c13d0000001f07400190000024c30000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000275e0000613d0000001f01400039000000600110018f0000001702100029000000000012004b00000000010000390000000101004039001900000002001d00000dd10020009c000006870000213d0000000100100190000006870000c13d0000001901000029000000400010043f000000200030008c0000005b0000413d0000001701000029000000000201043300000e09012000d1000000000002004b000024de0000613d00000000022100d900000e090020009c000026900000c13d00000018020000290000000002020433000000000002004b0000270f0000613d0000001304000029000000000404043300000000052100d900130000005400ad000000000012004b000024eb0000213d00000013015000f9000000000041004b000026900000c13d0000001b0100002900000000010104330000001d0010006c0000268a0000a13d000000190100002900000dde0010009c000006870000213d0000001a01000029000000000101043300000db1051001970000001601000029000000000101043300000019040000290000002002400039000000400020043f00000e00011001970000000000140435000000400400043d00000024014000390000001502000029000000000021043500000e12010000410000000000140435001700000004001d0000000401400039001600000005001d000000000051043500000000010004140000001c02000029000000040020008c0000002004000039000025360000613d000000170200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000ddd011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001705600029000025250000613d000000000701034f0000001708000029000000007907043c0000000008980436000000000058004b000025210000c13d0000001f07400190000025320000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000276a0000613d0000001f01400039000000600110018f0000001704100029000000000014004b00000000020000390000000102004039001800000004001d00000dd10040009c000006870000213d0000000100200190000006870000c13d0000001802000029000000400020043f000000200030008c0000005b0000413d000000180200002900000dde0020009c000006870000213d0000001702000029000000000202043300000018050000290000002004500039000000400040043f0000000000250435000000400400043d001700000004001d000000000002004b000025e00000c13d00000019020000290000000002020433001100000002001d00000e10020000410000001704000029000000000024043500000000020004140000001c04000029000000040040008c000025890000613d000000170100002900000dae0010009c00000dae01008041000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001705600029000025760000613d000000000701034f0000001708000029000000007907043c0000000008980436000000000058004b000025720000c13d0000001f07400190000025830000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027be0000613d0000001f01400039000000600110018f0000001704100029000000000014004b00000000020000390000000102004039001200000004001d00000dd10040009c000006870000213d0000000100200190000006870000c13d0000001202000029000000400020043f000000200030008c0000005b0000413d0000001702000029000000000202043300000e000020009c0000005b0000213d000000110020006b0000259e0000813d0000001201000029000025df0000013d00000e10020000410000001204000029000000000024043500000000020004140000001c04000029000000040040008c000025d20000613d000000120100002900000dae0010009c00000dae01008041000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000001c0200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c0000002004000039000000000403401900000020064001900000001205600029000025bf0000613d000000000701034f0000001208000029000000007907043c0000000008980436000000000058004b000025bb0000c13d0000001f07400190000025cc0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027ee0000613d0000001f01400039000000600110018f000000120110002900000dd10010009c000006870000213d000000400010043f000000200030008c0000005b0000413d0000001201000029000000000101043300000e000010009c0000005b0000213d00000018020000290000000000120435000000400100043d001700000001001d000000170100002900000dde0010009c000006870000213d00000017020000290000002001200039000000400010043f00000000000204350000001801000029000000000101043300000019020000290000000002020433000000000112004b000026900000413d000000400200043d001800000002001d00000dde0020009c000006870000213d00000018040000290000002002400039000000400020043f0000000000140435000000400200043d00000df2010000410000000000120435001900000002001d00000004012000390000001502000029000000000021043500000000010004140000001602000029000000040020008c00000020040000390000262c0000613d000000190200002900000dae0020009c00000dae02008041000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000dd9011001c7000000160200002936b536b00000040f0000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000019056000290000261b0000613d000000000701034f0000001908000029000000007907043c0000000008980436000000000058004b000026170000c13d0000001f07400190000026280000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000027760000613d0000001f01400039000000600210018f0000001901200029000000000021004b0000000002000039000000010200403900000dd10010009c000006870000213d0000000100200190000006870000c13d000000400010043f000000200030008c0000005b0000413d000000180200002900000000030204330000001902000029000000000402043300000000024300a9000000000004004b000026430000613d00000000044200d9000000000034004b000026900000c13d00000dfd0010009c000006870000213d0000004003100039000000400030043f000000000301043600000000000304350000001b0400002900000000040404330000001d0040006c0000268a0000a13d000000130400002900000e0a0440012a00000e0a0220012a0000001a05000029000000000505043300000db1055001970000000000510435000000000242001900000000002304350000000f0200002900000000020204330000001d0020006c0000268a0000a13d00000014030000290000000e0230002900000000001204350000000f0100002900000000010104330000001d0010006c0000268a0000a13d0000001d02000029001d00010020003d0000001b0100002900000000010104330000001d0010006b00001f690000413d001d00270000002d0000002401000029001a00000001001d001400600010003d0000000801000029000000050110027000160000000100350000000f0100002900000014020000290000000000120435000000160100002900000000010104330000001d0010006c0000268a0000a13d0000001d0300002900000005013002100000001602000029000000000112001900000020011000390000001a0400002900000000004104350000000001020433000000000031004b0000268a0000a13d0000001d02000029002700010020003d00000001022000390000002601000029001c00000001001d0000000001010433001d00000002001d000000000012004b00001e570000413d00001d3a0000013d000000000001042f00000e1301000041000000000010043f0000003201000039000000040010043f00000dd901000041000036b70001043000000e1301000041000000000010043f0000001101000039000000040010043f00000dd901000041000036b700010430000000000301034f0000001f0580018f000000000908001900000db006800198000000400200043d0000000004620019000026b10000613d000000000703034f0000000008020019000000007107043c0000000008180436000000000048004b0000269f0000c13d000026b10000013d000000000301034f0000001f0580018f000000000908001900000db006800198000000400200043d0000000004620019000026b10000613d000000000703034f0000000008020019000000007107043c0000000008180436000000000048004b000026ad0000c13d000000000005004b000026be0000613d000000000163034f0000000303500210000000000504043300000000053501cf000000000535022f000000000101043b0000010003300089000000000131022f00000000013101cf000000000151019f00000000001404350000006001900210000006590000013d0000001f0590018f000000000a09001900000db006900198000000400200043d0000000004620019000026cc0000613d0000001c0700035f0000000008020019000000007107043c0000000008180436000000000048004b000026c80000c13d000000000005004b000005460000613d0000001c0160035f0000000303500210000000000504043300000000053501cf000000000535022f000000000101043b0000010003300089000000000131022f00000000013101cf000000000151019f000005450000013d0000001d010000290000001f0510018f00000db006100198000000400200043d0000000004620019000026ff0000613d0000001c0700035f0000000008020019000000007107043c0000000008180436000000000048004b000026e10000c13d000026ff0000013d0000001d010000290000001f0510018f00000db006100198000000400200043d0000000004620019000026ff0000613d0000001c0700035f0000000008020019000000007107043c0000000008180436000000000048004b000026ee0000c13d000026ff0000013d0000001d010000290000001f0510018f00000db006100198000000400200043d0000000004620019000026ff0000613d0000001c0700035f0000000008020019000000007107043c0000000008180436000000000048004b000026fb0000c13d000000000005004b0000270c0000613d0000001c0160035f0000000303500210000000000504043300000000053501cf000000000535022f000000000101043b0000010003300089000000000131022f00000000013101cf000000000151019f00000000001404350000001d010000290000006001100210000006590000013d00000e1301000041000000000010043f0000001201000039000000040010043f00000dd901000041000036b70001043000000e1301000041000000000010043f0000005101000039000000040010043f00000dd901000041000036b700010430000000400400043d001d00000004001d00000e0d020000410000000000240435000000040240003900000020030000390000000000320435000000240240003936b528120000040f0000001d02000029000000000121004900000dae0010009c00000dae0100804100000dae0020009c00000dae0200804100000060011002100000004002200210000000000121019f000036b7000104300000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027350000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027410000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000274d0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027590000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027650000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027710000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000277d0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027890000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027950000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027a10000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027ad0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027b90000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027c50000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027d10000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027dd0000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027e90000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000027f50000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000028010000c13d0000064b0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000064b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000280d0000c13d0000064b0000013d00000000430104340000000001320436000000000003004b0000281e0000613d000000000200001900000000051200190000000006240019000000000606043300000000006504350000002002200039000000000032004b000028170000413d000000000213001900000000000204350000001f0230003900000e25022001970000000001210019000000000001042d000000004301043400000db103300197000000000332043600000000040404330000000000430435000000400310003900000000030304330000004004200039000000000034043500000060031000390000000003030433000000600420003900000000003404350000008003100039000000000303043300000080042000390000000000340435000000a0031000390000000003030433000000a0042000390000000000340435000000c0031000390000000003030433000000c0042000390000000000340435000000e0031000390000000003030433000000e004200039000000000034043500000100031000390000000003030433000001000420003900000000003404350000012003100039000000000303043300000120042000390000000000340435000001400310003900000000030304330000014004200039000000000034043500000160031000390000000003030433000000000003004b0000000003000039000000010300c039000001600420003900000000003404350000018003100039000000000303043300000180042000390000000000340435000001a003100039000000000303043300000db103300197000001a0042000390000000000340435000001c0031000390000000003030433000001c0042000390000000000340435000001e0031000390000000003030433000001e00420003900000000003404350000020002200039000002000110003900000000010104330000000000120435000000000001042d000000200300003900000000033104360000000064020434000001a0050000390000000000530435000001c00510003900000000740404340000000000450435000001e005100039000000000004004b0000287d0000613d00000000080000190000000009580019000000000a870019000000000a0a04330000000000a904350000002008800039000000000048004b000028760000413d00000000075400190000000000070435000000000606043300000db106600197000000400710003900000000006704350000004006200039000000000606043300000db10660019700000060071000390000000000670435000000600620003900000000060604330000008007100039000000000067043500000080062000390000000006060433000000a00710003900000000006704350000001f0640003900000e250660019700000000055600190000000006350049000000c007100039000000a0082000390000000008080433000000000067043500000000760804340000000005650436000000000006004b000028a40000613d00000000080000190000000009580019000000000a870019000000000a0a04330000000000a904350000002008800039000000000068004b0000289d0000413d000000000756001900000000000704350000001f0660003900000e250660019700000000055600190000000006350049000000c0072000390000000007070433000000e008100039000000000068043500000000760704340000000005650436000000000006004b000028ba0000613d00000000080000190000000009580019000000000a870019000000000a0a04330000000000a904350000002008800039000000000068004b000028b30000413d000000000756001900000000000704350000001f0660003900000e250660019700000000055600190000000006350049000000e00720003900000000070704330000010008100039000000000068043500000000760704340000000005650436000000000006004b000028d00000613d00000000080000190000000009580019000000000a870019000000000a0a04330000000000a904350000002008800039000000000068004b000028c90000413d000000000756001900000000000704350000010007200039000000000707043300000db107700197000001200810003900000000007804350000012007200039000000000707043300000140081000390000000000780435000001400720003900000000070704330000016008100039000000000078043500000160072000390000000007070433000001800810003900000000007804350000001f0660003900000e250460019700000000045400190000000003340049000001a00110003900000180022000390000000002020433000000000031043500000000030204330000000001340436000000000003004b0000293b0000613d000000000400001900000020022000390000000005020433000000007605043400000db106600197000000000661043600000000070704330000000000760435000000400650003900000000060604330000004007100039000000000067043500000060065000390000000006060433000000600710003900000000006704350000008006500039000000000606043300000080071000390000000000670435000000a0065000390000000006060433000000a0071000390000000000670435000000c0065000390000000006060433000000c0071000390000000000670435000000e0065000390000000006060433000000e007100039000000000067043500000100065000390000000006060433000001000710003900000000006704350000012006500039000000000606043300000120071000390000000000670435000001400650003900000000060604330000014007100039000000000067043500000160065000390000000006060433000000000006004b0000000006000039000000010600c039000001600710003900000000006704350000018006500039000000000606043300000180071000390000000000670435000001a006500039000000000606043300000db106600197000001a0071000390000000000670435000001c0065000390000000006060433000001c0071000390000000000670435000001e0065000390000000006060433000001e0071000390000000000670435000002000550003900000000050504330000020006100039000000000056043500000220011000390000000104400039000000000034004b000028f00000413d000000000001042d000000003101043400000db101100197000000000112043600000000020304330000000000210435000000000001042d000000004301043400000db103300197000000000332043600000000040404330000000000430435000000400310003900000000030304330000004004200039000000000034043500000060031000390000000003030433000000600420003900000000003404350000008003100039000000000303043300000080042000390000000000340435000000a002200039000000a00110003900000000010104330000000000120435000000000001042d000d000000000002000600000002001d000400000001001d000000400100043d00000e260010009c00002d0d0000813d000001a002100039000000400020043f000001800210003900000060090000390000000000920435000000e0021000390000000000920435000000c0021000390000000000920435000000a0021000390000000000920435000000000291043600000160031000390000000000030435000001400310003900000000000304350000012003100039000000000003043500000100031000390000000000030435000000800310003900000000000304350000006003100039000000000003043500000040011000390000000000010435000000000002043500000006010000290000004001100039000500000001001d0000000002010433000000400a00043d00000df60100004100000000001a0435000000000100041400000db102200197000000040020008c000d00000002001d000029880000c13d000000020100036700000000030000310000299c0000013d00000dae00a0009c000c0000000a001d00000dae0300004100000000030a4019000000400330021000000dae0010009c00000dae01008041000000c001100210000000000131019f00000db3011001c736b536b00000040f0000000003010019000000600330027000000dae0030019d00000dae033001970002000000010355000000010020019000002d340000613d00000060090000390000000c0a00002900000e25043001980000001f0530018f00000000024a0019000029a60000613d000000000601034f00000000070a0019000000006806043c0000000007870436000000000027004b000029a20000c13d000000000005004b000029b30000613d000000000141034f0000000304500210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001204350000001f0130003900000e25011001970000000002a10019000000000012004b00000000010000390000000101004039000c00000002001d00000dd10020009c00002d0d0000213d000000010010019000002d0d0000c13d0000000c01000029000000400010043f00000dea0030009c00002d130000213d0000001f0030008c00002d130000a13d00000000010a043300000dd10010009c00002d130000213d0000000002a300190000000001a100190000001f03100039000000000023004b000000000400001900000deb0400804100000deb0330019700000deb05200197000000000653013f000000000053004b000000000300001900000deb0300404100000deb0060009c000000000304c019000000000003004b00002d130000c13d000000001301043400000dd10030009c00002d0d0000213d00000005043002100000003f0540003900000dd2055001970000000c0550002900000dd10050009c00002d0d0000213d000000400050043f0000000c050000290000000003350436000900000003001d0000000003140019000000000023004b00002d130000213d000000000031004b000029f10000813d0000000c02000029000000001401043400000db10040009c00002d130000213d00000020022000390000000000420435000000000031004b000029ea0000413d00000dcf010000410000000000100443000000000100041200000004001004430000002400900443000000000100041400000dae0010009c00000dae01008041000000c00110021000000df8011001c7000080050200003936b536b00000040f000000010020019000002d330000613d0000000c020000290000000006020433000000000101043b00000db1011001970000000d0010006b00002a070000c13d000000000506001900002a7c0000013d000000000006004b00002a790000613d00000df90700004100000000080000190000000005000019000700000006001d00002a170000013d00000005015002100000000901100029000000000209043300000db102200197000000000021043500000001055000390000000108800039000000000068004b00002a7a0000813d0000000c010000290000000001010433000000000081004b00002a730000a13d000000050180021000000009091000290000000002090433000000400a00043d00000000007a0435000000000100041400000db102200197000000040020008c00002a290000c13d0000000003000031000000200030008c0000002004000039000000000403401900002a5d0000013d000d00000009001d000a00000008001d000800000005001d00000dae00a0009c00000dae0300004100000000030a4019000000400330021000000dae0010009c00000dae01008041000000c001100210000000000131019f00000db3011001c7000b0000000a001d36b536b00000040f0000000b0a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a001900002a470000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b00002a430000c13d0000001f0740019000002a540000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000000d0900002900002d150000613d0000000805000029000000070600002900000df9070000410000000a080000290000001f01400039000000600210018f0000000001a20019000000000021004b0000000002000039000000010200403900000dd10010009c00002d0d0000213d000000010020019000002d0d0000c13d000000400010043f000000200030008c00002d130000413d00000000010a0433000000000001004b00002a140000613d0000000c010000290000000001010433000000000081004b00002a730000a13d000000000051004b00002a0e0000213d00000e1301000041000000000010043f0000003201000039000000040010043f00000dd901000041000036b70001043000000000050000190000000c01000029000000000051043500000dd10050009c00002d0d0000213d00000005015002100000003f0210003900000dd202200197000000400300043d0000000002230019000d00000003001d000000000032004b0000000003000039000000010300403900000dd10020009c00002d0d0000213d000000010030019000002d0d0000c13d000000400020043f0000000d020000290000000006520436000000000005004b00002ada0000613d0000000002000019000000400300043d00000dd50030009c00002d0d0000213d0000022004300039000000400040043f00000200043000390000000000040435000001e0043000390000000000040435000001c0043000390000000000040435000001a00430003900000000000404350000018004300039000000000004043500000160043000390000000000040435000001400430003900000000000404350000012004300039000000000004043500000100043000390000000000040435000000e0043000390000000000040435000000c0043000390000000000040435000000a0043000390000000000040435000000800430003900000000000404350000006004300039000000000004043500000040043000390000000000040435000000200430003900000000000404350000000000030435000000000462001900000000003404350000002002200039000000000012004b00002a910000413d0000000003000019000800000005001d000700000006001d0000000c010000290000000001010433000000000031004b00002a730000a13d0000000502300210000a00000002001d0000000901200029000000000101043300000db101100197000b00000003001d36b52e930000040f0000000b03000029000000070600002900000008050000290000000d020000290000000002020433000000000032004b00002a730000a13d0000000a0260002900000000001204350000000d010000290000000001010433000000000031004b00002a730000a13d0000000103300039000000000053004b00002abf0000413d00000005010000290000000001010433000000400900043d00000e2002000041000000000029043500000db101100197000000040290003900000000001204350000000001000414000000040200002900000db102200197000000040020008c00002aea0000c13d0000000201000367000000000300003100002afd0000013d00000dae0090009c000c00000009001d00000dae030000410000000003094019000000400330021000000dae0010009c00000dae01008041000000c001100210000000000131019f00000dd9011001c736b536b00000040f0000000003010019000000600330027000000dae0030019d00000dae033001970002000000010355000000010020019000002d400000613d0000000c0900002900000e25043001980000001f0530018f000000000249001900002b070000613d000000000601034f0000000007090019000000006806043c0000000007870436000000000027004b00002b030000c13d000000000005004b00002b140000613d000000000141034f0000000304500210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001204350000001f0130003900000e25021001970000000001920019000000000021004b0000000002000039000000010200403900000dd10010009c00002d0d0000213d000000010020019000002d0d0000c13d000000400010043f00000dea0030009c00002d130000213d000000200030008c00002d130000413d000000000409043300000dd10040009c00002d130000213d00000000029300190000000004940019000000000542004900000dea0050009c00002d130000213d000000600050008c00002d130000413d00000dfe0010009c00002d0d0000213d0000006005100039000000400050043f000000007604043400000dd10060009c00002d130000213d00000000084600190000001f06800039000000000026004b000000000900001900000deb0900804100000deb0a60019700000deb06200197000000000b6a013f00000000006a004b000000000a00001900000deb0a00404100000deb00b0009c000000000a09c01900000000000a004b00002d130000c13d000000009808043400000dd10080009c00002d0d0000213d0000001f0a80003900000e250aa001970000003f0aa0003900000e250aa00197000000000a5a001900000dd100a0009c00002d0d0000213d0000004000a0043f0000000000850435000000000a98001900000000002a004b00002d130000213d000000800a100039000000000008004b00002b5d0000613d000000000b000019000000000cab0019000000000d9b0019000000000d0d04330000000000dc0435000000200bb0003900000000008b004b00002b560000413d0000000008a8001900000000000804350000000005510436000000000707043300000dd10070009c00002d130000213d00000000074700190000001f08700039000000000028004b000000000900001900000deb0900804100000deb08800197000000000a68013f000000000068004b000000000800001900000deb0800404100000deb00a0009c000000000809c019000000000008004b00002d130000c13d000000008707043400000dd10070009c00002d0d0000213d0000001f0970003900000e25099001970000003f0990003900000e250a900197000000400900043d000000000aa9001900000000009a004b000000000b000039000000010b00403900000dd100a0009c00002d0d0000213d0000000100b0019000002d0d0000c13d0000004000a0043f000000000a790436000000000b87001900000000002b004b00002d130000213d000000000007004b00002b900000613d000000000b000019000000000cab0019000000000d8b0019000000000d0d04330000000000dc0435000000200bb0003900000000007b004b00002b890000413d00000000077a0019000000000007043500000000009504350000004007400039000000000707043300000dd10070009c00002d130000213d00000000044700190000001f07400039000000000027004b000000000800001900000deb0800804100000deb07700197000000000967013f000000000067004b000000000600001900000deb0600404100000deb0090009c000000000608c019000000000006004b00002d130000c13d000000006404043400000dd10040009c00002d0d0000213d0000001f0740003900000e25077001970000003f0770003900000e2507700197000000400a00043d00000000077a00190000000000a7004b0000000008000039000000010800403900000dd10070009c00002d0d0000213d000000010080019000002d0d0000c13d000000400070043f00000000074a04360000000008640019000000000028004b00002d130000213d000000000004004b00002bc40000613d000000000200001900000000087200190000000009620019000000000909043300000000009804350000002002200039000000000042004b00002bbd0000413d0000000002470019000000000002043500000040021000390000000000a204350000000001010433000800000001001d0000000001050433000300000001001d000000060200002900000080012000390000000001010433000400000001001d00000060012000390000000001010433000700000001001d00000020012000390000000001010433000900000001001d0000000001020433000a00000001001d00000005010000290000000002010433000000400c00043d00000e1b0100004100000000001c0435000000000100041400000db105200197000000040050008c000c0000000a001d000b00000005001d00002be70000c13d000000200030008c0000002004000039000000000403401900002c170000013d00000dae00c0009c00000dae0200004100000000020c4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c7000000000205001900060000000c001d36b536b00000040f000000060c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c001900002c040000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b00002c000000c13d000000000006004b00002c110000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000000c0a00002900002d4c0000613d0000000b050000290000001f01400039000000600110018f000000000bc1001900000000001b004b0000000002000039000000010200403900000dd100b0009c00002d0d0000213d000000010020019000002d0d0000c13d0000004000b0043f000000200030008c00002d130000413d00000000020c0433000600000002001d00000db10020009c00002d130000213d00000e210200004100000000002b04350000000002000414000000040050008c00002c5f0000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900050000000b001d36b536b00000040f000000050b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900002c4a0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00002c460000c13d000000000006004b00002c570000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000000c0a00002900002d580000613d0000001f01400039000000600110018f0000000b05000029000000000cb1001900000dd100c0009c00002d0d0000213d0000004000c0043f000000200030008c00002d130000413d00000000020b0433000500000002001d00000e220200004100000000002c04350000000002000414000000040050008c00002c9e0000613d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900020000000c001d36b536b00000040f000000020c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c001900002c890000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b00002c850000c13d000000000006004b00002c960000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000000c0a00002900002d640000613d0000001f01400039000000600110018f0000000b05000029000000000bc1001900000dd100b0009c00002d0d0000213d0000004000b0043f000000200030008c00002d130000413d00000000060c043300000e230200004100000000002b04350000000002000414000000040050008c00002cde0000613d000100000006001d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900020000000b001d36b536b00000040f000000020b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900002cc80000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00002cc40000c13d000000000006004b00002cd50000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000000c0a00002900002d700000613d0000001f01400039000000600110018f0000000b0500002900000001060000290000000001b1001900000dd10010009c00002d0d0000213d000000400010043f000000200030008c00002d130000413d00000e1f0010009c00002d0d0000213d00000000020b0433000001a003100039000000400030043f00000180031000390000000d0400002900000000004304350000016003100039000000000023043500000140021000390000000000620435000001200210003900000005030000290000000000320435000001000210003900000006030000290000000000320435000000e0021000390000000000a20435000000c00210003900000003030000290000000000320435000000a0021000390000000803000029000000000032043500000080021000390000000403000029000000000032043500000060021000390000000703000029000000000032043500000040021000390000000000520435000000090200002900000db102200197000000200310003900000000002304350000000a020000290000000000210435000000000001042d00000e1301000041000000000010043f0000004101000039000000040010043f00000dd901000041000036b7000104300000000001000019000036b7000104300000001f0530018f00000db006300198000000400200043d000000000462001900002d200000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d1c0000c13d000000000005004b00002d2d0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000dae0020009c00000dae020080410000004002200210000000000112019f000036b700010430000000000001042f0000001f0530018f00000db006300198000000400200043d000000000462001900002d200000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d3b0000c13d00002d200000013d0000001f0530018f00000db006300198000000400200043d000000000462001900002d200000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d470000c13d00002d200000013d0000001f0530018f00000db006300198000000400200043d000000000462001900002d200000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d530000c13d00002d200000013d0000001f0530018f00000db006300198000000400200043d000000000462001900002d200000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d5f0000c13d00002d200000013d0000001f0530018f00000db006300198000000400200043d000000000462001900002d200000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d6b0000c13d00002d200000013d0000001f0530018f00000db006300198000000400200043d000000000462001900002d200000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002d770000c13d00002d200000013d0002000000000002000000400200043d00000e270020009c00002e570000813d0000004003200039000000400030043f00000020032000390000000000030435000000000002043500000dd702000041000000400c00043d00000000002c0435000000000200041400000db105100197000000040050008c000200000005001d00002d920000c13d0000000003000031000000200030008c0000002004000039000000000403401900002dc10000013d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900010000000c001d36b536b00000040f000000010c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c001900002daf0000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b00002dab0000c13d000000000006004b00002dbc0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002e5d0000613d00000002050000290000001f01400039000000600110018f000000000bc1001900000000001b004b0000000002000039000000010200403900000dd100b0009c00002e570000213d000000010020019000002e570000c13d0000004000b0043f0000001f0030008c00002e550000a13d00000000020c043300000db10020009c00002e550000213d00000e1b0400004100000000004b04350000000004000414000000040020008c00002e060000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000db3011001c700010000000b001d36b536b00000040f000000010b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900002df20000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00002dee0000c13d000000000006004b00002dff0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002e690000613d0000001f01400039000000600110018f0000000205000029000000000cb1001900000dd100c0009c00002e570000213d0000004000c0043f000000200030008c00002e550000413d00000000020b043300000db10020009c00002e550000213d00000e1d0400004100000000004c04350000000404c0003900000000005404350000000004000414000000040020008c00002e460000613d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000dd9011001c700010000000c001d36b536b00000040f000000010c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c001900002e320000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b00002e2e0000c13d000000000006004b00002e3f0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000002e750000613d0000001f01400039000000600110018f00000002050000290000000001c1001900000dd10010009c00002e570000213d000000400010043f000000200030008c00002e550000413d00000dfd0010009c00002e570000213d00000000020c04330000004003100039000000400030043f000000200310003900000000002304350000000000510435000000000001042d0000000001000019000036b70001043000000e1301000041000000000010043f0000004101000039000000040010043f00000dd901000041000036b7000104300000001f0530018f00000db006300198000000400200043d000000000462001900002e800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002e640000c13d00002e800000013d0000001f0530018f00000db006300198000000400200043d000000000462001900002e800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002e700000c13d00002e800000013d0000001f0530018f00000db006300198000000400200043d000000000462001900002e800000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00002e7c0000c13d000000000005004b00002e8d0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000dae0020009c00000dae020080410000004002200210000000000112019f000036b7000104300011000000000002000000400200043d00000e280020009c000033720000813d0000022003200039000000400030043f00000200032000390000000000030435000001e0032000390000000000030435000001c0032000390000000000030435000001a00320003900000000000304350000018003200039000000000003043500000160032000390000000000030435000001400320003900000000000304350000012003200039000000000003043500000100032000390000000000030435000000e0032000390000000000030435000000c0032000390000000000030435000000a003200039000000000003043500000080032000390000000000030435000000600320003900000000000304350000004003200039000000000003043500000020032000390000000000030435000000000002043500000dd602000041000000400b00043d00000000002b0435000000000200041400000db105100197000000040050008c000e00000005001d00002ec70000c13d0000000003000031000000200030008c0000002004000039000000000403401900002ef60000013d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900110000000b001d36b536b00000040f000000110b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900002ee40000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00002ee00000c13d000000000006004b00002ef10000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000033960000613d0000000e050000290000001f01400039000000600110018f000000000cb1001900000000001c004b0000000002000039000000010200403900000dd100c0009c000033720000213d0000000100200190000033720000c13d0000004000c0043f0000001f0030008c000033700000a13d00000000020b0433000b00000002001d00000dd70200004100000000002c04350000000002000414000000040050008c00002f3b0000613d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900110000000c001d36b536b00000040f000000110c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c001900002f270000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b00002f230000c13d000000000006004b00002f340000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000033a20000613d0000001f01400039000000600110018f0000000e05000029000000000bc1001900000dd100b0009c000033720000213d0000004000b0043f000000200030008c000033700000413d00000000070c043300000db10070009c000033700000213d00000dd80100004100000000061b04360000000401b0003900000000005104350000000001000414000000040070008c000d00000007001d00002f500000c13d000000400030008c0000004004000039000000000403401900002f820000013d001000000006001d00000dae00b0009c00000dae0200004100000000020b4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000dd9011001c7000000000207001900110000000b001d36b536b00000040f000000110b0000290000000003010019000000600330027000000dae03300197000000400030008c000000400400003900000000040340190000001f0640018f000000600740019000000000057b001900002f6e0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00002f6a0000c13d000000000006004b00002f7b0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000033ae0000613d0000000e050000290000000d0700002900000010060000290000001f01400039000000e00110018f000000000cb1001900000dd100c0009c000033720000213d0000004000c0043f000000400030008c000033700000413d00000000020b0433000000000002004b0000000001000039000000010100c039000a00000002001d000000000012004b000033700000c13d0000000001060433000900000001001d00000dda0100004100000000001c04350000000001000414000000040050008c00002f9a0000c13d000000200400003900002fca0000013d00000dae00c0009c00000dae0200004100000000020c4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c7000000000205001900110000000c001d36b536b00000040f000000110c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c001900002fb70000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b00002fb30000c13d000000000006004b00002fc40000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000033ba0000613d0000000e050000290000000d070000290000001f01400039000000600110018f000000000bc1001900000dd100b0009c000033720000213d0000004000b0043f000000200030008c000033700000413d00000000020c0433000c00000002001d00000db10020009c000033700000213d00000ddb0200004100000000002b043500000000020004140000000c04000029000000040040008c0000300e0000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000000c0200002900110000000b001d36b536b00000040f000000110b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900002ff90000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00002ff50000c13d000000000006004b000030060000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000033c60000613d0000001f01400039000000600110018f0000000e050000290000000d07000029000000000ab1001900000dd100a0009c000033720000213d0000004000a0043f000000200030008c000033700000413d00000000010b0433000800000001001d000000ff0010008c000033700000213d00000ddc080000410000002009000039000000000b00001900000000060000190000002401a000390000000000b1043500000000008a04350000000401a0003900000000005104350000000001000414000000040070008c00000000040900190000305a0000613d000f0000000b001d001100000006001d00000dae00a0009c00000dae0200004100000000020a4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000ddd011001c7000000000207001900100000000a001d36b536b00000040f000000100a0000290000000003010019000000600330027000000dae03300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000030430000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b0000303f0000c13d0000001f07400190000030500000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0002000000010355000000010020019000000020090000390000000f0b000029000033780000613d0000000e0500002900000011060000290000000d0700002900000ddc080000410000001f01400039000000600110018f000000000ca1001900000000001c004b0000000002000039000000010200403900000dd100c0009c000033720000213d0000000100200190000033720000c13d0000004000c0043f000000200030008c000033700000413d00000000020a0433000000000002004b0000000004000039000000010400c039000000000042004b000033700000c13d0000000002b201cf000000000626019f0000000102b00039000000ff0b20018f0000000800b0008c000000000a0c00190000301c0000a13d00000ddf0200004100000000002c04350000000002000414000000040050008c000030ad0000613d001100000006001d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900100000000c001d36b536b00000040f000000100c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000030970000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000030930000c13d000000000006004b000030a40000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000033d20000613d0000001f01400039000000600110018f0000000e0500002900000011060000290000000d07000029000000000bc1001900000dd100b0009c000033720000213d0000004000b0043f000000200030008c000033700000413d00000000020c0433000000000002004b001100000006001d000030f80000613d00000de00200004100000000002b04350000000002000414000000040050008c000030ef0000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c70000000002050019000f0000000b001d36b536b00000040f0000000f0b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000030d90000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000030d50000c13d000000000006004b000030e60000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000344a0000613d0000001f01400039000000600110018f0000000e0500002900000011060000290000000d070000290000000001b1001900000dd10010009c000033720000213d000000400010043f000000200030008c000033700000413d00000000020b0433000000000b010019000030f90000013d000000000200001900000de10100004100000000001b04350000000001000414000000040050008c001000000002001d000031010000c13d0000002004000039000031320000013d00000dae00b0009c00000dae0200004100000000020b4019000000400220021000000dae0010009c00000dae01008041000000c001100210000000000121019f00000db3011001c70000000002050019000f0000000b001d36b536b00000040f0000000f0b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b00190000311e0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000311a0000c13d000000000006004b0000312b0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000033de0000613d0000000e0500002900000011060000290000000d070000290000001f01400039000000600110018f000000000cb1001900000dd100c0009c000033720000213d0000004000c0043f000000200030008c000033700000413d00000000020b0433000f00000002001d00000de20200004100000000002c04350000000002000414000000040050008c000031740000613d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900070000000c001d36b536b00000040f000000070c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c00190000315e0000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b0000315a0000c13d000000000006004b0000316b0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000033ea0000613d0000001f01400039000000600110018f0000000e0500002900000011060000290000000d07000029000000000bc1001900000dd100b0009c000033720000213d0000004000b0043f000000200030008c000033700000413d00000000020c0433000700000002001d00000de30200004100000000002b04350000000402b0003900000000005204350000000002000414000000040070008c000031b60000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c7000000000207001900060000000b001d36b536b00000040f000000060b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000031a00000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000319c0000c13d000000000006004b000031ad0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000033f60000613d0000001f01400039000000600110018f0000000e0500002900000011060000290000000d07000029000000000cb1001900000dd100c0009c000033720000213d0000004000c0043f000000200030008c000033700000413d00000000020b0433000d00000002001d00000de40200004100000000002c04350000000402c0003900000000005204350000000002000414000000040070008c000031f70000613d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c7000000000207001900060000000c001d36b536b00000040f000000060c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000031e20000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000031de0000c13d000000000006004b000031ef0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000034020000613d0000001f01400039000000600110018f0000000e050000290000001106000029000000000bc1001900000dd100b0009c000033720000213d0000004000b0043f000000200030008c000033700000413d00000000020c0433000600000002001d00000de50200004100000000002b04350000000002000414000000040050008c000032360000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900050000000b001d36b536b00000040f000000050b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000032210000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000321d0000c13d000000000006004b0000322e0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000340e0000613d0000001f01400039000000600110018f0000000e050000290000001106000029000000000cb1001900000dd100c0009c000033720000213d0000004000c0043f000000200030008c000033700000413d00000000020b0433000500000002001d00000de60200004100000000002c04350000000002000414000000040050008c000032750000613d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900040000000c001d36b536b00000040f000000040c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000032600000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b0000325c0000c13d000000000006004b0000326d0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000341a0000613d0000001f01400039000000600110018f0000000e050000290000001106000029000000000bc1001900000dd100b0009c000033720000213d0000004000b0043f000000200030008c000033700000413d00000000020c0433000400000002001d00000ddf0200004100000000002b04350000000002000414000000040050008c000032b40000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900030000000b001d36b536b00000040f000000030b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b00190000329f0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000329b0000c13d000000000006004b000032ac0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000034260000613d0000001f01400039000000600110018f0000000e050000290000001106000029000000000cb1001900000dd100c0009c000033720000213d0000004000c0043f000000200030008c000033700000413d00000000020b0433000300000002001d00000de70200004100000000002c04350000000002000414000000040050008c000032f30000613d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900020000000c001d36b536b00000040f000000020c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000032de0000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000032da0000c13d000000000006004b000032eb0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000034320000613d0000001f01400039000000600110018f0000000e050000290000001106000029000000000bc1001900000dd100b0009c000033720000213d0000004000b0043f000000200030008c000033700000413d00000000070c043300000ddb0200004100000000002b04350000000002000414000000040050008c000033330000613d000100000007001d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900020000000b001d36b536b00000040f000000020b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b00190000331d0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000033190000c13d000000000006004b0000332a0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000343e0000613d0000001f01400039000000600110018f0000000e05000029000000110600002900000001070000290000000001b1001900000dd10010009c000033720000213d000000400010043f000000200030008c000033700000413d00000000020b0433000000ff0020008c000033700000213d00000dd50010009c000033720000213d0000022003100039000000400030043f000002000310003900000000006304350000000803000029000000ff0330018f000001e0041000390000000000340435000001c0031000390000000000230435000001a0021000390000000c03000029000000000032043500000180021000390000000903000029000000000032043500000160021000390000000a03000029000000000032043500000140021000390000000000720435000001200210003900000003030000290000000000320435000001000210003900000004030000290000000000320435000000e00210003900000005030000290000000000320435000000c00210003900000006030000290000000000320435000000a0021000390000000d03000029000000000032043500000080021000390000000703000029000000000032043500000060021000390000000f03000029000000000032043500000040021000390000001003000029000000000032043500000020021000390000000b0300002900000000003204350000000000510435000000000001042d0000000001000019000036b70001043000000e1301000041000000000010043f0000004101000039000000040010043f00000dd901000041000036b7000104300000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000337f0000c13d000000000005004b000033900000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000dae0020009c00000dae020080410000004002200210000000000112019f000036b7000104300000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000339d0000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000033a90000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000033b50000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000033c10000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000033cd0000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000033d90000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000033e50000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000033f10000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000033fd0000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000034090000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000034150000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000034210000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000342d0000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000034390000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000034450000c13d000033830000013d0000001f0530018f00000db006300198000000400200043d0000000004620019000033830000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000034510000c13d000033830000013d0007000000000002000000400300043d00000e290030009c0000360e0000813d000000c004300039000000400040043f000000a004300039000000000004043500000080043000390000000000040435000000600430003900000000000404350000004004300039000000000004043500000020043000390000000000040435000000000003043500000df203000041000000400c00043d00000000003c043500000db1032001970000000402c00039000700000003001d0000000000320435000000000200041400000db105100197000000040050008c000600000005001d000034780000c13d0000000003000031000000200030008c00000020040000390000000004034019000034a70000013d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c7000000000205001900050000000c001d36b536b00000040f000000050c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c0019000034950000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000034910000c13d000000000006004b000034a20000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000036160000613d00000006050000290000001f01400039000000600110018f000000000bc1001900000000001b004b0000000002000039000000010200403900000dd100b0009c0000360e0000213d00000001002001900000360e0000c13d0000004000b0043f0000001f0030008c000036140000a13d00000000020c0433000500000002001d00000df30200004100000000002b04350000000402b00039000000070400002900000000004204350000000002000414000000040050008c000034ef0000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c7000000000205001900040000000b001d36b536ab0000040f000000040b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000034db0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000034d70000c13d000000000006004b000034e80000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000036220000613d0000001f01400039000000600110018f0000000605000029000000000cb1001900000dd100c0009c0000360e0000213d0000004000c0043f000000200030008c000036140000413d00000000020b0433000400000002001d00000df40200004100000000002c04350000000402c00039000000070400002900000000004204350000000002000414000000040050008c000035300000613d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000dd9011001c7000000000205001900030000000c001d36b536ab0000040f000000030c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c00190000351c0000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000035180000c13d000000000006004b000035290000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000362e0000613d0000001f01400039000000600110018f0000000605000029000000000bc1001900000dd100b0009c0000360e0000213d0000004000b0043f000000200030008c000036140000413d00000000020c0433000300000002001d00000dda0200004100000000002b04350000000002000414000000040050008c0000356e0000613d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0020009c00000dae02008041000000c002200210000000000112019f00000db3011001c7000000000205001900020000000b001d36b536b00000040f000000020b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b00190000355a0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000035560000c13d000000000006004b000035670000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000200000001035500000001002001900000363a0000613d0000001f01400039000000600110018f0000000605000029000000000cb1001900000dd100c0009c0000360e0000213d0000004000c0043f000000200030008c000036140000413d00000000020b043300000db10020009c000036140000213d00000df20400004100000000004c04350000000406c00039000000070400002900000000004604350000000004000414000000040020008c000035b10000613d00000dae00c0009c00000dae0100004100000000010c4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000dd9011001c7000100000002001d00020000000c001d36b536b00000040f000000020c0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057c00190000359c0000613d000000000801034f00000000090c0019000000008a08043c0000000009a90436000000000059004b000035980000c13d000000000006004b000035a90000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000036460000613d0000001f01400039000000600110018f00000006050000290000000102000029000000000bc1001900000dd100b0009c0000360e0000213d0000004000b0043f000000200030008c000036140000413d00000000070c04330000002404b00039000000000054043500000df50400004100000000004b04350000000406b00039000000070400002900000000004604350000000004000414000000040020008c000035f40000613d000200000007001d00000dae00b0009c00000dae0100004100000000010b4019000000400110021000000dae0040009c00000dae04008041000000c003400210000000000113019f00000ddd011001c700070000000b001d36b536b00000040f000000070b0000290000000003010019000000600330027000000dae03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000035df0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000035db0000c13d000000000006004b000035ec0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00020000000103550000000100200190000036520000613d0000001f01400039000000600110018f000000060500002900000002070000290000000001b1001900000dd10010009c0000360e0000213d000000400010043f000000200030008c000036140000413d00000df10010009c0000360e0000213d00000000020b0433000000c003100039000000400030043f000000a0031000390000000000230435000000800210003900000000007204350000006002100039000000030300002900000000003204350000004002100039000000040300002900000000003204350000002002100039000000050300002900000000003204350000000000510435000000000001042d00000e1301000041000000000010043f0000004101000039000000040010043f00000dd901000041000036b7000104300000000001000019000036b7000104300000001f0530018f00000db006300198000000400200043d00000000046200190000365d0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000361d0000c13d0000365d0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000365d0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000036290000c13d0000365d0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000365d0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000036350000c13d0000365d0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000365d0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000036410000c13d0000365d0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000365d0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000364d0000c13d0000365d0000013d0000001f0530018f00000db006300198000000400200043d00000000046200190000365d0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000036590000c13d000000000005004b0000366a0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000dae0020009c00000dae020080410000004002200210000000000112019f000036b700010430000000010010008c000036780000613d000000020010008c000036860000c13d00000e0801000041000000000010044300000000010004140000367b0000013d00000e06010000410000000000100443000000000100041400000dae0010009c00000dae01008041000000c00110021000000e07011001c70000800b0200003936b536b00000040f0000000100200190000036850000613d000000000101043b000000000001042d000000000001042f00000e1301000041000000000010043f0000005101000039000000040010043f00000dd901000041000036b700010430000000000001042f00000000050100190000000000200443000000050030008c0000369b0000413d000000040100003900000000020000190000000506200210000000000664001900000005066002700000000006060031000000000161043a0000000102200039000000000031004b000036930000413d00000dae0030009c00000dae030080410000006001300210000000000200041400000dae0020009c00000dae02008041000000c002200210000000000112019f00000e2a011001c7000000000205001936b536b00000040f0000000100200190000036aa0000613d000000000101043b000000000001042d000000000001042f000036ae002104210000000102000039000000000001042d0000000002000019000000000001042d000036b3002104230000000102000039000000000001042d0000000002000019000000000001042d000036b500000432000036b60001042e000036b70001043000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000ffffffffffffffffffffffffffffffffffffffff09c8f7ec0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000001e13380ae0fcab3000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000140000001000000000000000000000000000000000000000000000000000000000000000000000000007c51b64100000000000000000000000000000000000000000000000000000000c7ad089400000000000000000000000000000000000000000000000000000000d77ebf9500000000000000000000000000000000000000000000000000000000d77ebf9600000000000000000000000000000000000000000000000000000000e0a67f1100000000000000000000000000000000000000000000000000000000e1d146fb00000000000000000000000000000000000000000000000000000000c7ad089500000000000000000000000000000000000000000000000000000000d26998e900000000000000000000000000000000000000000000000000000000aa5dbd2200000000000000000000000000000000000000000000000000000000aa5dbd2300000000000000000000000000000000000000000000000000000000b3124239000000000000000000000000000000000000000000000000000000007c51b642000000000000000000000000000000000000000000000000000000007c84e3b30000000000000000000000000000000000000000000000000000000047d86a80000000000000000000000000000000000000000000000000000000006857249b000000000000000000000000000000000000000000000000000000006857249c000000000000000000000000000000000000000000000000000000007a27db570000000000000000000000000000000000000000000000000000000047d86a810000000000000000000000000000000000000000000000000000000055dd951500000000000000000000000000000000000000000000000000000000345954db00000000000000000000000000000000000000000000000000000000345954dc000000000000000000000000000000000000000000000000000000003e3e399c000000000000000000000000000000000000000000000000000000000d3ae318000000000000000000000000000000000000000000000000000000001f884fdf310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e0000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000000000000000000000000000000000ffffffffffffff7f00000000000000000000000000000000000000000000003fffffffffffffffe0000000000000000000000000000000000000000000000000fffffffffffffddf182df0f5000000000000000000000000000000000000000000000000000000005fe3b567000000000000000000000000000000000000000000000000000000008e8f294b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000006f307dc300000000000000000000000000000000000000000000000000000000313ce56700000000000000000000000000000000000000000000000000000000e85a2960000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffdf18160ddd00000000000000000000000000000000000000000000000000000000ae9d70b000000000000000000000000000000000000000000000000000000000f8f9da2800000000000000000000000000000000000000000000000000000000173b99040000000000000000000000000000000000000000000000000000000002c3bcbb000000000000000000000000000000000000000000000000000000004a5844320000000000000000000000000000000000000000000000000000000047bd3718000000000000000000000000000000000000000000000000000000008f840ddd000000000000000000000000000000000000000000000000000000003b1d21a200000000000000000000000000000000000000000000000000000000f36dba380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000008000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000080000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffebf000000000000000000000000000000000000000000000000ffffffffffffff3f70a082310000000000000000000000000000000000000000000000000000000017bfdfbc000000000000000000000000000000000000000000000000000000003af9e66900000000000000000000000000000000000000000000000000000000dd62ed3e00000000000000000000000000000000000000000000000000000000b0772d0b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000800000000000000000020000020000000000000000000000000000004400000000000000000000000022abdbf50000000000000000000000000000000000000000000000000000000061252fd100000000000000000000000000000000000000000000000000000000f7c618c1000000000000000000000000000000000000000000000000000000001627ee8900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffbf000000000000000000000000000000000000000000000000ffffffffffffff9f8f693ec70000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff81814945000000000000000000000000000000000000000000000000000000002c427b570000000000000000000000000000000000000000000000000000000092a1823500000000000000000000000000000000000000000000000000000000aa5af0fd000000000000000000000000000000000000000000000000000000007c05a7c500000000000000000000000000000000000000000000000000000000796b89b91644bc98cd93958e4c9038275d622183e25ac5af08cc6b5d95539132020000020000000000000000000000000000000400000000000000000000000042cbb15ccdc3cad6266b0e7a08c0454b23bf29dc2df74b6f3c209e9336465bd10000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000c097ce7bc90715b34b9f10000000006e657720696e646578206f766572666c6f777300000000000000000000000000000000010000000000000000000000000000000000000000000000000000000008c379a00000000000000000000000000000000000000000000000000000000074c4c1cc000000000000000000000000000000000000000000000000000000006dfd08ca00000000000000000000000000000000000000000000000000000000160c3a030000000000000000000000000000000000000000000000000000000095dd919300000000000000000000000000000000000000000000000000000000552c0971000000000000000000000000000000000000000000000000000000004e487b7100000000000000000000000000000000000000000000000000000000266e0a7f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000440000008000000000000000007aee632d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000002200000000000000000000000000000000000000000000000000000000000000000ffffffffffffff5f0000000000000000000000000000000000000004000000e00000000000000000000000000000000000000000000000000000000000000000ffffffffffffff1f7dc0d1d000000000000000000000000000000000000000000000000000000000bbcac55700000000000000000000000000000000000000000000000000000000fc57d4df00000000000000000000000000000000000000000000000000000000d88ff1f400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffe5fa3aefa2c00000000000000000000000000000000000000000000000000000000e8755446000000000000000000000000000000000000000000000000000000004ada90af00000000000000000000000000000000000000000000000000000000db5c65de00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffedfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000000000000000000000000000000000fffffffffffffe60000000000000000000000000000000000000000000000000ffffffffffffffc0000000000000000000000000000000000000000000000000fffffffffffffde0000000000000000000000000000000000000000000000000ffffffffffffff4002000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd266e967e3b2382c6511fd4150dd11c23ea0355910672dd36d07081e6b4a2b6" ] } diff --git a/deployments/zksyncmainnet/solcInputs/10818118264cbc82e2eea514eb3f075b.json b/deployments/zksyncmainnet/solcInputs/10818118264cbc82e2eea514eb3f075b.json new file mode 100644 index 000000000..2cef6c6a2 --- /dev/null +++ b/deployments/zksyncmainnet/solcInputs/10818118264cbc82e2eea514eb3f075b.json @@ -0,0 +1,247 @@ +{ + "language": "Solidity", + "sources": { + "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface AggregatorV3Interface {\n function decimals() external view returns (uint8);\n\n function description() external view returns (string memory);\n\n function version() external view returns (uint256);\n\n function getRoundData(uint80 _roundId)\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n\n function latestRoundData()\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n}\n" + }, + "@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/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/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/access/AccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\nimport \"../utils/Context.sol\";\nimport \"../utils/Strings.sol\";\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address => bool) members;\n bytes32 adminRole;\n }\n\n mapping(bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with a standardized message including the required role.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n *\n * _Available since v4.1._\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role);\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view virtual override returns (bool) {\n return _roles[role].members[account];\n }\n\n /**\n * @dev Revert with a standard message if `_msgSender()` is missing `role`.\n * Overriding this function changes the behavior of the {onlyRole} modifier.\n *\n * Format of the revert message is described in {_checkRole}.\n *\n * _Available since v4.6._\n */\n function _checkRole(bytes32 role) internal view virtual {\n _checkRole(role, _msgSender());\n }\n\n /**\n * @dev Revert with a standard message if `account` is missing `role`.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n */\n function _checkRole(bytes32 role, address account) internal view virtual {\n if (!hasRole(role, account)) {\n revert(\n string(\n abi.encodePacked(\n \"AccessControl: account \",\n Strings.toHexString(account),\n \" is missing role \",\n Strings.toHexString(uint256(role), 32)\n )\n )\n );\n }\n }\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 {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {\n return _roles[role].adminRole;\n }\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 * May emit a {RoleGranted} event.\n */\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\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 * May emit a {RoleRevoked} event.\n */\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\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 revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n *\n * May emit a {RoleRevoked} event.\n */\n function renounceRole(bytes32 role, address account) public virtual override {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * May emit a {RoleGranted} event.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n *\n * NOTE: This function is deprecated in favor of {_grantRole}.\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleGranted} event.\n */\n function _grantRole(bytes32 role, address account) internal virtual {\n if (!hasRole(role, account)) {\n _roles[role].members[account] = true;\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * Internal function without access restriction.\n *\n * May emit a {RoleRevoked} event.\n */\n function _revokeRole(bytes32 role, address account) internal virtual {\n if (hasRole(role, account)) {\n _roles[role].members[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n }\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/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/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/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (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 function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n // The surrounding unchecked block does not change this fact.\n // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1, \"Math: mulDiv overflow\");\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10 ** 64) {\n value /= 10 ** 64;\n result += 64;\n }\n if (value >= 10 ** 32) {\n value /= 10 ** 32;\n result += 32;\n }\n if (value >= 10 ** 16) {\n value /= 10 ** 16;\n result += 16;\n }\n if (value >= 10 ** 8) {\n value /= 10 ** 8;\n result += 8;\n }\n if (value >= 10 ** 4) {\n value /= 10 ** 4;\n result += 4;\n }\n if (value >= 10 ** 2) {\n value /= 10 ** 2;\n result += 2;\n }\n if (value >= 10 ** 1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/SignedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n /**\n * @dev Returns the largest of two signed numbers.\n */\n function max(int256 a, int256 b) internal pure returns (int256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two signed numbers.\n */\n function min(int256 a, int256 b) internal pure returns (int256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two signed numbers without overflow.\n * The result is rounded towards zero.\n */\n function average(int256 a, int256 b) internal pure returns (int256) {\n // Formula from the book \"Hacker's Delight\"\n int256 x = (a & b) + ((a ^ b) >> 1);\n return x + (int256(uint256(x) >> 255) & (a ^ b));\n }\n\n /**\n * @dev Returns the absolute unsigned value of a signed value.\n */\n function abs(int256 n) internal pure returns (uint256) {\n unchecked {\n // must be unchecked in order to support `n = type(int256).min`\n return uint256(n >= 0 ? n : -n);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `int256` to its ASCII `string` decimal representation.\n */\n function toString(int256 value) internal pure returns (string memory) {\n return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n\n /**\n * @dev Returns true if the two strings are equal.\n */\n function equal(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(bytes(a)) == keccak256(bytes(b));\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/AccessControlManager.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"./IAccessControlManagerV8.sol\";\n\n/**\n * @title AccessControlManager\n * @author Venus\n * @dev This contract is a wrapper of OpenZeppelin AccessControl extending it in a way to standartize access control within Venus Smart Contract Ecosystem.\n * @notice Access control plays a crucial role in the Venus governance model. It is used to restrict functions so that they can only be called from one\n * account or list of accounts (EOA or Contract Accounts).\n *\n * The implementation of `AccessControlManager`(https://github.com/VenusProtocol/governance-contracts/blob/main/contracts/Governance/AccessControlManager.sol)\n * inherits the [Open Zeppelin AccessControl](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/AccessControl.sol)\n * contract as a base for role management logic. There are two role types: admin and granular permissions.\n * \n * ## Granular Roles\n * \n * Granular roles are built by hashing the contract address and its function signature. For example, given contract `Foo` with function `Foo.bar()` which\n * is guarded by ACM, calling `giveRolePermission` for account B do the following:\n * \n * 1. Compute `keccak256(contractFooAddress,functionSignatureBar)`\n * 1. Add the computed role to the roles of account B\n * 1. Account B now can call `ContractFoo.bar()`\n * \n * ## Admin Roles\n * \n * Admin roles allow for an address to call a function signature on any contract guarded by the `AccessControlManager`. This is particularly useful for\n * contracts created by factories.\n * \n * For Admin roles a null address is hashed in place of the contract address (`keccak256(0x0000000000000000000000000000000000000000,functionSignatureBar)`.\n * \n * In the previous example, giving account B the admin role, account B will have permissions to call the `bar()` function on any contract that is guarded by\n * ACM, not only contract A.\n * \n * ## Protocol Integration\n * \n * All restricted functions in Venus Protocol use a hook to ACM in order to check if the caller has the right permission to call the guarded function.\n * `AccessControlledV5` and `AccessControlledV8` abstract contract makes this integration easier. They call ACM's external method\n * `isAllowedToCall(address caller, string functionSig)`. Here is an example of how `setCollateralFactor` function in `Comptroller` is integrated with ACM:\n\n```\n contract Comptroller is [...] AccessControlledV8 {\n [...]\n function setCollateralFactor(VToken vToken, uint256 newCollateralFactorMantissa, uint256 newLiquidationThresholdMantissa) external {\n _checkAccessAllowed(\"setCollateralFactor(address,uint256,uint256)\");\n [...]\n }\n }\n```\n */\ncontract AccessControlManager is AccessControl, IAccessControlManagerV8 {\n /// @notice Emitted when an account is given a permission to a certain contract function\n /// @dev If contract address is 0x000..0 this means that the account is a default admin of this function and\n /// can call any contract function with this signature\n event PermissionGranted(address account, address contractAddress, string functionSig);\n\n /// @notice Emitted when an account is revoked a permission to a certain contract function\n event PermissionRevoked(address account, address contractAddress, string functionSig);\n\n constructor() {\n // Grant the contract deployer the default admin role: it will be able\n // to grant and revoke any roles\n _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n }\n\n /**\n * @notice Gives a function call permission to one single account\n * @dev this function can be called only from Role Admin or DEFAULT_ADMIN_ROLE\n * @param contractAddress address of contract for which call permissions will be granted\n * @dev if contractAddress is zero address, the account can access the specified function\n * on **any** contract managed by this ACL\n * @param functionSig signature e.g. \"functionName(uint256,bool)\"\n * @param accountToPermit account that will be given access to the contract function\n * @custom:event Emits a {RoleGranted} and {PermissionGranted} events.\n */\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) public {\n bytes32 role = keccak256(abi.encodePacked(contractAddress, functionSig));\n grantRole(role, accountToPermit);\n emit PermissionGranted(accountToPermit, contractAddress, functionSig);\n }\n\n /**\n * @notice Revokes an account's permission to a particular function call\n * @dev this function can be called only from Role Admin or DEFAULT_ADMIN_ROLE\n * \t\tMay emit a {RoleRevoked} event.\n * @param contractAddress address of contract for which call permissions will be revoked\n * @param functionSig signature e.g. \"functionName(uint256,bool)\"\n * @custom:event Emits {RoleRevoked} and {PermissionRevoked} events.\n */\n function revokeCallPermission(\n address contractAddress,\n string calldata functionSig,\n address accountToRevoke\n ) public {\n bytes32 role = keccak256(abi.encodePacked(contractAddress, functionSig));\n revokeRole(role, accountToRevoke);\n emit PermissionRevoked(accountToRevoke, contractAddress, functionSig);\n }\n\n /**\n * @notice Verifies if the given account can call a contract's guarded function\n * @dev Since restricted contracts using this function as a permission hook, we can get contracts address with msg.sender\n * @param account for which call permissions will be checked\n * @param functionSig restricted function signature e.g. \"functionName(uint256,bool)\"\n * @return false if the user account cannot call the particular contract function\n *\n */\n function isAllowedToCall(address account, string calldata functionSig) public view returns (bool) {\n bytes32 role = keccak256(abi.encodePacked(msg.sender, functionSig));\n\n if (hasRole(role, account)) {\n return true;\n } else {\n role = keccak256(abi.encodePacked(address(0), functionSig));\n return hasRole(role, account);\n }\n }\n\n /**\n * @notice Verifies if the given account can call a contract's guarded function\n * @dev This function is used as a view function to check permissions rather than contract hook for access restriction check.\n * @param account for which call permissions will be checked against\n * @param contractAddress address of the restricted contract\n * @param functionSig signature of the restricted function e.g. \"functionName(uint256,bool)\"\n * @return false if the user account cannot call the particular contract function\n */\n function hasPermission(\n address account,\n address contractAddress,\n string calldata functionSig\n ) public view returns (bool) {\n bytes32 role = keccak256(abi.encodePacked(contractAddress, functionSig));\n return hasRole(role, account);\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/interfaces/FeedRegistryInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\ninterface FeedRegistryInterface {\n function latestRoundDataByName(\n string memory base,\n string memory quote\n )\n external\n view\n returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\n\n function decimalsByName(string memory base, string memory quote) external view returns (uint8);\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/PublicResolverInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n// SPDX-FileCopyrightText: 2022 Venus\npragma solidity ^0.8.25;\n\ninterface PublicResolverInterface {\n function addr(bytes32 node) external view returns (address payable);\n}\n" + }, + "@venusprotocol/oracle/contracts/interfaces/SIDRegistryInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n// SPDX-FileCopyrightText: 2022 Venus\npragma solidity ^0.8.25;\n\ninterface SIDRegistryInterface {\n function resolver(bytes32 node) external view returns (address);\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/oracles/BinanceOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport \"../interfaces/VBep20Interface.sol\";\nimport \"../interfaces/SIDRegistryInterface.sol\";\nimport \"../interfaces/FeedRegistryInterface.sol\";\nimport \"../interfaces/PublicResolverInterface.sol\";\nimport \"../interfaces/OracleInterface.sol\";\nimport \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport \"../interfaces/OracleInterface.sol\";\n\n/**\n * @title BinanceOracle\n * @author Venus\n * @notice This oracle fetches price of assets from Binance.\n */\ncontract BinanceOracle is AccessControlledV8, OracleInterface {\n /// @notice Used to fetch feed registry address.\n address public sidRegistryAddress;\n\n /// @notice Set this as asset address for BNB. This is the underlying address for vBNB\n address public constant BNB_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\n\n /// @notice Max stale period configuration for assets\n mapping(string => uint256) public maxStalePeriod;\n\n /// @notice Override symbols to be compatible with Binance feed registry\n mapping(string => string) public symbols;\n\n /// @notice Used to fetch price of assets used directly when space ID is not supported by current chain.\n address public feedRegistryAddress;\n\n /// @notice Emits when asset stale period is updated.\n event MaxStalePeriodAdded(string indexed asset, uint256 maxStalePeriod);\n\n /// @notice Emits when symbol of the asset is updated.\n event SymbolOverridden(string indexed symbol, string overriddenSymbol);\n\n /// @notice Emits when address of feed registry is updated.\n event FeedRegistryUpdated(address indexed oldFeedRegistry, address indexed newFeedRegistry);\n\n /**\n * @notice Checks whether an address is null or not\n */\n modifier notNullAddress(address someone) {\n if (someone == address(0)) revert(\"can't be zero address\");\n _;\n }\n\n /// @notice Constructor for the implementation contract.\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Sets the contracts required to fetch prices\n * @param _sidRegistryAddress Address of SID registry\n * @param _acm Address of the access control manager contract\n */\n function initialize(address _sidRegistryAddress, address _acm) external initializer {\n sidRegistryAddress = _sidRegistryAddress;\n __AccessControlled_init(_acm);\n }\n\n /**\n * @notice Used to set the max stale period of an asset\n * @param symbol The symbol of the asset\n * @param _maxStalePeriod The max stake period\n */\n function setMaxStalePeriod(string memory symbol, uint256 _maxStalePeriod) external {\n _checkAccessAllowed(\"setMaxStalePeriod(string,uint256)\");\n if (_maxStalePeriod == 0) revert(\"stale period can't be zero\");\n if (bytes(symbol).length == 0) revert(\"symbol cannot be empty\");\n\n maxStalePeriod[symbol] = _maxStalePeriod;\n emit MaxStalePeriodAdded(symbol, _maxStalePeriod);\n }\n\n /**\n * @notice Used to override a symbol when fetching price\n * @param symbol The symbol to override\n * @param overrideSymbol The symbol after override\n */\n function setSymbolOverride(string calldata symbol, string calldata overrideSymbol) external {\n _checkAccessAllowed(\"setSymbolOverride(string,string)\");\n if (bytes(symbol).length == 0) revert(\"symbol cannot be empty\");\n\n symbols[symbol] = overrideSymbol;\n emit SymbolOverridden(symbol, overrideSymbol);\n }\n\n /**\n * @notice Used to set feed registry address when current chain does not support space ID.\n * @param newfeedRegistryAddress Address of new feed registry.\n */\n function setFeedRegistryAddress(\n address newfeedRegistryAddress\n ) external notNullAddress(newfeedRegistryAddress) onlyOwner {\n if (sidRegistryAddress != address(0)) revert(\"sidRegistryAddress must be zero\");\n emit FeedRegistryUpdated(feedRegistryAddress, newfeedRegistryAddress);\n feedRegistryAddress = newfeedRegistryAddress;\n }\n\n /**\n * @notice Uses Space ID to fetch the feed registry address\n * @return feedRegistryAddress Address of binance oracle feed registry.\n */\n function getFeedRegistryAddress() public view returns (address) {\n bytes32 nodeHash = 0x94fe3821e0768eb35012484db4df61890f9a6ca5bfa984ef8ff717e73139faff;\n\n SIDRegistryInterface sidRegistry = SIDRegistryInterface(sidRegistryAddress);\n address publicResolverAddress = sidRegistry.resolver(nodeHash);\n PublicResolverInterface publicResolver = PublicResolverInterface(publicResolverAddress);\n\n return publicResolver.addr(nodeHash);\n }\n\n /**\n * @notice Gets the price of a asset from the binance oracle\n * @param asset Address of the asset\n * @return Price in USD\n */\n function getPrice(address asset) public view returns (uint256) {\n string memory symbol;\n uint256 decimals;\n\n if (asset == BNB_ADDR) {\n symbol = \"BNB\";\n decimals = 18;\n } else {\n IERC20Metadata token = IERC20Metadata(asset);\n symbol = token.symbol();\n decimals = token.decimals();\n }\n\n string memory overrideSymbol = symbols[symbol];\n\n if (bytes(overrideSymbol).length != 0) {\n symbol = overrideSymbol;\n }\n\n return _getPrice(symbol, decimals);\n }\n\n function _getPrice(string memory symbol, uint256 decimals) internal view returns (uint256) {\n FeedRegistryInterface feedRegistry;\n\n if (sidRegistryAddress != address(0)) {\n // If sidRegistryAddress is available, fetch feedRegistryAddress from sidRegistry\n feedRegistry = FeedRegistryInterface(getFeedRegistryAddress());\n } else {\n // Use feedRegistry directly if sidRegistryAddress is not available\n feedRegistry = FeedRegistryInterface(feedRegistryAddress);\n }\n\n (, int256 answer, , uint256 updatedAt, ) = feedRegistry.latestRoundDataByName(symbol, \"USD\");\n if (answer <= 0) revert(\"invalid binance oracle price\");\n if (block.timestamp < updatedAt) revert(\"updatedAt exceeds block time\");\n\n uint256 deltaTime;\n unchecked {\n deltaTime = block.timestamp - updatedAt;\n }\n if (deltaTime > maxStalePeriod[symbol]) revert(\"binance oracle price expired\");\n\n uint256 decimalDelta = feedRegistry.decimalsByName(symbol, \"USD\");\n return (uint256(answer) * (10 ** (18 - decimalDelta))) * (10 ** (18 - decimals));\n }\n}\n" + }, + "@venusprotocol/oracle/contracts/oracles/ChainlinkOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport \"../interfaces/VBep20Interface.sol\";\nimport \"../interfaces/OracleInterface.sol\";\nimport \"@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\nimport \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\n\n/**\n * @title ChainlinkOracle\n * @author Venus\n * @notice This oracle fetches prices of assets from the Chainlink oracle.\n */\ncontract ChainlinkOracle is AccessControlledV8, OracleInterface {\n struct TokenConfig {\n /// @notice Underlying token address, which can't be a null address\n /// @notice Used to check if a token is supported\n /// @notice 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB address for native tokens\n /// (e.g BNB for BNB chain, ETH for Ethereum network)\n address asset;\n /// @notice Chainlink feed address\n address feed;\n /// @notice Price expiration period of this asset\n uint256 maxStalePeriod;\n }\n\n /// @notice Set this as asset address for native token on each chain.\n /// This is the underlying address for vBNB on BNB chain or an underlying asset for a native market on any chain.\n address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\n\n /// @notice Manually set an override price, useful under extenuating conditions such as price feed failure\n mapping(address => uint256) public prices;\n\n /// @notice Token config by assets\n mapping(address => TokenConfig) public tokenConfigs;\n\n /// @notice Emit when a price is manually set\n event PricePosted(address indexed asset, uint256 previousPriceMantissa, uint256 newPriceMantissa);\n\n /// @notice Emit when a token config is added\n event TokenConfigAdded(address indexed asset, address feed, uint256 maxStalePeriod);\n\n modifier notNullAddress(address someone) {\n if (someone == address(0)) revert(\"can't be zero address\");\n _;\n }\n\n /// @notice Constructor for the implementation contract.\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the owner of the contract\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 /**\n * @notice Manually set the price of a given asset\n * @param asset Asset address\n * @param price Asset price in 18 decimals\n * @custom:access Only Governance\n * @custom:event Emits PricePosted event on successfully setup of asset price\n */\n function setDirectPrice(address asset, uint256 price) external notNullAddress(asset) {\n _checkAccessAllowed(\"setDirectPrice(address,uint256)\");\n\n uint256 previousPriceMantissa = prices[asset];\n prices[asset] = price;\n emit PricePosted(asset, previousPriceMantissa, price);\n }\n\n /**\n * @notice Add multiple token configs at the same time\n * @param tokenConfigs_ config array\n * @custom:access Only Governance\n * @custom:error Zero length error thrown, if length of the array in parameter is 0\n */\n function setTokenConfigs(TokenConfig[] memory tokenConfigs_) external {\n if (tokenConfigs_.length == 0) revert(\"length can't be 0\");\n uint256 numTokenConfigs = tokenConfigs_.length;\n for (uint256 i; i < numTokenConfigs; ++i) {\n setTokenConfig(tokenConfigs_[i]);\n }\n }\n\n /**\n * @notice Add single token config. asset & feed cannot be null addresses and maxStalePeriod must be positive\n * @param tokenConfig Token config struct\n * @custom:access Only Governance\n * @custom:error NotNullAddress error is thrown if asset address is null\n * @custom:error NotNullAddress error is thrown if token feed address is null\n * @custom:error Range error is thrown if maxStale period of token is not greater than zero\n * @custom:event Emits TokenConfigAdded event on successfully setting of the token config\n */\n function setTokenConfig(\n TokenConfig memory tokenConfig\n ) public notNullAddress(tokenConfig.asset) notNullAddress(tokenConfig.feed) {\n _checkAccessAllowed(\"setTokenConfig(TokenConfig)\");\n\n if (tokenConfig.maxStalePeriod == 0) revert(\"stale period can't be zero\");\n tokenConfigs[tokenConfig.asset] = tokenConfig;\n emit TokenConfigAdded(tokenConfig.asset, tokenConfig.feed, tokenConfig.maxStalePeriod);\n }\n\n /**\n * @notice Gets the price of a asset from the chainlink oracle\n * @param asset Address of the asset\n * @return Price in USD from Chainlink or a manually set price for the asset\n */\n function getPrice(address asset) public view virtual returns (uint256) {\n uint256 decimals;\n\n if (asset == NATIVE_TOKEN_ADDR) {\n decimals = 18;\n } else {\n IERC20Metadata token = IERC20Metadata(asset);\n decimals = token.decimals();\n }\n\n return _getPriceInternal(asset, decimals);\n }\n\n /**\n * @notice Gets the Chainlink price for a given asset\n * @param asset address of the asset\n * @param decimals decimals of the asset\n * @return price Asset price in USD or a manually set price of the asset\n */\n function _getPriceInternal(address asset, uint256 decimals) internal view returns (uint256 price) {\n uint256 tokenPrice = prices[asset];\n if (tokenPrice != 0) {\n price = tokenPrice;\n } else {\n price = _getChainlinkPrice(asset);\n }\n\n uint256 decimalDelta = 18 - decimals;\n return price * (10 ** decimalDelta);\n }\n\n /**\n * @notice Get the Chainlink price for an asset, revert if token config doesn't exist\n * @dev The precision of the price feed is used to ensure the returned price has 18 decimals of precision\n * @param asset Address of the asset\n * @return price Price in USD, with 18 decimals of precision\n * @custom:error NotNullAddress error is thrown if the asset address is null\n * @custom:error Price error is thrown if the Chainlink price of asset is not greater than zero\n * @custom:error Timing error is thrown if current timestamp is less than the last updatedAt timestamp\n * @custom:error Timing error is thrown if time difference between current time and last updated time\n * is greater than maxStalePeriod\n */\n function _getChainlinkPrice(\n address asset\n ) private view notNullAddress(tokenConfigs[asset].asset) returns (uint256) {\n TokenConfig memory tokenConfig = tokenConfigs[asset];\n AggregatorV3Interface feed = AggregatorV3Interface(tokenConfig.feed);\n\n // note: maxStalePeriod cannot be 0\n uint256 maxStalePeriod = tokenConfig.maxStalePeriod;\n\n // Chainlink USD-denominated feeds store answers at 8 decimals, mostly\n uint256 decimalDelta = 18 - feed.decimals();\n\n (, int256 answer, , uint256 updatedAt, ) = feed.latestRoundData();\n if (answer <= 0) revert(\"chainlink price must be positive\");\n if (block.timestamp < updatedAt) revert(\"updatedAt exceeds block time\");\n\n uint256 deltaTime;\n unchecked {\n deltaTime = block.timestamp - updatedAt;\n }\n\n if (deltaTime > maxStalePeriod) revert(\"chainlink price expired\");\n\n return uint256(answer) * (10 ** decimalDelta);\n }\n}\n" + }, + "@venusprotocol/protocol-reserve/contracts/Interfaces/IComptroller.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\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" + }, + "@venusprotocol/protocol-reserve/contracts/Interfaces/IIncomeDestination.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\ninterface IIncomeDestination {\n function updateAssetsState(address comptroller, address asset) external;\n}\n" + }, + "@venusprotocol/protocol-reserve/contracts/Interfaces/IPoolRegistry.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\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" + }, + "@venusprotocol/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\ninterface IProtocolShareReserve {\n /// @notice it represents the type of vToken income\n enum IncomeType {\n SPREAD,\n LIQUIDATION,\n ERC4626_WRAPPER_REWARDS,\n FLASHLOAN\n }\n\n function updateAssetsState(\n address comptroller,\n address asset,\n IncomeType incomeType\n ) external;\n}\n" + }, + "@venusprotocol/protocol-reserve/contracts/Interfaces/IVToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\ninterface IVToken {\n function underlying() external view returns (address);\n}\n" + }, + "@venusprotocol/protocol-reserve/contracts/ProtocolReserve/ProtocolShareReserve.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\";\nimport { MaxLoopsLimitHelper } from \"@venusprotocol/solidity-utilities/contracts/MaxLoopsLimitHelper.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\nimport { IProtocolShareReserve } from \"../Interfaces/IProtocolShareReserve.sol\";\nimport { IComptroller } from \"../Interfaces/IComptroller.sol\";\nimport { IPoolRegistry } from \"../Interfaces/IPoolRegistry.sol\";\nimport { IVToken } from \"../Interfaces/IVToken.sol\";\nimport { IIncomeDestination } from \"../Interfaces/IIncomeDestination.sol\";\n\nerror InvalidAddress();\nerror UnsupportedAsset();\nerror InvalidTotalPercentage();\nerror InvalidMaxLoopsLimit();\n\ncontract ProtocolShareReserve is\n AccessControlledV8,\n ReentrancyGuardUpgradeable,\n MaxLoopsLimitHelper,\n IProtocolShareReserve\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice protocol income is categorized into two schemas.\n /// The first schema is for spread income\n /// The second schema is for liquidation income\n enum Schema {\n PROTOCOL_RESERVES,\n ADDITIONAL_REVENUE\n }\n\n struct DistributionConfig {\n Schema schema;\n /// @dev percenatge is represented without any scale\n uint16 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 pool registry contract\n address public poolRegistry;\n\n uint16 public constant MAX_PERCENT = 1e4;\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 Event emitted after updating 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 uint16 oldPercentage,\n uint16 newPercentage,\n Schema schema\n );\n\n /// @notice Event emitted when distribution configuration is added\n event DistributionConfigAdded(address indexed destination, uint16 percentage, Schema schema);\n\n /// @notice Event emitted when distribution configuration is removed\n event DistributionConfigRemoved(address indexed destination, uint16 percentage, Schema schema);\n\n /**\n * @dev Constructor to initialize the immutable variables\n * @param _corePoolComptroller The address of core pool comptroller\n * @param _wbnb The address of WBNB\n * @param _vbnb The address of vBNB\n */\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _corePoolComptroller,\n address _wbnb,\n address _vbnb\n ) {\n ensureNonzeroAddress(_corePoolComptroller);\n ensureNonzeroAddress(_wbnb);\n ensureNonzeroAddress(_vbnb);\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 ensureNonzeroAddress(_poolRegistry);\n emit PoolRegistryUpdated(poolRegistry, _poolRegistry);\n poolRegistry = _poolRegistry;\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[] calldata configs) external nonReentrant {\n _checkAccessAllowed(\"addOrUpdateDistributionConfigs(DistributionConfig[])\");\n\n for (uint256 i = 0; i < configs.length; ) {\n DistributionConfig memory _config = configs[i];\n ensureNonzeroAddress(_config.destination);\n\n bool updated = false;\n uint256 distributionTargetsLength = distributionTargets.length;\n for (uint256 j = 0; j < distributionTargetsLength; ) {\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 Remove destionation target if percentage is 0\n * @param schema schema of the configuration\n * @param destination destination address of the configuration\n */\n function removeDistributionConfig(Schema schema, address destination) external {\n _checkAccessAllowed(\"removeDistributionConfig(Schema,address)\");\n\n uint256 distributionIndex;\n bool found = false;\n for (uint256 i = 0; i < distributionTargets.length; ) {\n DistributionConfig storage config = distributionTargets[i];\n\n if (schema == config.schema && destination == config.destination && config.percentage == 0) {\n found = true;\n distributionIndex = i;\n break;\n }\n\n unchecked {\n ++i;\n }\n }\n\n if (found) {\n emit DistributionConfigRemoved(\n distributionTargets[distributionIndex].destination,\n distributionTargets[distributionIndex].percentage,\n distributionTargets[distributionIndex].schema\n );\n\n distributionTargets[distributionIndex] = distributionTargets[distributionTargets.length - 1];\n distributionTargets.pop();\n }\n\n _ensurePercentages();\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[] calldata assets) external nonReentrant {\n for (uint256 i = 0; 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 uint256 distributionTargetsLength = distributionTargets.length;\n for (uint256 i = 0; i < distributionTargetsLength; ) {\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 Used to find out the percentage distribution for a particular destination based on schema\n * @param destination the destination address of the distribution target\n * @param schema the schema of the distribution target\n * @return percentage percentage distribution\n */\n function getPercentageDistribution(address destination, Schema schema) external view returns (uint256) {\n uint256 distributionTargetsLength = distributionTargets.length;\n for (uint256 i = 0; i < distributionTargetsLength; ) {\n DistributionConfig memory config = distributionTargets[i];\n\n if (config.destination == destination && config.schema == schema) {\n return config.percentage;\n }\n\n unchecked {\n ++i;\n }\n }\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(IProtocolShareReserve) nonReentrant {\n if (!IComptroller(comptroller).isComptroller()) revert InvalidAddress();\n ensureNonzeroAddress(asset);\n\n if (\n comptroller != CORE_POOL_COMPTROLLER &&\n IPoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) == address(0)\n ) revert InvalidAddress();\n\n Schema schema = _getSchema(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 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 = 0; 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 if (transferAmount != 0) {\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\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 income type\n * @param incomeType type of income\n * @return schema schema for distribution\n */\n function _getSchema(IncomeType incomeType) internal view returns (Schema schema) {\n schema = Schema.ADDITIONAL_REVENUE;\n\n if (incomeType == IncomeType.SPREAD) {\n schema = Schema.PROTOCOL_RESERVES;\n }\n }\n\n /**\n * @dev This ensures that the total percentage of all the distribution targets is 100% or 0%\n */\n function _ensurePercentages() internal view {\n uint256 totalSchemas = uint256(type(Schema).max) + 1;\n uint16[] memory totalPercentages = new uint16[](totalSchemas);\n\n uint256 distributionTargetsLength = distributionTargets.length;\n for (uint256 i = 0; i < distributionTargetsLength; ) {\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" + }, + "@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" + }, + "@venusprotocol/venus-protocol/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" + }, + "@venusprotocol/venus-protocol/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/Comptroller.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { IPrime } from \"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\";\n\nimport { ComptrollerInterface, Action } from \"./ComptrollerInterface.sol\";\nimport { ComptrollerStorage } from \"./ComptrollerStorage.sol\";\nimport { ExponentialNoError } from \"./ExponentialNoError.sol\";\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.sol\";\nimport { MaxLoopsLimitHelper } from \"./MaxLoopsLimitHelper.sol\";\nimport { ensureNonzeroAddress } from \"./lib/validators.sol\";\n\n/**\n * @title Comptroller\n * @author Venus\n * @notice The Comptroller is designed to provide checks for all minting, redeeming, transferring, borrowing, lending, repaying, liquidating,\n * and seizing done by the `vToken` contract. Each pool has one `Comptroller` checking these interactions across markets. When a user interacts\n * with a given market by one of these main actions, a call is made to a corresponding hook in the associated `Comptroller`, which either allows\n * or reverts the transaction. These hooks also update supply and borrow rewards as they are called. The comptroller holds the logic for assessing\n * liquidity snapshots of an account via the collateral factor and liquidation threshold. This check determines the collateral needed for a borrow,\n * as well as how much of a borrow may be liquidated. A user may borrow a portion of their collateral with the maximum amount determined by the\n * markets collateral factor. However, if their borrowed amount exceeds an amount calculated using the market’s corresponding liquidation threshold,\n * the borrow is eligible for liquidation.\n *\n * The `Comptroller` also includes two functions `liquidateAccount()` and `healAccount()`, which are meant to handle accounts that do not exceed\n * the `minLiquidatableCollateral` for the `Comptroller`:\n *\n * - `healAccount()`: This function is called to seize all of a given user’s collateral, requiring the `msg.sender` repay a certain percentage\n * of the debt calculated by `collateral/(borrows*liquidationIncentive)`. The function can only be called if the calculated percentage does not exceed\n * 100%, because otherwise no `badDebt` would be created and `liquidateAccount()` should be used instead. The difference in the actual amount of debt\n * and debt paid off is recorded as `badDebt` for each market, which can then be auctioned off for the risk reserves of the associated pool.\n * - `liquidateAccount()`: This function can only be called if the collateral seized will cover all borrows of an account, as well as the liquidation\n * incentive. Otherwise, the pool will incur bad debt, in which case the function `healAccount()` should be used instead. This function skips the logic\n * verifying that the repay amount does not exceed the close factor.\n */\ncontract Comptroller is\n Ownable2StepUpgradeable,\n AccessControlledV8,\n ComptrollerStorage,\n ComptrollerInterface,\n ExponentialNoError,\n MaxLoopsLimitHelper\n{\n // PoolRegistry, immutable to save on gas\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable poolRegistry;\n\n /// @notice Emitted when an account enters a market\n event MarketEntered(VToken indexed vToken, address indexed account);\n\n /// @notice Emitted when an account exits a market\n event MarketExited(VToken indexed vToken, address indexed account);\n\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(VToken vToken, uint256 oldCollateralFactorMantissa, uint256 newCollateralFactorMantissa);\n\n /// @notice Emitted when liquidation threshold is changed by admin\n event NewLiquidationThreshold(\n VToken vToken,\n uint256 oldLiquidationThresholdMantissa,\n uint256 newLiquidationThresholdMantissa\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 an action is paused on a market\n event ActionPausedMarket(VToken vToken, Action action, bool pauseState);\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 the collateral threshold (in USD) for non-batch liquidations is changed\n event NewMinLiquidatableCollateral(uint256 oldMinLiquidatableCollateral, uint256 newMinLiquidatableCollateral);\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 a rewards distributor is added\n event NewRewardsDistributor(address indexed rewardsDistributor, address indexed rewardToken);\n\n /// @notice Emitted when a market is supported\n event MarketSupported(VToken vToken);\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 a market\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\n\n /// @notice Emitted when a market is unlisted\n event MarketUnlisted(address indexed vToken);\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 Thrown when collateral factor exceeds the upper bound\n error InvalidCollateralFactor();\n\n /// @notice Thrown when liquidation threshold exceeds the collateral factor\n error InvalidLiquidationThreshold();\n\n /// @notice Thrown when the action is only available to specific sender, but the real sender was different\n error UnexpectedSender(address expectedSender, address actualSender);\n\n /// @notice Thrown when the oracle returns an invalid price for some asset\n error PriceError(address vToken);\n\n /// @notice Thrown if VToken unexpectedly returned a nonzero error code while trying to get account snapshot\n error SnapshotError(address vToken, address user);\n\n /// @notice Thrown when the market is not listed\n error MarketNotListed(address market);\n\n /// @notice Thrown when a market has an unexpected comptroller\n error ComptrollerMismatch();\n\n /// @notice Thrown when user is not member of market\n error MarketNotCollateral(address vToken, address user);\n\n /// @notice Thrown when borrow action is not paused\n error BorrowActionNotPaused();\n\n /// @notice Thrown when mint action is not paused\n error MintActionNotPaused();\n\n /// @notice Thrown when redeem action is not paused\n error RedeemActionNotPaused();\n\n /// @notice Thrown when repay action is not paused\n error RepayActionNotPaused();\n\n /// @notice Thrown when seize action is not paused\n error SeizeActionNotPaused();\n\n /// @notice Thrown when exit market action is not paused\n error ExitMarketActionNotPaused();\n\n /// @notice Thrown when transfer action is not paused\n error TransferActionNotPaused();\n\n /// @notice Thrown when enter market action is not paused\n error EnterMarketActionNotPaused();\n\n /// @notice Thrown when liquidate action is not paused\n error LiquidateActionNotPaused();\n\n /// @notice Thrown when borrow cap is not zero\n error BorrowCapIsNotZero();\n\n /// @notice Thrown when supply cap is not zero\n error SupplyCapIsNotZero();\n\n /// @notice Thrown when collateral factor is not zero\n error CollateralFactorIsNotZero();\n\n /**\n * @notice Thrown during the liquidation if user's total collateral amount is lower than\n * a predefined threshold. In this case only batch liquidations (either liquidateAccount\n * or healAccount) are available.\n */\n error MinimalCollateralViolated(uint256 expectedGreaterThan, uint256 actual);\n error CollateralExceedsThreshold(uint256 expectedLessThanOrEqualTo, uint256 actual);\n error InsufficientCollateral(uint256 collateralToSeize, uint256 availableCollateral);\n\n /// @notice Thrown when the account doesn't have enough liquidity to redeem or borrow\n error InsufficientLiquidity();\n\n /// @notice Thrown when trying to liquidate a healthy account\n error InsufficientShortfall();\n\n /// @notice Thrown when trying to repay more than allowed by close factor\n error TooMuchRepay();\n\n /// @notice Thrown if the user is trying to exit a market in which they have an outstanding debt\n error NonzeroBorrowBalance();\n\n /// @notice Thrown when trying to perform an action that is paused\n error ActionPaused(address market, Action action);\n\n /// @notice Thrown when trying to add a market that is already listed\n error MarketAlreadyListed(address market);\n\n /// @notice Thrown if the supply cap is exceeded\n error SupplyCapExceeded(address market, uint256 cap);\n\n /// @notice Thrown if the borrow cap is exceeded\n error BorrowCapExceeded(address market, uint256 cap);\n\n /// @notice Thrown if delegate approval status is already set to the requested value\n error DelegationStatusUnchanged();\n\n /// @param poolRegistry_ Pool registry address\n /// @custom:oz-upgrades-unsafe-allow constructor\n /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n constructor(address poolRegistry_) {\n ensureNonzeroAddress(poolRegistry_);\n\n poolRegistry = poolRegistry_;\n _disableInitializers();\n }\n\n /**\n * @param loopLimit Limit for the loops can iterate to avoid the DOS\n * @param accessControlManager Access control manager contract address\n */\n function initialize(uint256 loopLimit, address accessControlManager) external initializer {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager);\n\n _setMaxLoopsLimit(loopLimit);\n }\n\n /**\n * @notice Add assets to be included in account liquidity calculation; enabling them to be used as collateral\n * @param vTokens The list of addresses of the vToken markets to be enabled\n * @return errors An array of NO_ERROR for compatibility with Venus core tooling\n * @custom:event MarketEntered is emitted for each market on success\n * @custom:error ActionPaused error is thrown if entering any of the markets is paused\n * @custom:error MarketNotListed error is thrown if any of the markets is not listed\n * @custom:access Not restricted\n */\n function enterMarkets(address[] memory vTokens) external override returns (uint256[] memory) {\n uint256 len = vTokens.length;\n\n uint256[] memory results = new uint256[](len);\n for (uint256 i; i < len; ++i) {\n VToken vToken = VToken(vTokens[i]);\n\n _addToMarket(vToken, msg.sender);\n results[i] = NO_ERROR;\n }\n\n return results;\n }\n\n /**\n * @notice Unlist a market by setting isListed to false\n * @dev Checks if all actions are paused, borrow/supply caps is set to 0 and collateral factor is to 0.\n * @param market The address of the market (token) to unlist\n * @return uint256 Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event MarketUnlisted is emitted on success\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error BorrowActionNotPaused error is thrown if borrow action is not paused\n * @custom:error MintActionNotPaused error is thrown if mint action is not paused\n * @custom:error RedeemActionNotPaused error is thrown if redeem action is not paused\n * @custom:error RepayActionNotPaused error is thrown if repay action is not paused\n * @custom:error EnterMarketActionNotPaused error is thrown if enter market action is not paused\n * @custom:error LiquidateActionNotPaused error is thrown if liquidate action is not paused\n * @custom:error BorrowCapIsNotZero error is thrown if borrow cap is not zero\n * @custom:error SupplyCapIsNotZero error is thrown if supply cap is not zero\n * @custom:error CollateralFactorIsNotZero error is thrown if collateral factor is not zero\n */\n function unlistMarket(address market) external returns (uint256) {\n _checkAccessAllowed(\"unlistMarket(address)\");\n\n Market storage _market = markets[market];\n\n if (!_market.isListed) {\n revert MarketNotListed(market);\n }\n\n if (!actionPaused(market, Action.BORROW)) {\n revert BorrowActionNotPaused();\n }\n\n if (!actionPaused(market, Action.MINT)) {\n revert MintActionNotPaused();\n }\n\n if (!actionPaused(market, Action.REDEEM)) {\n revert RedeemActionNotPaused();\n }\n\n if (!actionPaused(market, Action.REPAY)) {\n revert RepayActionNotPaused();\n }\n\n if (!actionPaused(market, Action.SEIZE)) {\n revert SeizeActionNotPaused();\n }\n\n if (!actionPaused(market, Action.ENTER_MARKET)) {\n revert EnterMarketActionNotPaused();\n }\n\n if (!actionPaused(market, Action.LIQUIDATE)) {\n revert LiquidateActionNotPaused();\n }\n\n if (!actionPaused(market, Action.TRANSFER)) {\n revert TransferActionNotPaused();\n }\n\n if (!actionPaused(market, Action.EXIT_MARKET)) {\n revert ExitMarketActionNotPaused();\n }\n\n if (borrowCaps[market] != 0) {\n revert BorrowCapIsNotZero();\n }\n\n if (supplyCaps[market] != 0) {\n revert SupplyCapIsNotZero();\n }\n\n if (_market.collateralFactorMantissa != 0) {\n revert CollateralFactorIsNotZero();\n }\n\n _market.isListed = false;\n emit MarketUnlisted(market);\n\n return NO_ERROR;\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 * @custom:event DelegateUpdated emits on success\n * @custom:error ZeroAddressNotAllowed is thrown when delegate address is zero\n * @custom:error DelegationStatusUnchanged is thrown if approval status is already set to the requested value\n * @custom:access Not restricted\n */\n function updateDelegate(address delegate, bool approved) external {\n ensureNonzeroAddress(delegate);\n if (approvedDelegates[msg.sender][delegate] == approved) {\n revert DelegationStatusUnchanged();\n }\n\n approvedDelegates[msg.sender][delegate] = approved;\n emit DelegateUpdated(msg.sender, delegate, approved);\n }\n\n /**\n * @notice Removes asset from sender's account liquidity calculation; disabling them as collateral\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event MarketExited is emitted on success\n * @custom:error ActionPaused error is thrown if exiting the market is paused\n * @custom:error NonzeroBorrowBalance error is thrown if the user has an outstanding borrow in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if exiting the market would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function exitMarket(address vTokenAddress) external override returns (uint256) {\n _checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\n VToken vToken = VToken(vTokenAddress);\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\n (uint256 tokensHeld, uint256 amountOwed, ) = _safeGetAccountSnapshot(vToken, msg.sender);\n\n /* Fail if the sender has a borrow balance */\n if (amountOwed != 0) {\n revert NonzeroBorrowBalance();\n }\n\n /* Fail if the sender is not permitted to redeem all of their tokens */\n _checkRedeemAllowed(vTokenAddress, msg.sender, tokensHeld);\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 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 // load into memory for faster iteration\n VToken[] memory userAssetList = accountAssets[msg.sender];\n uint256 len = userAssetList.length;\n\n uint256 assetIndex = len;\n for (uint256 i; i < len; ++i) {\n if (userAssetList[i] == vToken) {\n assetIndex = i;\n break;\n }\n }\n\n // We *must* have found the asset in the list or our redundant data structure is broken\n assert(assetIndex < len);\n\n // copy last item in list to location of item to be removed, reduce length by 1\n VToken[] storage storedList = accountAssets[msg.sender];\n storedList[assetIndex] = storedList[storedList.length - 1];\n storedList.pop();\n\n emit MarketExited(vToken, msg.sender);\n\n return NO_ERROR;\n }\n\n /*** Policy Hooks ***/\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 * @custom:error ActionPaused error is thrown if supplying to this market is paused\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error SupplyCapExceeded error is thrown if the total supply exceeds the cap after minting\n * @custom:access Not restricted\n */\n function preMintHook(address vToken, address minter, uint256 mintAmount) external override {\n _checkActionPauseState(vToken, Action.MINT);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n uint256 supplyCap = supplyCaps[vToken];\n // Skipping the cap check for uncapped coins to save some gas\n if (supplyCap != type(uint256).max) {\n uint256 vTokenSupply = VToken(vToken).totalSupply();\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\n if (nextTotalSupply > supplyCap) {\n revert SupplyCapExceeded(vToken, supplyCap);\n }\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, minter);\n }\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external override {\n _checkActionPauseState(vToken, Action.REDEEM);\n\n _checkRedeemAllowed(vToken, redeemer, redeemTokens);\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, redeemer);\n }\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 if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(redeemer, vToken);\n }\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 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 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 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 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 * @custom:error ActionPaused error is thrown if borrowing is paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if there is not enough collateral to borrow\n * @custom:error BorrowCapExceeded is thrown if the borrow cap will be exceeded should this borrow succeed\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted if vToken is enabled as collateral, otherwise only vToken\n */\n /// disable-eslint\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external override {\n _checkActionPauseState(vToken, Action.BORROW);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n if (!markets[vToken].accountMembership[borrower]) {\n // only vTokens may call borrowAllowed if borrower not in market\n _checkSenderIs(vToken);\n\n // attempt to add borrower to the market or revert\n _addToMarket(VToken(msg.sender), borrower);\n }\n\n // Update the prices of tokens\n updatePrices(borrower);\n\n if (oracle.getUnderlyingPrice(vToken) == 0) {\n revert PriceError(address(vToken));\n }\n\n uint256 borrowCap = borrowCaps[vToken];\n // Skipping the cap check for uncapped coins to save some gas\n if (borrowCap != type(uint256).max) {\n uint256 totalBorrows = VToken(vToken).totalBorrows();\n uint256 badDebt = VToken(vToken).badDebt();\n uint256 nextTotalBorrows = totalBorrows + borrowAmount + badDebt;\n if (nextTotalBorrows > borrowCap) {\n revert BorrowCapExceeded(vToken, borrowCap);\n }\n }\n\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n borrower,\n VToken(vToken),\n 0,\n borrowAmount,\n _getCollateralFactor\n );\n\n if (snapshot.shortfall > 0) {\n revert InsufficientLiquidity();\n }\n\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\n }\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 borrower The account which would borrowed the asset\n * @custom:error ActionPaused error is thrown if repayments are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:access Not restricted\n */\n function preRepayHook(address vToken, address borrower) external override {\n _checkActionPauseState(vToken, Action.REPAY);\n\n oracle.updatePrice(vToken);\n\n if (!markets[vToken].isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenBorrowIndex(vToken, borrowIndex);\n rewardsDistributor.distributeBorrowerRewardToken(vToken, borrower, borrowIndex);\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 borrower The address of the borrower\n * @param repayAmount The amount of underlying being repaid\n * @param skipLiquidityCheck Allows the borrow to be liquidated regardless of the account liquidity\n * @custom:error ActionPaused error is thrown if liquidations are paused in this market\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\n * @custom:error TooMuchRepay error is thrown if the liquidator is trying to repay more than allowed by close factor\n * @custom:error MinimalCollateralViolated is thrown if the users' total collateral is lower than the threshold for non-batch liquidations\n * @custom:error InsufficientShortfall is thrown when trying to liquidate a healthy account\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n */\n function preLiquidateHook(\n address vTokenBorrowed,\n address vTokenCollateral,\n address borrower,\n uint256 repayAmount,\n bool skipLiquidityCheck\n ) external override {\n // Pause Action.LIQUIDATE on BORROWED TOKEN to prevent liquidating it.\n // If we want to pause liquidating to vTokenCollateral, we should pause\n // Action.SEIZE on it\n _checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\n\n // Update the prices of tokens\n updatePrices(borrower);\n\n if (!markets[vTokenBorrowed].isListed) {\n revert MarketNotListed(address(vTokenBorrowed));\n }\n if (!markets[vTokenCollateral].isListed) {\n revert MarketNotListed(address(vTokenCollateral));\n }\n\n uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\n\n /* Allow accounts to be liquidated if it is a forced liquidation */\n if (skipLiquidityCheck || isForcedLiquidationEnabled[vTokenBorrowed]) {\n if (repayAmount > borrowBalance) {\n revert TooMuchRepay();\n }\n return;\n }\n\n /* The borrower must have shortfall and collateral > threshold in order to be liquidatable */\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral <= minLiquidatableCollateral) {\n /* The liquidator should use either liquidateAccount or healAccount */\n revert MinimalCollateralViolated(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n /* The liquidator may not repay more than what is allowed by the closeFactor */\n uint256 maxClose = mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance);\n if (repayAmount > maxClose) {\n revert TooMuchRepay();\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 seizerContract Contract that tries to seize the asset (either borrowed vToken or Comptroller)\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @custom:error ActionPaused error is thrown if seizing this type of collateral is paused\n * @custom:error MarketNotListed error is thrown if either collateral or borrowed token is not listed\n * @custom:error ComptrollerMismatch error is when seizer contract or seized asset belong to different pools\n * @custom:access Not restricted\n */\n function preSeizeHook(\n address vTokenCollateral,\n address seizerContract,\n address liquidator,\n address borrower\n ) external override {\n // Pause Action.SEIZE on COLLATERAL to prevent seizing it.\n // If we want to pause liquidating vTokenBorrowed, we should pause\n // Action.LIQUIDATE on it\n _checkActionPauseState(vTokenCollateral, Action.SEIZE);\n\n Market storage market = markets[vTokenCollateral];\n\n if (!market.isListed) {\n revert MarketNotListed(vTokenCollateral);\n }\n\n if (seizerContract == address(this)) {\n // If Comptroller is the seizer, just check if collateral's comptroller\n // is equal to the current address\n if (address(VToken(vTokenCollateral).comptroller()) != address(this)) {\n revert ComptrollerMismatch();\n }\n } else {\n // If the seizer is not the Comptroller, check that the seizer is a\n // listed market, and that the markets' comptrollers match\n if (!markets[seizerContract].isListed) {\n revert MarketNotListed(seizerContract);\n }\n if (VToken(vTokenCollateral).comptroller() != VToken(seizerContract).comptroller()) {\n revert ComptrollerMismatch();\n }\n }\n\n if (!market.accountMembership[borrower]) {\n revert MarketNotCollateral(vTokenCollateral, borrower);\n }\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vTokenCollateral);\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, borrower);\n rewardsDistributor.distributeSupplierRewardToken(vTokenCollateral, liquidator);\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 * @custom:error ActionPaused error is thrown if withdrawals are paused in this market\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InsufficientLiquidity error is thrown if the withdrawal would lead to user's insolvency\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external override {\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 _checkRedeemAllowed(vToken, src, transferTokens);\n\n // Keep the flywheel moving\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n rewardsDistributor.updateRewardTokenSupplyIndex(vToken);\n rewardsDistributor.distributeSupplierRewardToken(vToken, src);\n rewardsDistributor.distributeSupplierRewardToken(vToken, dst);\n }\n }\n\n /*** Pool-level operations ***/\n\n /**\n * @notice Seizes all the remaining collateral, makes msg.sender repay the existing\n * borrows, and treats the rest of the debt as bad debt (for each market).\n * The sender has to repay a certain percentage of the debt, computed as\n * collateral / (borrows * liquidationIncentive).\n * @param user account to heal\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for healing\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function healAccount(address user) external {\n VToken[] memory userAssets = getAssetsIn(user);\n uint256 userAssetsCount = userAssets.length;\n\n address liquidator = msg.sender;\n {\n ResilientOracleInterface oracle_ = oracle;\n // We need all user's markets to be fresh for the computations to be correct\n for (uint256 i; i < userAssetsCount; ++i) {\n userAssets[i].accrueInterest();\n oracle_.updatePrice(address(userAssets[i]));\n }\n }\n\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(user, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n // percentage = collateral / (borrows * liquidation incentive)\n Exp memory collateral = Exp({ mantissa: snapshot.totalCollateral });\n Exp memory scaledBorrows = mul_(\n Exp({ mantissa: snapshot.borrows }),\n Exp({ mantissa: liquidationIncentiveMantissa })\n );\n\n Exp memory percentage = div_(collateral, scaledBorrows);\n if (lessThanExp(Exp({ mantissa: MANTISSA_ONE }), percentage)) {\n revert CollateralExceedsThreshold(scaledBorrows.mantissa, collateral.mantissa);\n }\n\n for (uint256 i; i < userAssetsCount; ++i) {\n VToken market = userAssets[i];\n\n (uint256 tokens, uint256 borrowBalance, ) = _safeGetAccountSnapshot(market, user);\n uint256 repaymentAmount = mul_ScalarTruncate(percentage, borrowBalance);\n\n // Seize the entire collateral\n if (tokens != 0) {\n market.seize(liquidator, user, tokens);\n }\n // Repay a certain percentage of the borrow, forgive the rest\n if (borrowBalance != 0) {\n market.healBorrow(liquidator, user, repaymentAmount);\n }\n }\n }\n\n /**\n * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than\n * a predefined threshold, and the account collateral can be seized to cover all borrows. If\n * the collateral is higher than the threshold, use regular liquidations. If the collateral is\n * below the threshold, and the account is insolvent, use healAccount.\n * @param borrower the borrower address\n * @param orders an array of liquidation orders\n * @custom:error CollateralExceedsThreshold error is thrown when the collateral is too big for a batch liquidation\n * @custom:error InsufficientCollateral error is thrown when there is not enough collateral to cover the debt\n * @custom:error SnapshotError is thrown if some vToken fails to return the account's supply and borrows\n * @custom:error PriceError is thrown if the oracle returns an incorrect price for some asset\n * @custom:access Not restricted\n */\n function liquidateAccount(address borrower, LiquidationOrder[] calldata orders) external {\n // We will accrue interest and update the oracle prices later during the liquidation\n\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(borrower, _getLiquidationThreshold);\n\n if (snapshot.totalCollateral > minLiquidatableCollateral) {\n // You should use the regular vToken.liquidateBorrow(...) call\n revert CollateralExceedsThreshold(minLiquidatableCollateral, snapshot.totalCollateral);\n }\n\n uint256 collateralToSeize = mul_ScalarTruncate(\n Exp({ mantissa: liquidationIncentiveMantissa }),\n snapshot.borrows\n );\n if (collateralToSeize >= snapshot.totalCollateral) {\n // There is not enough collateral to seize. Use healBorrow to repay some part of the borrow\n // and record bad debt.\n revert InsufficientCollateral(collateralToSeize, snapshot.totalCollateral);\n }\n\n if (snapshot.shortfall == 0) {\n revert InsufficientShortfall();\n }\n\n uint256 ordersCount = orders.length;\n\n _ensureMaxLoops(ordersCount / 2);\n\n for (uint256 i; i < ordersCount; ++i) {\n if (!markets[address(orders[i].vTokenBorrowed)].isListed) {\n revert MarketNotListed(address(orders[i].vTokenBorrowed));\n }\n if (!markets[address(orders[i].vTokenCollateral)].isListed) {\n revert MarketNotListed(address(orders[i].vTokenCollateral));\n }\n\n LiquidationOrder calldata order = orders[i];\n order.vTokenBorrowed.forceLiquidateBorrow(\n msg.sender,\n borrower,\n order.repayAmount,\n order.vTokenCollateral,\n true\n );\n }\n\n VToken[] memory borrowMarkets = getAssetsIn(borrower);\n uint256 marketsCount = borrowMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower);\n require(borrowBalance == 0, \"Nonzero borrow balance after liquidation\");\n }\n }\n\n /**\n * @notice Sets the closeFactor to use when liquidating borrows\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\n * @custom:event Emits NewCloseFactor on success\n * @custom:access Controlled by AccessControlManager\n */\n function setCloseFactor(uint256 newCloseFactorMantissa) external {\n _checkAccessAllowed(\"setCloseFactor(uint256)\");\n require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, \"Close factor greater than maximum close factor\");\n require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, \"Close factor smaller than minimum close factor\");\n\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\n closeFactorMantissa = newCloseFactorMantissa;\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\n }\n\n /**\n * @notice Sets the collateralFactor for a market\n * @dev This function is restricted by the AccessControlManager\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 * @custom:event Emits NewCollateralFactor when collateral factor is updated\n * and NewLiquidationThreshold when liquidation threshold is updated\n * @custom:error MarketNotListed error is thrown when the market is not listed\n * @custom:error InvalidCollateralFactor error is thrown when collateral factor is too high\n * @custom:error InvalidLiquidationThreshold error is thrown when liquidation threshold is lower than collateral factor\n * @custom:error PriceError is thrown when the oracle returns an invalid price for the asset\n * @custom:access Controlled by AccessControlManager\n */\n function setCollateralFactor(\n VToken vToken,\n uint256 newCollateralFactorMantissa,\n uint256 newLiquidationThresholdMantissa\n ) external {\n _checkAccessAllowed(\"setCollateralFactor(address,uint256,uint256)\");\n\n // Verify market is listed\n Market storage market = markets[address(vToken)];\n if (!market.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n // Check collateral factor <= 0.9\n if (newCollateralFactorMantissa > MAX_COLLATERAL_FACTOR_MANTISSA) {\n revert InvalidCollateralFactor();\n }\n\n // Ensure that liquidation threshold <= 1\n if (newLiquidationThresholdMantissa > MANTISSA_ONE) {\n revert InvalidLiquidationThreshold();\n }\n\n // Ensure that liquidation threshold >= CF\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\n revert InvalidLiquidationThreshold();\n }\n\n // If collateral factor != 0, fail if price == 0\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\n revert PriceError(address(vToken));\n }\n\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\n market.collateralFactorMantissa = newCollateralFactorMantissa;\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\n }\n\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\n emit NewLiquidationThreshold(vToken, oldLiquidationThresholdMantissa, newLiquidationThresholdMantissa);\n }\n }\n\n /**\n * @notice Sets liquidationIncentive\n * @dev This function is restricted by the AccessControlManager\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\n * @custom:event Emits NewLiquidationIncentive on success\n * @custom:access Controlled by AccessControlManager\n */\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external {\n require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, \"liquidation incentive should be greater than 1e18\");\n\n _checkAccessAllowed(\"setLiquidationIncentive(uint256)\");\n\n // Save current value for use in log\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\n\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\n /**\n * @notice Add the market to the markets mapping and set it as listed\n * @dev Only callable by the PoolRegistry\n * @param vToken The address of the market (token) to list\n * @custom:error MarketAlreadyListed is thrown if the market is already listed in this pool\n * @custom:access Only PoolRegistry\n */\n function supportMarket(VToken vToken) external {\n _checkSenderIs(poolRegistry);\n\n if (markets[address(vToken)].isListed) {\n revert MarketAlreadyListed(address(vToken));\n }\n\n require(vToken.isVToken(), \"Comptroller: Invalid vToken\"); // Sanity check to make sure its really a VToken\n\n Market storage newMarket = markets[address(vToken)];\n newMarket.isListed = true;\n newMarket.collateralFactorMantissa = 0;\n newMarket.liquidationThresholdMantissa = 0;\n\n _addMarket(address(vToken));\n\n uint256 rewardDistributorsCount = rewardsDistributors.length;\n\n for (uint256 i; i < rewardDistributorsCount; ++i) {\n rewardsDistributors[i].initializeMarket(address(vToken));\n }\n\n emit MarketSupported(vToken);\n }\n\n /**\n * @notice Set the given borrow caps for the given vToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\n * @dev This function is restricted by the AccessControlManager\n * @dev A borrow cap of type(uint256).max corresponds to unlimited borrowing.\n * @dev Borrow caps smaller than the current total borrows are accepted. This way, new borrows will not be allowed\n until the total borrows amount goes below the new borrow cap\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 type(uint256).max corresponds to unlimited borrowing.\n * @custom:access Controlled by AccessControlManager\n */\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\n _checkAccessAllowed(\"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 _ensureMaxLoops(numMarkets);\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 * @notice Set the given supply caps for the given vToken markets. Supply that brings total Supply to or above supply cap will revert.\n * @dev This function is restricted by the AccessControlManager\n * @dev A supply cap of type(uint256).max corresponds to unlimited supply.\n * @dev Supply caps smaller than the current total supplies are accepted. This way, new supplies will not be allowed\n until the total supplies amount goes below the new supply cap\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 type(uint256).max corresponds to unlimited supply.\n * @custom:access Controlled by AccessControlManager\n */\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\n _checkAccessAllowed(\"setMarketSupplyCaps(address[],uint256[])\");\n uint256 vTokensCount = vTokens.length;\n\n require(vTokensCount != 0, \"invalid number of markets\");\n require(vTokensCount == newSupplyCaps.length, \"invalid number of markets\");\n\n _ensureMaxLoops(vTokensCount);\n\n for (uint256 i; i < vTokensCount; ++i) {\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\n }\n }\n\n /**\n * @notice Pause/unpause specified actions\n * @dev This function is restricted by the AccessControlManager\n * @param marketsList Markets to pause/unpause the actions on\n * @param actionsList List of action ids to pause/unpause\n * @param paused The new paused state (true=paused, false=unpaused)\n * @custom:access Controlled by AccessControlManager\n */\n function setActionsPaused(VToken[] calldata marketsList, Action[] calldata actionsList, bool paused) external {\n _checkAccessAllowed(\"setActionsPaused(address[],uint256[],bool)\");\n\n uint256 marketsCount = marketsList.length;\n uint256 actionsCount = actionsList.length;\n\n _ensureMaxLoops(marketsCount * actionsCount);\n\n for (uint256 marketIdx; marketIdx < marketsCount; ++marketIdx) {\n for (uint256 actionIdx; actionIdx < actionsCount; ++actionIdx) {\n _setActionPaused(address(marketsList[marketIdx]), actionsList[actionIdx], paused);\n }\n }\n }\n\n /**\n * @notice Set the given collateral threshold for non-batch liquidations. Regular liquidations\n * will fail if the collateral amount is less than this threshold. Liquidators should use batch\n * operations like liquidateAccount or healAccount.\n * @dev This function is restricted by the AccessControlManager\n * @param newMinLiquidatableCollateral The new min liquidatable collateral (in USD).\n * @custom:access Controlled by AccessControlManager\n */\n function setMinLiquidatableCollateral(uint256 newMinLiquidatableCollateral) external {\n _checkAccessAllowed(\"setMinLiquidatableCollateral(uint256)\");\n\n uint256 oldMinLiquidatableCollateral = minLiquidatableCollateral;\n minLiquidatableCollateral = newMinLiquidatableCollateral;\n emit NewMinLiquidatableCollateral(oldMinLiquidatableCollateral, newMinLiquidatableCollateral);\n }\n\n /**\n * @notice Add a new RewardsDistributor and initialize it with all markets. We can add several RewardsDistributor\n * contracts with the same rewardToken, and there could be overlaping among them considering the last reward slot (block or second)\n * @dev Only callable by the admin\n * @param _rewardsDistributor Address of the RewardDistributor contract to add\n * @custom:access Only Governance\n * @custom:event Emits NewRewardsDistributor with distributor address\n */\n function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner {\n require(!rewardsDistributorExists[address(_rewardsDistributor)], \"already exists\");\n\n uint256 rewardsDistributorsLen = rewardsDistributors.length;\n _ensureMaxLoops(rewardsDistributorsLen + 1);\n\n rewardsDistributors.push(_rewardsDistributor);\n rewardsDistributorExists[address(_rewardsDistributor)] = true;\n\n uint256 marketsCount = allMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n _rewardsDistributor.initializeMarket(address(allMarkets[i]));\n }\n\n emit NewRewardsDistributor(address(_rewardsDistributor), address(_rewardsDistributor.rewardToken()));\n }\n\n /**\n * @notice Sets a new price oracle for the Comptroller\n * @dev Only callable by the admin\n * @param newOracle Address of the new price oracle to set\n * @custom:event Emits NewPriceOracle on success\n * @custom:error ZeroAddressNotAllowed is thrown when the new oracle address is zero\n */\n function setPriceOracle(ResilientOracleInterface newOracle) external onlyOwner {\n ensureNonzeroAddress(address(newOracle));\n\n ResilientOracleInterface oldOracle = oracle;\n oracle = newOracle;\n emit NewPriceOracle(oldOracle, newOracle);\n }\n\n /**\n * @notice Set the for loop iteration limit to avoid DOS\n * @param limit Limit for the max loops can execute at a time\n */\n function setMaxLoopsLimit(uint256 limit) external onlyOwner {\n _setMaxLoopsLimit(limit);\n }\n\n /**\n * @notice Sets the prime token contract for the comptroller\n * @param _prime Address of the Prime contract\n */\n function setPrimeToken(IPrime _prime) external onlyOwner {\n ensureNonzeroAddress(address(_prime));\n\n emit NewPrimeToken(prime, _prime);\n prime = _prime;\n }\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 * @param vTokenBorrowed Borrowed vToken\n * @param enable Whether to enable forced liquidations\n */\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\n _checkAccessAllowed(\"setForcedLiquidation(address,bool)\");\n ensureNonzeroAddress(vTokenBorrowed);\n\n if (!markets[vTokenBorrowed].isListed) {\n revert MarketNotListed(vTokenBorrowed);\n }\n\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\n }\n\n /**\n * @notice Determine the current account liquidity with respect to liquidation threshold requirements\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\n * @param account The account get liquidity for\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Account liquidity in excess of liquidation threshold requirements,\n * @return shortfall Account shortfall below liquidation threshold requirements\n */\n function getAccountLiquidity(\n address account\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getLiquidationThreshold);\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\n }\n\n /**\n * @notice Determine the current account liquidity with respect to collateral requirements\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\n * @param account The account get liquidity for\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Account liquidity in excess of collateral requirements,\n * @return shortfall Account shortfall below collateral requirements\n */\n function getBorrowingPower(\n address account\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall) {\n AccountLiquiditySnapshot memory snapshot = _getCurrentLiquiditySnapshot(account, _getCollateralFactor);\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\n }\n\n /**\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\n * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @return liquidity Hypothetical account liquidity in excess of collateral requirements,\n * @return shortfall 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 error, uint256 liquidity, uint256 shortfall) {\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n account,\n VToken(vTokenModify),\n redeemTokens,\n borrowAmount,\n _getCollateralFactor\n );\n return (NO_ERROR, snapshot.liquidity, snapshot.shortfall);\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 markets The list of market addresses\n */\n function getAllMarkets() external view override returns (VToken[] memory) {\n return allMarkets;\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 /*** Assets You Are In ***/\n\n /**\n * @notice Returns whether the given account is entered in a given market\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 market specified, 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 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 error Always NO_ERROR for compatibility with Venus core tooling\n * @return tokensToSeize Number of vTokenCollateral tokens to be seized in a liquidation\n * @custom:error PriceError if the oracle returns an invalid price\n */\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view override returns (uint256 error, uint256 tokensToSeize) {\n /* Read oracle prices for borrowed and collateral markets */\n uint256 priceBorrowedMantissa = _safeGetUnderlyingPrice(VToken(vTokenBorrowed));\n uint256 priceCollateralMantissa = _safeGetUnderlyingPrice(VToken(vTokenCollateral));\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 uint256 exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\n uint256 seizeTokens;\n Exp memory numerator;\n Exp memory denominator;\n Exp memory ratio;\n\n numerator = mul_(Exp({ mantissa: liquidationIncentiveMantissa }), Exp({ mantissa: priceBorrowedMantissa }));\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\n ratio = div_(numerator, denominator);\n\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\n\n return (NO_ERROR, seizeTokens);\n }\n\n /**\n * @notice Returns reward speed given a vToken\n * @param vToken The vToken to get the reward speeds for\n * @return rewardSpeeds Array of total supply and borrow speeds and reward token for all reward distributors\n */\n function getRewardsByMarket(address vToken) external view returns (RewardSpeeds[] memory rewardSpeeds) {\n uint256 rewardsDistributorsLength = rewardsDistributors.length;\n rewardSpeeds = new RewardSpeeds[](rewardsDistributorsLength);\n for (uint256 i; i < rewardsDistributorsLength; ++i) {\n RewardsDistributor rewardsDistributor = rewardsDistributors[i];\n address rewardToken = address(rewardsDistributor.rewardToken());\n rewardSpeeds[i] = RewardSpeeds({\n rewardToken: rewardToken,\n supplySpeed: rewardsDistributor.rewardTokenSupplySpeeds(vToken),\n borrowSpeed: rewardsDistributor.rewardTokenBorrowSpeeds(vToken)\n });\n }\n return rewardSpeeds;\n }\n\n /**\n * @notice Return all reward distributors for this pool\n * @return Array of RewardDistributor addresses\n */\n function getRewardDistributors() external view returns (RewardsDistributor[] memory) {\n return rewardsDistributors;\n }\n\n /**\n * @notice A marker method that returns true for a valid Comptroller contract\n * @return Always true\n */\n function isComptroller() external pure override returns (bool) {\n return true;\n }\n\n /**\n * @notice Update the prices of all the tokens associated with the provided account\n * @param account Address of the account to get associated tokens with\n */\n function updatePrices(address account) public {\n VToken[] memory vTokens = getAssetsIn(account);\n uint256 vTokensCount = vTokens.length;\n\n ResilientOracleInterface oracle_ = oracle;\n\n for (uint256 i; i < vTokensCount; ++i) {\n oracle_.updatePrice(address(vTokens[i]));\n }\n }\n\n /**\n * @notice Checks if a certain action is paused on a market\n * @param market vToken address\n * @param action Action to check\n * @return paused True if the action is paused otherwise false\n */\n function actionPaused(address market, Action action) public view returns (bool) {\n return _actionPaused[market][action];\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 list with the assets the account has entered\n */\n function getAssetsIn(address account) public 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 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 */\n function _addToMarket(VToken vToken, address borrower) internal {\n _checkActionPauseState(address(vToken), Action.ENTER_MARKET);\n Market storage marketToJoin = markets[address(vToken)];\n\n if (!marketToJoin.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n if (marketToJoin.accountMembership[borrower]) {\n // already joined\n return;\n }\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\n /**\n * @notice Internal function to validate that a market hasn't already been added\n * and if it hasn't adds it\n * @param vToken The market to support\n */\n function _addMarket(address vToken) internal {\n uint256 marketsCount = allMarkets.length;\n\n for (uint256 i; i < marketsCount; ++i) {\n if (allMarkets[i] == VToken(vToken)) {\n revert MarketAlreadyListed(vToken);\n }\n }\n allMarkets.push(VToken(vToken));\n marketsCount = allMarkets.length;\n _ensureMaxLoops(marketsCount);\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 _setActionPaused(address market, Action action, bool paused) internal {\n require(markets[market].isListed, \"cannot pause a market that is not listed\");\n _actionPaused[market][action] = paused;\n emit ActionPausedMarket(VToken(market), action, paused);\n }\n\n /**\n * @dev Internal function to check that vTokens can be safely redeemed for the underlying asset.\n * @param vToken Address of the vTokens to redeem\n * @param redeemer Account redeeming the tokens\n * @param redeemTokens The number of tokens to redeem\n */\n function _checkRedeemAllowed(address vToken, address redeemer, uint256 redeemTokens) internal {\n Market storage market = markets[vToken];\n\n if (!market.isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\n if (!market.accountMembership[redeemer]) {\n return;\n }\n\n // Update the prices of tokens\n updatePrices(redeemer);\n\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\n AccountLiquiditySnapshot memory snapshot = _getHypotheticalLiquiditySnapshot(\n redeemer,\n VToken(vToken),\n redeemTokens,\n 0,\n _getCollateralFactor\n );\n if (snapshot.shortfall > 0) {\n revert InsufficientLiquidity();\n }\n }\n\n /**\n * @notice Get the total collateral, weighted collateral, borrow balance, liquidity, shortfall\n * @param account The account to get the snapshot for\n * @param weight The function to compute the weight of the collateral – either collateral factor or\n * liquidation threshold. Accepts the address of the vToken and returns the weight as Exp.\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\n * without calculating accumulated interest.\n * @return snapshot Account liquidity snapshot\n */\n function _getCurrentLiquiditySnapshot(\n address account,\n function(VToken) internal view returns (Exp memory) weight\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\n return _getHypotheticalLiquiditySnapshot(account, VToken(address(0)), 0, 0, weight);\n }\n\n /**\n * @notice Determine what the supply/borrow balances 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 weight The function to compute the weight of the collateral – either collateral factor or\n liquidation threshold. Accepts the address of the VToken and returns the weight\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\n * without calculating accumulated interest.\n * @return snapshot Account liquidity snapshot\n */\n function _getHypotheticalLiquiditySnapshot(\n address account,\n VToken vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount,\n function(VToken) internal view returns (Exp memory) weight\n ) internal view returns (AccountLiquiditySnapshot memory snapshot) {\n // For each asset the account is in\n VToken[] memory assets = getAssetsIn(account);\n uint256 assetsCount = assets.length;\n\n for (uint256 i; i < assetsCount; ++i) {\n VToken asset = assets[i];\n\n // Read the balances and exchange rate from the vToken\n (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) = _safeGetAccountSnapshot(\n asset,\n account\n );\n\n // Get the normalized price of the asset\n Exp memory oraclePrice = Exp({ mantissa: _safeGetUnderlyingPrice(asset) });\n\n // Pre-compute conversion factors from vTokens -> usd\n Exp memory vTokenPrice = mul_(Exp({ mantissa: exchangeRateMantissa }), oraclePrice);\n Exp memory weightedVTokenPrice = mul_(weight(asset), vTokenPrice);\n\n // weightedCollateral += weightedVTokenPrice * vTokenBalance\n snapshot.weightedCollateral = mul_ScalarTruncateAddUInt(\n weightedVTokenPrice,\n vTokenBalance,\n snapshot.weightedCollateral\n );\n\n // totalCollateral += vTokenPrice * vTokenBalance\n snapshot.totalCollateral = mul_ScalarTruncateAddUInt(vTokenPrice, vTokenBalance, snapshot.totalCollateral);\n\n // borrows += oraclePrice * borrowBalance\n snapshot.borrows = mul_ScalarTruncateAddUInt(oraclePrice, borrowBalance, snapshot.borrows);\n\n // Calculate effects of interacting with vTokenModify\n if (asset == vTokenModify) {\n // redeem effect\n // effects += tokensToDenom * redeemTokens\n snapshot.effects = mul_ScalarTruncateAddUInt(weightedVTokenPrice, redeemTokens, snapshot.effects);\n\n // borrow effect\n // effects += oraclePrice * borrowAmount\n snapshot.effects = mul_ScalarTruncateAddUInt(oraclePrice, borrowAmount, snapshot.effects);\n }\n }\n\n uint256 borrowPlusEffects = snapshot.borrows + snapshot.effects;\n // These are safe, as the underflow condition is checked first\n unchecked {\n if (snapshot.weightedCollateral > borrowPlusEffects) {\n snapshot.liquidity = snapshot.weightedCollateral - borrowPlusEffects;\n snapshot.shortfall = 0;\n } else {\n snapshot.liquidity = 0;\n snapshot.shortfall = borrowPlusEffects - snapshot.weightedCollateral;\n }\n }\n\n return snapshot;\n }\n\n /**\n * @dev Retrieves price from oracle for an asset and checks it is nonzero\n * @param asset Address for asset to query price\n * @return Underlying price\n */\n function _safeGetUnderlyingPrice(VToken asset) internal view returns (uint256) {\n uint256 oraclePriceMantissa = oracle.getUnderlyingPrice(address(asset));\n if (oraclePriceMantissa == 0) {\n revert PriceError(address(asset));\n }\n return oraclePriceMantissa;\n }\n\n /**\n * @dev Return collateral factor for a market\n * @param asset Address for asset\n * @return Collateral factor as exponential\n */\n function _getCollateralFactor(VToken asset) internal view returns (Exp memory) {\n return Exp({ mantissa: markets[address(asset)].collateralFactorMantissa });\n }\n\n /**\n * @dev Retrieves liquidation threshold for a market as an exponential\n * @param asset Address for asset to liquidation threshold\n * @return Liquidation threshold as exponential\n */\n function _getLiquidationThreshold(VToken asset) internal view returns (Exp memory) {\n return Exp({ mantissa: markets[address(asset)].liquidationThresholdMantissa });\n }\n\n /**\n * @dev Returns supply and borrow balances of user in vToken, reverts on failure\n * @param vToken Market to query\n * @param user Account address\n * @return vTokenBalance Balance of vTokens, the same as vToken.balanceOf(user)\n * @return borrowBalance Borrowed amount, including the interest\n * @return exchangeRateMantissa Stored exchange rate\n */\n function _safeGetAccountSnapshot(\n VToken vToken,\n address user\n ) internal view returns (uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRateMantissa) {\n uint256 err;\n (err, vTokenBalance, borrowBalance, exchangeRateMantissa) = vToken.getAccountSnapshot(user);\n if (err != 0) {\n revert SnapshotError(address(vToken), user);\n }\n return (vTokenBalance, borrowBalance, exchangeRateMantissa);\n }\n\n /// @notice Reverts if the call is not from expectedSender\n /// @param expectedSender Expected transaction sender\n function _checkSenderIs(address expectedSender) internal view {\n if (msg.sender != expectedSender) {\n revert UnexpectedSender(expectedSender, msg.sender);\n }\n }\n\n /// @notice Reverts if a certain action is paused on a market\n /// @param market Market to check\n /// @param action Action to check\n function _checkActionPauseState(address market, Action action) private view {\n if (actionPaused(market, action)) {\n revert ActionPaused(market, action);\n }\n }\n}\n" + }, + "contracts/ComptrollerInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.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\n/**\n * @title ComptrollerInterface\n * @author Venus\n * @notice Interface implemented by the `Comptroller` contract.\n */\ninterface ComptrollerInterface {\n /*** Assets You Are In ***/\n\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\n\n function exitMarket(address vToken) external returns (uint256);\n\n /*** Policy Hooks ***/\n\n function preMintHook(address vToken, address minter, uint256 mintAmount) external;\n\n function preRedeemHook(address vToken, address redeemer, uint256 redeemTokens) external;\n\n function preBorrowHook(address vToken, address borrower, uint256 borrowAmount) external;\n\n function preRepayHook(address vToken, address borrower) external;\n\n function preLiquidateHook(\n address vTokenBorrowed,\n address vTokenCollateral,\n address borrower,\n uint256 repayAmount,\n bool skipLiquidityCheck\n ) external;\n\n function preSeizeHook(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower\n ) external;\n\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\n\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\n\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\n\n function repayBorrowVerify(\n address vToken,\n address payer,\n address borrower,\n uint repayAmount,\n uint borrowerIndex\n ) external;\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 seizeVerify(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint seizeTokens\n ) external;\n\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\n\n function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external;\n\n function isComptroller() external view returns (bool);\n\n /*** Liquidity/Liquidation Calculations ***/\n\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 repayAmount\n ) external view returns (uint256, uint256);\n\n function getAllMarkets() external view returns (VToken[] memory);\n\n function actionPaused(address market, Action action) external view returns (bool);\n}\n\n/**\n * @title ComptrollerViewInterface\n * @author Venus\n * @notice Interface implemented by the `Comptroller` contract, including only some util view functions.\n */\ninterface ComptrollerViewInterface {\n function markets(address) external view returns (bool, uint256);\n\n function oracle() external view returns (ResilientOracleInterface);\n\n function getAssetsIn(address) external view returns (VToken[] memory);\n\n function closeFactorMantissa() external view returns (uint256);\n\n function liquidationIncentiveMantissa() external view returns (uint256);\n\n function minLiquidatableCollateral() external view returns (uint256);\n\n function getRewardDistributors() external view returns (RewardsDistributor[] memory);\n\n function getAllMarkets() external view returns (VToken[] memory);\n\n function borrowCaps(address) external view returns (uint256);\n\n function supplyCaps(address) external view returns (uint256);\n\n function approvedDelegates(address user, address delegate) external view returns (bool);\n}\n" + }, + "contracts/ComptrollerStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { VToken } from \"./VToken.sol\";\nimport { RewardsDistributor } from \"./Rewards/RewardsDistributor.sol\";\nimport { IPrime } from \"@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol\";\nimport { Action } from \"./ComptrollerInterface.sol\";\n\n/**\n * @title ComptrollerStorage\n * @author Venus\n * @notice Storage layout for the `Comptroller` contract.\n */\ncontract ComptrollerStorage {\n struct LiquidationOrder {\n VToken vTokenCollateral;\n VToken vTokenBorrowed;\n uint256 repayAmount;\n }\n\n struct AccountLiquiditySnapshot {\n uint256 totalCollateral;\n uint256 weightedCollateral;\n uint256 borrows;\n uint256 effects;\n uint256 liquidity;\n uint256 shortfall;\n }\n\n struct RewardSpeeds {\n address rewardToken;\n uint256 supplySpeed;\n uint256 borrowSpeed;\n }\n\n struct Market {\n // Whether or not this market is listed\n bool isListed;\n // 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 uint256 collateralFactorMantissa;\n // 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 uint256 liquidationThresholdMantissa;\n // Per-market mapping of \"accounts in this asset\"\n mapping(address => bool) accountMembership;\n }\n\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 Per-account mapping of \"assets you are in\"\n */\n mapping(address => VToken[]) public accountAssets;\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 /// @notice A list of all markets\n VToken[] public allMarkets;\n\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which restricts borrowing.\n mapping(address => uint256) public borrowCaps;\n\n /// @notice Minimal collateral required for regular (non-batch) liquidations\n uint256 public minLiquidatableCollateral;\n\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting not allowed\n mapping(address => uint256) public supplyCaps;\n\n /// @notice True if a certain action is paused on a certain market\n mapping(address => mapping(Action => bool)) internal _actionPaused;\n\n // List of Reward Distributors added\n RewardsDistributor[] internal rewardsDistributors;\n\n // Used to check if rewards distributor is added\n mapping(address => bool) internal rewardsDistributorExists;\n\n /// @notice Flag indicating whether forced liquidation enabled for a market\n mapping(address => bool) public isForcedLiquidationEnabled;\n\n uint256 internal constant NO_ERROR = 0;\n\n // closeFactorMantissa must be strictly greater than this value\n uint256 internal constant MIN_CLOSE_FACTOR_MANTISSA = 0.05e18; // 0.05\n\n // closeFactorMantissa must not exceed this value\n uint256 internal constant MAX_CLOSE_FACTOR_MANTISSA = 0.9e18; // 0.9\n\n // No collateralFactorMantissa may exceed this value\n uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.95e18; // 0.95\n\n /// Prime token address\n IPrime public prime;\n\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 /**\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[47] private __gap;\n}\n" + }, + "contracts/ErrorReporter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n/**\n * @title TokenErrorReporter\n * @author Venus\n * @notice Errors that can be thrown by the `VToken` contract.\n */\ncontract TokenErrorReporter {\n uint256 public constant NO_ERROR = 0; // support legacy return codes\n\n error TransferNotAllowed();\n\n error MintFreshnessCheck();\n\n error RedeemFreshnessCheck();\n error RedeemTransferOutNotPossible();\n\n error BorrowFreshnessCheck();\n error BorrowCashNotAvailable();\n error DelegateNotApproved();\n\n error RepayBorrowFreshnessCheck();\n\n error HealBorrowUnauthorized();\n error ForceLiquidateBorrowUnauthorized();\n\n error LiquidateFreshnessCheck();\n error LiquidateCollateralFreshnessCheck();\n error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\n error LiquidateLiquidatorIsBorrower();\n error LiquidateCloseAmountIsZero();\n error LiquidateCloseAmountIsUintMax();\n\n error LiquidateSeizeLiquidatorIsBorrower();\n\n error ProtocolSeizeShareTooBig();\n\n error SetReserveFactorFreshCheck();\n error SetReserveFactorBoundsCheck();\n\n error AddReservesFactorFreshCheck(uint256 actualAddAmount);\n\n error ReduceReservesFreshCheck();\n error ReduceReservesCashNotAvailable();\n error ReduceReservesCashValidation();\n\n error SetInterestRateModelFreshCheck();\n}\n" + }, + "contracts/ExponentialNoError.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { EXP_SCALE as EXP_SCALE_, MANTISSA_ONE as MANTISSA_ONE_ } from \"./lib/constants.sol\";\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 struct Exp {\n uint256 mantissa;\n }\n\n struct Double {\n uint256 mantissa;\n }\n\n uint256 internal constant EXP_SCALE = EXP_SCALE_;\n uint256 internal constant DOUBLE_SCALE = 1e36;\n uint256 internal constant HALF_EXP_SCALE = EXP_SCALE / 2;\n uint256 internal constant MANTISSA_ONE = MANTISSA_ONE_;\n\n /**\n * @dev Truncates the given exp to a whole number value.\n * For example, truncate(Exp{mantissa: 15 * EXP_SCALE}) = 15\n */\n function truncate(Exp memory exp) internal pure returns (uint256) {\n // Note: We are not using careful math here as we're performing a division that cannot fail\n return exp.mantissa / EXP_SCALE;\n }\n\n /**\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\n */\n // solhint-disable-next-line func-name-mixedcase\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\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 // solhint-disable-next-line func-name-mixedcase\n function mul_ScalarTruncateAddUInt(Exp memory a, uint256 scalar, uint256 addend) internal pure returns (uint256) {\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 function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\n require(n <= type(uint224).max, errorMessage);\n return uint224(n);\n }\n\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\n require(n <= type(uint32).max, 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_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a + b;\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_(uint256 a, uint256 b) internal pure returns (uint256) {\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) / EXP_SCALE });\n }\n\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\n return Exp({ mantissa: mul_(a.mantissa, b) });\n }\n\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\n return mul_(a, b.mantissa) / EXP_SCALE;\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) / DOUBLE_SCALE });\n }\n\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: mul_(a.mantissa, b) });\n }\n\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\n return mul_(a, b.mantissa) / DOUBLE_SCALE;\n }\n\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a * b;\n }\n\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: div_(mul_(a.mantissa, EXP_SCALE), b.mantissa) });\n }\n\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\n return Exp({ mantissa: div_(a.mantissa, b) });\n }\n\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\n return div_(mul_(a, EXP_SCALE), 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, DOUBLE_SCALE), b.mantissa) });\n }\n\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(a.mantissa, b) });\n }\n\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\n return div_(mul_(a, DOUBLE_SCALE), b.mantissa);\n }\n\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\n return a / b;\n }\n\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(mul_(a, DOUBLE_SCALE), b) });\n }\n}\n" + }, + "contracts/InterestRateModel.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n/**\n * @title Compound's InterestRateModel Interface\n * @author Compound\n */\nabstract contract InterestRateModel {\n /**\n * @notice Calculates the current borrow interest rate per slot (block or second)\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 amount of reserves the market has\n * @param badDebt The amount of badDebt in the market\n * @return The borrow rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\n */\n function getBorrowRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 badDebt\n ) external view virtual returns (uint256);\n\n /**\n * @notice Calculates the current supply interest rate per slot (block or second)\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 amount of reserves the market has\n * @param reserveFactorMantissa The current reserve factor the market has\n * @param badDebt The amount of badDebt in the market\n * @return The supply rate percentage per slot (block or second) as a mantissa (scaled by EXP_SCALE)\n */\n function getSupplyRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 reserveFactorMantissa,\n uint256 badDebt\n ) external view virtual returns (uint256);\n\n /**\n * @notice Indicator that this is an InterestRateModel contract (for inspection)\n * @return Always true\n */\n function isInterestRateModel() external pure virtual returns (bool) {\n return true;\n }\n}\n" + }, + "contracts/IPancakeswapV2Router.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\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" + }, + "contracts/legacy/RiskFund/IRiskFund.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\n/**\n * @title IRiskFund\n * @author Venus\n * @notice Interface implemented by `RiskFund`.\n */\ninterface IRiskFundV1 {\n function swapPoolsAssets(\n address[] calldata markets,\n uint256[] calldata amountsOutMin,\n address[][] calldata paths,\n uint256 deadline\n ) external returns (uint256);\n\n function transferReserveForAuction(address comptroller, uint256 amount) external returns (uint256);\n\n function updateAssetsState(address comptroller, address asset) external;\n\n function convertibleBaseAsset() external view returns (address);\n\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256);\n}\n" + }, + "contracts/legacy/RiskFund/ReserveHelpers.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\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\";\n\nimport { ensureNonzeroAddress } from \"../../lib/validators.sol\";\nimport { ComptrollerInterface } from \"../../ComptrollerInterface.sol\";\nimport { PoolRegistryInterface } from \"../../Pool/PoolRegistryInterface.sol\";\nimport { VToken } from \"../../VToken.sol\";\n\ncontract ReserveHelpers is Ownable2StepUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n uint256 private constant NOT_ENTERED = 1;\n\n uint256 private constant ENTERED = 2;\n\n // Address of the core pool's comptroller\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable CORE_POOL_COMPTROLLER;\n\n // Address of the VBNB\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable VBNB;\n\n // Address of the native wrapped token\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable NATIVE_WRAPPED;\n\n // Store the previous state for the asset transferred to ProtocolShareReserve combined(for all pools).\n mapping(address => uint256) public assetsReserves;\n\n // Store the asset's reserve per pool in the ProtocolShareReserve.\n // Comptroller(pool) -> Asset -> amount\n mapping(address => mapping(address => uint256)) internal _poolsAssetsReserves;\n\n // Address of pool registry contract\n address public poolRegistry;\n\n /**\n * @dev Guard variable for re-entrancy checks\n */\n uint256 internal status;\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 */\n uint256[46] private __gap;\n\n /// @notice Event emitted after the update of the assets reserves.\n /// @param comptroller Pool's Comptroller address\n /// @param asset Token address\n /// @param amount An amount by which the reserves have increased\n event AssetsReservesUpdated(address indexed comptroller, address indexed asset, uint256 amount);\n\n /// @notice event emitted on sweep token success\n event SweepToken(address indexed token, address indexed to, uint256 amount);\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n */\n modifier nonReentrant() {\n require(status != ENTERED, \"re-entered\");\n status = ENTERED;\n _;\n status = NOT_ENTERED;\n }\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address corePoolComptroller_, address vbnb_, address nativeWrapped_) {\n ensureNonzeroAddress(corePoolComptroller_);\n ensureNonzeroAddress(vbnb_);\n ensureNonzeroAddress(nativeWrapped_);\n\n CORE_POOL_COMPTROLLER = corePoolComptroller_;\n VBNB = vbnb_;\n NATIVE_WRAPPED = nativeWrapped_;\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 BEP-20 token to sweep\n * @param _to Recipient of the output tokens.\n * @custom:error ZeroAddressNotAllowed is thrown when asset address is zero\n * @custom:access Only Owner\n */\n function sweepToken(address _token, address _to) external onlyOwner nonReentrant {\n ensureNonzeroAddress(_to);\n uint256 balanceDfference_;\n uint256 balance_ = IERC20Upgradeable(_token).balanceOf(address(this));\n\n require(balance_ > assetsReserves[_token], \"ReserveHelpers: Zero surplus tokens\");\n unchecked {\n balanceDfference_ = balance_ - assetsReserves[_token];\n }\n\n emit SweepToken(_token, _to, balanceDfference_);\n IERC20Upgradeable(_token).safeTransfer(_to, balanceDfference_);\n }\n\n /**\n * @notice Get the Amount of the asset in the risk fund for the specific pool.\n * @param comptroller Comptroller address(pool).\n * @param asset Asset address.\n * @return Asset's reserve in risk fund.\n * @custom:error ZeroAddressNotAllowed is thrown when asset address is zero\n */\n function getPoolAssetReserve(address comptroller, address asset) external view returns (uint256) {\n ensureNonzeroAddress(asset);\n require(ComptrollerInterface(comptroller).isComptroller(), \"ReserveHelpers: Comptroller address invalid\");\n return _poolsAssetsReserves[comptroller][asset];\n }\n\n /**\n * @notice Update the reserve of the asset for the specific pool after transferring to risk fund\n * and transferring funds to the protocol share reserve\n * @param comptroller Comptroller address(pool).\n * @param asset Asset address.\n * @custom:error ZeroAddressNotAllowed is thrown when asset address is zero\n */\n function updateAssetsState(address comptroller, address asset) public virtual {\n ensureNonzeroAddress(asset);\n require(ComptrollerInterface(comptroller).isComptroller(), \"ReserveHelpers: Comptroller address invalid\");\n address poolRegistry_ = poolRegistry;\n require(poolRegistry_ != address(0), \"ReserveHelpers: Pool Registry address is not set\");\n require(ensureAssetListed(comptroller, asset), \"ReserveHelpers: The pool doesn't support the asset\");\n uint256 currentBalance = IERC20Upgradeable(asset).balanceOf(address(this));\n uint256 assetReserve = assetsReserves[asset];\n if (currentBalance > assetReserve) {\n uint256 balanceDifference;\n unchecked {\n balanceDifference = currentBalance - assetReserve;\n }\n assetsReserves[asset] += balanceDifference;\n _poolsAssetsReserves[comptroller][asset] += balanceDifference;\n emit AssetsReservesUpdated(comptroller, asset, balanceDifference);\n }\n }\n\n function isAssetListedInCore(address tokenAddress) internal view returns (bool isAssetListed) {\n VToken[] memory coreMarkets = ComptrollerInterface(CORE_POOL_COMPTROLLER).getAllMarkets();\n for (uint256 i; i < coreMarkets.length; ++i) {\n isAssetListed = (VBNB == address(coreMarkets[i]))\n ? (tokenAddress == NATIVE_WRAPPED)\n : (coreMarkets[i].underlying() == tokenAddress);\n if (isAssetListed) {\n break;\n }\n }\n }\n\n /// @notice This function checks for the given asset is listed or not\n /// @param comptroller Address of the comptroller\n /// @param asset Address of the asset\n function ensureAssetListed(address comptroller, address asset) internal view returns (bool) {\n if (comptroller == CORE_POOL_COMPTROLLER) {\n return isAssetListedInCore(asset);\n }\n return PoolRegistryInterface(poolRegistry).getVTokenForAsset(comptroller, asset) != address(0);\n }\n}\n" + }, + "contracts/legacy/RiskFund/RiskFund.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 { SafeERC20Upgradeable } 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 { ComptrollerInterface } from \"../../ComptrollerInterface.sol\";\nimport { IRiskFundV1 } from \"./IRiskFund.sol\";\nimport { ReserveHelpers } from \"./ReserveHelpers.sol\";\nimport { ExponentialNoError } from \"../../ExponentialNoError.sol\";\nimport { VToken } from \"../../VToken.sol\";\nimport { ComptrollerViewInterface } from \"../../ComptrollerInterface.sol\";\nimport { Comptroller } from \"../../Comptroller.sol\";\nimport { PoolRegistry } from \"../../Pool/PoolRegistry.sol\";\nimport { IPancakeswapV2Router } from \"../../IPancakeswapV2Router.sol\";\nimport { MaxLoopsLimitHelper } from \"../../MaxLoopsLimitHelper.sol\";\nimport { ensureNonzeroAddress } from \"../../lib/validators.sol\";\nimport { ApproveOrRevert } from \"../../lib/ApproveOrRevert.sol\";\n\n/**\n * @title RiskFund\n * @author Venus\n * @notice Contract with basic features to track/hold different assets for different Comptrollers.\n * @dev This contract does not support BNB.\n */\ncontract RiskFund is AccessControlledV8, ExponentialNoError, ReserveHelpers, MaxLoopsLimitHelper, IRiskFundV1 {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n using ApproveOrRevert for IERC20Upgradeable;\n\n address public convertibleBaseAsset;\n address public shortfall;\n address public pancakeSwapRouter;\n uint256 public minAmountToConvert;\n\n /// @notice Emitted when pool registry address is updated\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\n\n /// @notice Emitted when shortfall contract address is updated\n event ShortfallContractUpdated(address indexed oldShortfallContract, address indexed newShortfallContract);\n\n /// @notice Emitted when convertible base asset is updated\n event ConvertibleBaseAssetUpdated(address indexed oldConvertibleBaseAsset, address indexed newConvertibleBaseAsset);\n\n /// @notice Emitted when PancakeSwap router contract address is updated\n event PancakeSwapRouterUpdated(address indexed oldPancakeSwapRouter, address indexed newPancakeSwapRouter);\n\n /// @notice Emitted when minimum amount to convert is updated\n event MinAmountToConvertUpdated(uint256 oldMinAmountToConvert, uint256 newMinAmountToConvert);\n\n /// @notice Emitted when pools assets are swapped\n event SwappedPoolsAssets(address[] markets, uint256[] amountsOutMin, uint256 totalAmount);\n\n /// @notice Emitted when reserves are transferred for auction\n event TransferredReserveForAuction(address indexed comptroller, uint256 amount);\n\n /// @dev Note that the contract is upgradeable. Use initialize() or reinitializers\n /// to set the state variables.\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address corePoolComptroller_,\n address vbnb_,\n address nativeWrapped_\n ) ReserveHelpers(corePoolComptroller_, vbnb_, nativeWrapped_) {\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the deployer to owner.\n * @param pancakeSwapRouter_ Address of the PancakeSwap router\n * @param minAmountToConvert_ Minimum amount assets must be worth to convert into base asset\n * @param convertibleBaseAsset_ Address of the base asset\n * @param accessControlManager_ Address of the access control contract\n * @param loopsLimit_ Limit for the loops in the contract to avoid DOS\n * @custom:error ZeroAddressNotAllowed is thrown when PCS router address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when convertible base asset address is zero\n */\n function initialize(\n address pancakeSwapRouter_,\n uint256 minAmountToConvert_,\n address convertibleBaseAsset_,\n address accessControlManager_,\n uint256 loopsLimit_\n ) external initializer {\n ensureNonzeroAddress(pancakeSwapRouter_);\n ensureNonzeroAddress(convertibleBaseAsset_);\n require(minAmountToConvert_ > 0, \"Risk Fund: Invalid min amount to convert\");\n require(loopsLimit_ > 0, \"Risk Fund: Loops limit can not be zero\");\n\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n\n pancakeSwapRouter = pancakeSwapRouter_;\n minAmountToConvert = minAmountToConvert_;\n convertibleBaseAsset = convertibleBaseAsset_;\n\n _setMaxLoopsLimit(loopsLimit_);\n }\n\n /**\n * @notice 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 ensureNonzeroAddress(poolRegistry_);\n address oldPoolRegistry = poolRegistry;\n poolRegistry = poolRegistry_;\n emit PoolRegistryUpdated(oldPoolRegistry, poolRegistry_);\n }\n\n /**\n * @notice Shortfall contract address setter\n * @param shortfallContractAddress_ Address of the auction contract\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\n */\n function setShortfallContractAddress(address shortfallContractAddress_) external onlyOwner {\n ensureNonzeroAddress(shortfallContractAddress_);\n\n address oldShortfallContractAddress = shortfall;\n shortfall = shortfallContractAddress_;\n emit ShortfallContractUpdated(oldShortfallContractAddress, shortfallContractAddress_);\n }\n\n /**\n * @notice PancakeSwap router address setter\n * @param pancakeSwapRouter_ Address of the PancakeSwap router\n * @custom:error ZeroAddressNotAllowed is thrown when PCS router address is zero\n */\n function setPancakeSwapRouter(address pancakeSwapRouter_) external onlyOwner {\n ensureNonzeroAddress(pancakeSwapRouter_);\n address oldPancakeSwapRouter = pancakeSwapRouter;\n pancakeSwapRouter = pancakeSwapRouter_;\n emit PancakeSwapRouterUpdated(oldPancakeSwapRouter, pancakeSwapRouter_);\n }\n\n /**\n * @notice Min amount to convert setter\n * @param minAmountToConvert_ Min amount to convert.\n */\n function setMinAmountToConvert(uint256 minAmountToConvert_) external {\n _checkAccessAllowed(\"setMinAmountToConvert(uint256)\");\n require(minAmountToConvert_ > 0, \"Risk Fund: Invalid min amount to convert\");\n uint256 oldMinAmountToConvert = minAmountToConvert;\n minAmountToConvert = minAmountToConvert_;\n emit MinAmountToConvertUpdated(oldMinAmountToConvert, minAmountToConvert_);\n }\n\n /**\n * @notice Sets a new convertible base asset\n * @param _convertibleBaseAsset Address for new convertible base asset.\n */\n function setConvertibleBaseAsset(address _convertibleBaseAsset) external {\n _checkAccessAllowed(\"setConvertibleBaseAsset(address)\");\n require(_convertibleBaseAsset != address(0), \"Risk Fund: new convertible base asset address invalid\");\n\n address oldConvertibleBaseAsset = convertibleBaseAsset;\n convertibleBaseAsset = _convertibleBaseAsset;\n\n emit ConvertibleBaseAssetUpdated(oldConvertibleBaseAsset, _convertibleBaseAsset);\n }\n\n /**\n * @notice Swap array of pool assets into base asset's tokens of at least a minimum amount\n * @param markets Array of vTokens whose assets to swap for base asset\n * @param amountsOutMin Minimum amount to receive for swap\n * @param paths A path consisting of PCS token pairs for each swap\n * @param deadline Deadline for the swap\n * @return Number of swapped tokens\n * @custom:error ZeroAddressNotAllowed is thrown if PoolRegistry contract address is not configured\n */\n function swapPoolsAssets(\n address[] calldata markets,\n uint256[] calldata amountsOutMin,\n address[][] calldata paths,\n uint256 deadline\n ) external override nonReentrant returns (uint256) {\n _checkAccessAllowed(\"swapPoolsAssets(address[],uint256[],address[][],uint256)\");\n require(deadline >= block.timestamp, \"Risk fund: deadline passed\");\n address poolRegistry_ = poolRegistry;\n ensureNonzeroAddress(poolRegistry_);\n require(markets.length == amountsOutMin.length, \"Risk fund: markets and amountsOutMin are unequal lengths\");\n require(markets.length == paths.length, \"Risk fund: markets and paths are unequal lengths\");\n\n uint256 totalAmount;\n uint256 marketsCount = markets.length;\n\n _ensureMaxLoops(marketsCount);\n\n for (uint256 i; i < marketsCount; ++i) {\n address comptroller = address(VToken(markets[i]).comptroller());\n\n PoolRegistry.VenusPool memory pool = PoolRegistry(poolRegistry_).getPoolByComptroller(comptroller);\n require(pool.comptroller == comptroller, \"comptroller doesn't exist pool registry\");\n require(Comptroller(comptroller).isMarketListed(VToken(markets[i])), \"market is not listed\");\n uint256 swappedTokens = _swapAsset(VToken(markets[i]), comptroller, amountsOutMin[i], paths[i]);\n _poolsAssetsReserves[comptroller][convertibleBaseAsset] += swappedTokens;\n assetsReserves[convertibleBaseAsset] += swappedTokens;\n totalAmount = totalAmount + swappedTokens;\n }\n emit SwappedPoolsAssets(markets, amountsOutMin, totalAmount);\n return totalAmount;\n }\n\n /**\n * @notice Transfer tokens for auction.\n * @param comptroller Comptroller of the pool.\n * @param amount Amount to be transferred to auction contract.\n * @return Number reserved tokens.\n */\n function transferReserveForAuction(\n address comptroller,\n uint256 amount\n ) external override nonReentrant returns (uint256) {\n address shortfall_ = shortfall;\n require(msg.sender == shortfall_, \"Risk fund: Only callable by Shortfall contract\");\n require(\n amount <= _poolsAssetsReserves[comptroller][convertibleBaseAsset],\n \"Risk Fund: Insufficient pool reserve.\"\n );\n unchecked {\n _poolsAssetsReserves[comptroller][convertibleBaseAsset] =\n _poolsAssetsReserves[comptroller][convertibleBaseAsset] -\n amount;\n }\n unchecked {\n assetsReserves[convertibleBaseAsset] = assetsReserves[convertibleBaseAsset] - amount;\n }\n emit TransferredReserveForAuction(comptroller, amount);\n IERC20Upgradeable(convertibleBaseAsset).safeTransfer(shortfall_, amount);\n return amount;\n }\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) external onlyOwner {\n _setMaxLoopsLimit(limit);\n }\n\n /**\n * @notice Get the Amount of the Base asset in the risk fund for the specific pool.\n * @param comptroller Comptroller address(pool).\n * @return Base Asset's reserve in risk fund.\n */\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256) {\n require(ComptrollerInterface(comptroller).isComptroller(), \"Risk Fund: Comptroller address invalid\");\n return _poolsAssetsReserves[comptroller][convertibleBaseAsset];\n }\n\n /**\n * @notice Update the reserve of the asset for the specific pool after transferring to risk fund.\n * @param comptroller Comptroller address(pool).\n * @param asset Asset address.\n */\n function updateAssetsState(address comptroller, address asset) public override(IRiskFundV1, ReserveHelpers) {\n super.updateAssetsState(comptroller, asset);\n }\n\n /**\n * @dev Swap single asset to base asset.\n * @param vToken VToken\n * @param comptroller Comptroller address\n * @param amountOutMin Minimum amount to receive for swap\n * @param path A path for the swap consisting of PCS token pairs\n * @return Number of swapped tokens.\n */\n function _swapAsset(\n VToken vToken,\n address comptroller,\n uint256 amountOutMin,\n address[] calldata path\n ) internal returns (uint256) {\n require(amountOutMin != 0, \"RiskFund: amountOutMin must be greater than 0 to swap vToken\");\n uint256 totalAmount;\n\n address underlyingAsset = vToken.underlying();\n address convertibleBaseAsset_ = convertibleBaseAsset;\n uint256 balanceOfUnderlyingAsset = _poolsAssetsReserves[comptroller][underlyingAsset];\n\n if (balanceOfUnderlyingAsset == 0) {\n return 0;\n }\n\n ResilientOracleInterface oracle = ComptrollerViewInterface(comptroller).oracle();\n oracle.updateAssetPrice(convertibleBaseAsset_);\n Exp memory baseAssetPrice = Exp({ mantissa: oracle.getPrice(convertibleBaseAsset_) });\n uint256 amountOutMinInUsd = mul_ScalarTruncate(baseAssetPrice, amountOutMin);\n\n require(amountOutMinInUsd >= minAmountToConvert, \"RiskFund: minAmountToConvert violated\");\n\n assetsReserves[underlyingAsset] -= balanceOfUnderlyingAsset;\n _poolsAssetsReserves[comptroller][underlyingAsset] -= balanceOfUnderlyingAsset;\n\n if (underlyingAsset != convertibleBaseAsset_) {\n require(path[0] == underlyingAsset, \"RiskFund: swap path must start with the underlying asset\");\n require(\n path[path.length - 1] == convertibleBaseAsset_,\n \"RiskFund: finally path must be convertible base asset\"\n );\n address pancakeSwapRouter_ = pancakeSwapRouter;\n IERC20Upgradeable(underlyingAsset).approveOrRevert(pancakeSwapRouter_, 0);\n IERC20Upgradeable(underlyingAsset).approveOrRevert(pancakeSwapRouter_, balanceOfUnderlyingAsset);\n uint256[] memory amounts = IPancakeswapV2Router(pancakeSwapRouter_).swapExactTokensForTokens(\n balanceOfUnderlyingAsset,\n amountOutMin,\n path,\n address(this),\n block.timestamp\n );\n totalAmount = amounts[path.length - 1];\n } else {\n totalAmount = balanceOfUnderlyingAsset;\n }\n\n return totalAmount;\n }\n}\n" + }, + "contracts/Lens/legacy/PoolLensR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IERC20Metadata } from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { ExponentialNoError } from \"../../ExponentialNoError.sol\";\nimport { VToken } from \"../../VToken.sol\";\nimport { ComptrollerInterface, ComptrollerViewInterface } from \"../../ComptrollerInterface.sol\";\nimport { PoolRegistryInterface } from \"../../Pool/PoolRegistryInterface.sol\";\nimport { PoolRegistry } from \"../../Pool/PoolRegistry.sol\";\nimport { RewardsDistributor } from \"../../Rewards/RewardsDistributor.sol\";\n\n/**\n * @title PoolLens\n * @author Venus\n * @notice The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information\n * for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be\n * looked up for specific pools and markets:\n- the vToken balance of a given user;\n- the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address;\n- the vToken address in a pool for a given asset;\n- a list of all pools that support an asset;\n- the underlying asset price of a vToken;\n- the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\n */\ncontract PoolLensR1 is ExponentialNoError {\n /**\n * @dev Struct for PoolDetails.\n */\n struct PoolData {\n string name;\n address creator;\n address comptroller;\n uint256 blockPosted;\n uint256 timestampPosted;\n string category;\n string logoURL;\n string description;\n address priceOracle;\n uint256 closeFactor;\n uint256 liquidationIncentive;\n uint256 minLiquidatableCollateral;\n VTokenMetadata[] vTokens;\n }\n\n /**\n * @dev Struct for VToken.\n */\n struct VTokenMetadata {\n address vToken;\n uint256 exchangeRateCurrent;\n uint256 supplyRatePerBlock;\n uint256 borrowRatePerBlock;\n uint256 reserveFactorMantissa;\n uint256 supplyCaps;\n uint256 borrowCaps;\n uint256 totalBorrows;\n uint256 totalReserves;\n uint256 totalSupply;\n uint256 totalCash;\n bool isListed;\n uint256 collateralFactorMantissa;\n address underlyingAssetAddress;\n uint256 vTokenDecimals;\n uint256 underlyingDecimals;\n }\n\n /**\n * @dev Struct for VTokenBalance.\n */\n struct VTokenBalances {\n address vToken;\n uint256 balanceOf;\n uint256 borrowBalanceCurrent;\n uint256 balanceOfUnderlying;\n uint256 tokenBalance;\n uint256 tokenAllowance;\n }\n\n /**\n * @dev Struct for underlyingPrice of VToken.\n */\n struct VTokenUnderlyingPrice {\n address vToken;\n uint256 underlyingPrice;\n }\n\n /**\n * @dev Struct with pending reward info for a market.\n */\n struct PendingReward {\n address vTokenAddress;\n uint256 amount;\n }\n\n /**\n * @dev Struct with reward distribution totals for a single reward token and distributor.\n */\n struct RewardSummary {\n address distributorAddress;\n address rewardTokenAddress;\n uint256 totalRewards;\n PendingReward[] pendingRewards;\n }\n\n /**\n * @dev Struct used in RewardDistributor to save last updated market state.\n */\n struct RewardTokenState {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block number the index was last updated at\n uint32 block;\n // The block number at which to stop rewards\n uint32 lastRewardingBlock;\n }\n\n /**\n * @dev Struct with bad debt of a market denominated\n */\n struct BadDebt {\n address vTokenAddress;\n uint256 badDebtUsd;\n }\n\n /**\n * @dev Struct with bad debt total denominated in usd for a pool and an array of BadDebt structs for each market\n */\n struct BadDebtSummary {\n address comptroller;\n uint256 totalBadDebtUsd;\n BadDebt[] badDebts;\n }\n\n /**\n * @notice Queries the user's supply/borrow balances in vTokens\n * @param vTokens The list of vToken addresses\n * @param account The user Account\n * @return A list of structs containing balances data\n */\n function vTokenBalancesAll(VToken[] calldata vTokens, address account) external returns (VTokenBalances[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenBalances[] memory res = new VTokenBalances[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenBalances(vTokens[i], account);\n }\n return res;\n }\n\n /**\n * @notice Queries all pools with addtional details for each of them\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @return Arrays of all Venus pools' data\n */\n function getAllPools(address poolRegistryAddress) external view returns (PoolData[] memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n PoolRegistry.VenusPool[] memory venusPools = poolRegistryInterface.getAllPools();\n uint256 poolLength = venusPools.length;\n\n PoolData[] memory poolDataItems = new PoolData[](poolLength);\n\n for (uint256 i; i < poolLength; ++i) {\n PoolRegistry.VenusPool memory venusPool = venusPools[i];\n PoolData memory poolData = getPoolDataFromVenusPool(poolRegistryAddress, venusPool);\n poolDataItems[i] = poolData;\n }\n\n return poolDataItems;\n }\n\n /**\n * @notice Queries the details of a pool identified by Comptroller address\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param comptroller The Comptroller implementation address\n * @return PoolData structure containing the details of the pool\n */\n function getPoolByComptroller(\n address poolRegistryAddress,\n address comptroller\n ) external view returns (PoolData memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return getPoolDataFromVenusPool(poolRegistryAddress, poolRegistryInterface.getPoolByComptroller(comptroller));\n }\n\n /**\n * @notice Returns vToken holding the specified underlying asset in the specified pool\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param comptroller The pool comptroller\n * @param asset The underlyingAsset of VToken\n * @return Address of the vToken\n */\n function getVTokenForAsset(\n address poolRegistryAddress,\n address comptroller,\n address asset\n ) external view returns (address) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return poolRegistryInterface.getVTokenForAsset(comptroller, asset);\n }\n\n /**\n * @notice Returns all pools that support the specified underlying asset\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param asset The underlying asset of vToken\n * @return A list of Comptroller contracts\n */\n function getPoolsSupportedByAsset(\n address poolRegistryAddress,\n address asset\n ) external view returns (address[] memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return poolRegistryInterface.getPoolsSupportedByAsset(asset);\n }\n\n /**\n * @notice Returns the price data for the underlying assets of the specified vTokens\n * @param vTokens The list of vToken addresses\n * @return An array containing the price data for each asset\n */\n function vTokenUnderlyingPriceAll(\n VToken[] calldata vTokens\n ) external view returns (VTokenUnderlyingPrice[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenUnderlyingPrice[] memory res = new VTokenUnderlyingPrice[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenUnderlyingPrice(vTokens[i]);\n }\n return res;\n }\n\n /**\n * @notice Returns the pending rewards for a user for a given pool.\n * @param account The user account.\n * @param comptrollerAddress address\n * @return Pending rewards array\n */\n function getPendingRewards(\n address account,\n address comptrollerAddress\n ) external view returns (RewardSummary[] memory) {\n VToken[] memory markets = ComptrollerInterface(comptrollerAddress).getAllMarkets();\n RewardsDistributor[] memory rewardsDistributors = ComptrollerViewInterface(comptrollerAddress)\n .getRewardDistributors();\n RewardSummary[] memory rewardSummary = new RewardSummary[](rewardsDistributors.length);\n for (uint256 i; i < rewardsDistributors.length; ++i) {\n RewardSummary memory reward;\n reward.distributorAddress = address(rewardsDistributors[i]);\n reward.rewardTokenAddress = address(rewardsDistributors[i].rewardToken());\n reward.totalRewards = rewardsDistributors[i].rewardTokenAccrued(account);\n reward.pendingRewards = _calculateNotDistributedAwards(account, markets, rewardsDistributors[i]);\n rewardSummary[i] = reward;\n }\n return rewardSummary;\n }\n\n /**\n * @notice Returns a summary of a pool's bad debt broken down by market\n *\n * @param comptrollerAddress Address of the comptroller\n *\n * @return badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and\n * a break down of bad debt by market\n */\n function getPoolBadDebt(address comptrollerAddress) external view returns (BadDebtSummary memory) {\n uint256 totalBadDebtUsd;\n\n // Get every market in the pool\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\n VToken[] memory markets = comptroller.getAllMarkets();\n ResilientOracleInterface priceOracle = comptroller.oracle();\n\n BadDebt[] memory badDebts = new BadDebt[](markets.length);\n\n BadDebtSummary memory badDebtSummary;\n badDebtSummary.comptroller = comptrollerAddress;\n badDebtSummary.badDebts = badDebts;\n\n // // Calculate the bad debt is USD per market\n for (uint256 i; i < markets.length; ++i) {\n BadDebt memory badDebt;\n badDebt.vTokenAddress = address(markets[i]);\n badDebt.badDebtUsd =\n (VToken(address(markets[i])).badDebt() * priceOracle.getUnderlyingPrice(address(markets[i]))) /\n EXP_SCALE;\n badDebtSummary.badDebts[i] = badDebt;\n totalBadDebtUsd = totalBadDebtUsd + badDebt.badDebtUsd;\n }\n\n badDebtSummary.totalBadDebtUsd = totalBadDebtUsd;\n\n return badDebtSummary;\n }\n\n /**\n * @notice Queries the user's supply/borrow balances in the specified vToken\n * @param vToken vToken address\n * @param account The user Account\n * @return A struct containing the balances data\n */\n function vTokenBalances(VToken vToken, address account) public returns (VTokenBalances memory) {\n uint256 balanceOf = vToken.balanceOf(account);\n uint256 borrowBalanceCurrent = vToken.borrowBalanceCurrent(account);\n uint256 balanceOfUnderlying = vToken.balanceOfUnderlying(account);\n uint256 tokenBalance;\n uint256 tokenAllowance;\n\n IERC20 underlying = IERC20(vToken.underlying());\n tokenBalance = underlying.balanceOf(account);\n tokenAllowance = underlying.allowance(account, address(vToken));\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 Queries additional information for the pool\n * @param poolRegistryAddress Address of the PoolRegistry\n * @param venusPool The VenusPool Object from PoolRegistry\n * @return Enriched PoolData\n */\n function getPoolDataFromVenusPool(\n address poolRegistryAddress,\n PoolRegistry.VenusPool memory venusPool\n ) public view returns (PoolData memory) {\n // Get tokens in the Pool\n ComptrollerInterface comptrollerInstance = ComptrollerInterface(venusPool.comptroller);\n\n VToken[] memory vTokens = comptrollerInstance.getAllMarkets();\n\n VTokenMetadata[] memory vTokenMetadataItems = vTokenMetadataAll(vTokens);\n\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n\n PoolRegistry.VenusPoolMetaData memory venusPoolMetaData = poolRegistryInterface.getVenusPoolMetadata(\n venusPool.comptroller\n );\n\n ComptrollerViewInterface comptrollerViewInstance = ComptrollerViewInterface(venusPool.comptroller);\n\n PoolData memory poolData = PoolData({\n name: venusPool.name,\n creator: venusPool.creator,\n comptroller: venusPool.comptroller,\n blockPosted: venusPool.blockPosted,\n timestampPosted: venusPool.timestampPosted,\n category: venusPoolMetaData.category,\n logoURL: venusPoolMetaData.logoURL,\n description: venusPoolMetaData.description,\n vTokens: vTokenMetadataItems,\n priceOracle: address(comptrollerViewInstance.oracle()),\n closeFactor: comptrollerViewInstance.closeFactorMantissa(),\n liquidationIncentive: comptrollerViewInstance.liquidationIncentiveMantissa(),\n minLiquidatableCollateral: comptrollerViewInstance.minLiquidatableCollateral()\n });\n\n return poolData;\n }\n\n /**\n * @notice Returns the metadata of VToken\n * @param vToken The address of vToken\n * @return VTokenMetadata struct\n */\n function vTokenMetadata(VToken vToken) public view returns (VTokenMetadata memory) {\n uint256 exchangeRateCurrent = vToken.exchangeRateStored();\n address comptrollerAddress = address(vToken.comptroller());\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\n (bool isListed, uint256 collateralFactorMantissa) = comptroller.markets(address(vToken));\n\n address underlyingAssetAddress = vToken.underlying();\n uint256 underlyingDecimals = IERC20Metadata(underlyingAssetAddress).decimals();\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 supplyCaps: comptroller.supplyCaps(address(vToken)),\n borrowCaps: comptroller.borrowCaps(address(vToken)),\n totalBorrows: vToken.totalBorrows(),\n totalReserves: vToken.totalReserves(),\n totalSupply: vToken.totalSupply(),\n totalCash: vToken.getCash(),\n isListed: isListed,\n collateralFactorMantissa: collateralFactorMantissa,\n underlyingAssetAddress: underlyingAssetAddress,\n vTokenDecimals: vToken.decimals(),\n underlyingDecimals: underlyingDecimals\n });\n }\n\n /**\n * @notice Returns the metadata of all VTokens\n * @param vTokens The list of vToken addresses\n * @return An array of VTokenMetadata structs\n */\n function vTokenMetadataAll(VToken[] memory vTokens) public view returns (VTokenMetadata[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenMetadata[] memory res = new VTokenMetadata[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenMetadata(vTokens[i]);\n }\n return res;\n }\n\n /**\n * @notice Returns the price data for the underlying asset of the specified vToken\n * @param vToken vToken address\n * @return The price data for each asset\n */\n function vTokenUnderlyingPrice(VToken vToken) public view returns (VTokenUnderlyingPrice memory) {\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(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 function _calculateNotDistributedAwards(\n address account,\n VToken[] memory markets,\n RewardsDistributor rewardsDistributor\n ) internal view returns (PendingReward[] memory) {\n PendingReward[] memory pendingRewards = new PendingReward[](markets.length);\n for (uint256 i; i < markets.length; ++i) {\n // Market borrow and supply state we will modify update in-memory, in order to not modify storage\n RewardTokenState memory borrowState;\n (borrowState.index, borrowState.block, borrowState.lastRewardingBlock) = rewardsDistributor\n .rewardTokenBorrowState(address(markets[i]));\n RewardTokenState memory supplyState;\n (supplyState.index, supplyState.block, supplyState.lastRewardingBlock) = rewardsDistributor\n .rewardTokenSupplyState(address(markets[i]));\n Exp memory marketBorrowIndex = Exp({ mantissa: markets[i].borrowIndex() });\n\n // Update market supply and borrow index in-memory\n updateMarketBorrowIndex(address(markets[i]), rewardsDistributor, borrowState, marketBorrowIndex);\n updateMarketSupplyIndex(address(markets[i]), rewardsDistributor, supplyState);\n\n // Calculate pending rewards\n uint256 borrowReward = calculateBorrowerReward(\n address(markets[i]),\n rewardsDistributor,\n account,\n borrowState,\n marketBorrowIndex\n );\n uint256 supplyReward = calculateSupplierReward(\n address(markets[i]),\n rewardsDistributor,\n account,\n supplyState\n );\n\n PendingReward memory pendingReward;\n pendingReward.vTokenAddress = address(markets[i]);\n pendingReward.amount = borrowReward + supplyReward;\n pendingRewards[i] = pendingReward;\n }\n return pendingRewards;\n }\n\n function updateMarketBorrowIndex(\n address vToken,\n RewardsDistributor rewardsDistributor,\n RewardTokenState memory borrowState,\n Exp memory marketBorrowIndex\n ) internal view {\n uint256 borrowSpeed = rewardsDistributor.rewardTokenBorrowSpeeds(vToken);\n uint256 blockNumber = block.number;\n\n if (borrowState.lastRewardingBlock > 0 && blockNumber > borrowState.lastRewardingBlock) {\n blockNumber = borrowState.lastRewardingBlock;\n }\n\n uint256 deltaBlocks = sub_(blockNumber, uint256(borrowState.block));\n if (deltaBlocks > 0 && borrowSpeed > 0) {\n // Remove the total earned interest rate since the opening of the market from total borrows\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint256 tokensAccrued = mul_(deltaBlocks, borrowSpeed);\n Double memory ratio = borrowAmount > 0 ? fraction(tokensAccrued, 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 function updateMarketSupplyIndex(\n address vToken,\n RewardsDistributor rewardsDistributor,\n RewardTokenState memory supplyState\n ) internal view {\n uint256 supplySpeed = rewardsDistributor.rewardTokenSupplySpeeds(vToken);\n uint256 blockNumber = block.number;\n\n if (supplyState.lastRewardingBlock > 0 && blockNumber > supplyState.lastRewardingBlock) {\n blockNumber = supplyState.lastRewardingBlock;\n }\n\n uint256 deltaBlocks = sub_(blockNumber, uint256(supplyState.block));\n if (deltaBlocks > 0 && supplySpeed > 0) {\n uint256 supplyTokens = VToken(vToken).totalSupply();\n uint256 tokensAccrued = mul_(deltaBlocks, supplySpeed);\n Double memory ratio = supplyTokens > 0 ? fraction(tokensAccrued, 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 function calculateBorrowerReward(\n address vToken,\n RewardsDistributor rewardsDistributor,\n address borrower,\n RewardTokenState memory borrowState,\n Exp memory marketBorrowIndex\n ) internal view returns (uint256) {\n Double memory borrowIndex = Double({ mantissa: borrowState.index });\n Double memory borrowerIndex = Double({\n mantissa: rewardsDistributor.rewardTokenBorrowerIndex(vToken, borrower)\n });\n if (borrowerIndex.mantissa == 0 && borrowIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\n // Covers the case where users borrowed tokens before the market's borrow state index was set\n borrowerIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\n }\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\n return borrowerDelta;\n }\n\n function calculateSupplierReward(\n address vToken,\n RewardsDistributor rewardsDistributor,\n address supplier,\n RewardTokenState memory supplyState\n ) internal view returns (uint256) {\n Double memory supplyIndex = Double({ mantissa: supplyState.index });\n Double memory supplierIndex = Double({\n mantissa: rewardsDistributor.rewardTokenSupplierIndex(vToken, supplier)\n });\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\n // Covers the case where users supplied tokens before the market's supply state index was set\n supplierIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\n }\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\n return supplierDelta;\n }\n}\n" + }, + "contracts/Lens/legacy/PoolLensR2.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IERC20Metadata } from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { ExponentialNoError } from \"../../ExponentialNoError.sol\";\nimport { VToken } from \"../../VToken.sol\";\nimport { Action, ComptrollerInterface, ComptrollerViewInterface } from \"../../ComptrollerInterface.sol\";\nimport { PoolRegistryInterface } from \"../../Pool/PoolRegistryInterface.sol\";\nimport { PoolRegistry } from \"../../Pool/PoolRegistry.sol\";\nimport { RewardsDistributor } from \"../../Rewards/RewardsDistributor.sol\";\n\n/**\n * @title PoolLens\n * @author Venus\n * @notice The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information\n * for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be\n * looked up for specific pools and markets:\n- the vToken balance of a given user;\n- the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address;\n- the vToken address in a pool for a given asset;\n- a list of all pools that support an asset;\n- the underlying asset price of a vToken;\n- the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\n */\ncontract PoolLensR2 is ExponentialNoError {\n /**\n * @dev Struct for PoolDetails.\n */\n struct PoolData {\n string name;\n address creator;\n address comptroller;\n uint256 blockPosted;\n uint256 timestampPosted;\n string category;\n string logoURL;\n string description;\n address priceOracle;\n uint256 closeFactor;\n uint256 liquidationIncentive;\n uint256 minLiquidatableCollateral;\n VTokenMetadata[] vTokens;\n }\n\n /**\n * @dev Struct for VToken.\n */\n struct VTokenMetadata {\n address vToken;\n uint256 exchangeRateCurrent;\n uint256 supplyRatePerBlock;\n uint256 borrowRatePerBlock;\n uint256 reserveFactorMantissa;\n uint256 supplyCaps;\n uint256 borrowCaps;\n uint256 totalBorrows;\n uint256 totalReserves;\n uint256 totalSupply;\n uint256 totalCash;\n bool isListed;\n uint256 collateralFactorMantissa;\n address underlyingAssetAddress;\n uint256 vTokenDecimals;\n uint256 underlyingDecimals;\n uint256 pausedActions;\n }\n\n /**\n * @dev Struct for VTokenBalance.\n */\n struct VTokenBalances {\n address vToken;\n uint256 balanceOf;\n uint256 borrowBalanceCurrent;\n uint256 balanceOfUnderlying;\n uint256 tokenBalance;\n uint256 tokenAllowance;\n }\n\n /**\n * @dev Struct for underlyingPrice of VToken.\n */\n struct VTokenUnderlyingPrice {\n address vToken;\n uint256 underlyingPrice;\n }\n\n /**\n * @dev Struct with pending reward info for a market.\n */\n struct PendingReward {\n address vTokenAddress;\n uint256 amount;\n }\n\n /**\n * @dev Struct with reward distribution totals for a single reward token and distributor.\n */\n struct RewardSummary {\n address distributorAddress;\n address rewardTokenAddress;\n uint256 totalRewards;\n PendingReward[] pendingRewards;\n }\n\n /**\n * @dev Struct used in RewardDistributor to save last updated market state.\n */\n struct RewardTokenState {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block number the index was last updated at\n uint32 block;\n // The block number at which to stop rewards\n uint32 lastRewardingBlock;\n }\n\n /**\n * @dev Struct with bad debt of a market denominated\n */\n struct BadDebt {\n address vTokenAddress;\n uint256 badDebtUsd;\n }\n\n /**\n * @dev Struct with bad debt total denominated in usd for a pool and an array of BadDebt structs for each market\n */\n struct BadDebtSummary {\n address comptroller;\n uint256 totalBadDebtUsd;\n BadDebt[] badDebts;\n }\n\n /**\n * @notice Queries the user's supply/borrow balances in vTokens\n * @param vTokens The list of vToken addresses\n * @param account The user Account\n * @return A list of structs containing balances data\n */\n function vTokenBalancesAll(VToken[] calldata vTokens, address account) external returns (VTokenBalances[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenBalances[] memory res = new VTokenBalances[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenBalances(vTokens[i], account);\n }\n return res;\n }\n\n /**\n * @notice Queries all pools with addtional details for each of them\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @return Arrays of all Venus pools' data\n */\n function getAllPools(address poolRegistryAddress) external view returns (PoolData[] memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n PoolRegistry.VenusPool[] memory venusPools = poolRegistryInterface.getAllPools();\n uint256 poolLength = venusPools.length;\n\n PoolData[] memory poolDataItems = new PoolData[](poolLength);\n\n for (uint256 i; i < poolLength; ++i) {\n PoolRegistry.VenusPool memory venusPool = venusPools[i];\n PoolData memory poolData = getPoolDataFromVenusPool(poolRegistryAddress, venusPool);\n poolDataItems[i] = poolData;\n }\n\n return poolDataItems;\n }\n\n /**\n * @notice Queries the details of a pool identified by Comptroller address\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param comptroller The Comptroller implementation address\n * @return PoolData structure containing the details of the pool\n */\n function getPoolByComptroller(\n address poolRegistryAddress,\n address comptroller\n ) external view returns (PoolData memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return getPoolDataFromVenusPool(poolRegistryAddress, poolRegistryInterface.getPoolByComptroller(comptroller));\n }\n\n /**\n * @notice Returns vToken holding the specified underlying asset in the specified pool\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param comptroller The pool comptroller\n * @param asset The underlyingAsset of VToken\n * @return Address of the vToken\n */\n function getVTokenForAsset(\n address poolRegistryAddress,\n address comptroller,\n address asset\n ) external view returns (address) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return poolRegistryInterface.getVTokenForAsset(comptroller, asset);\n }\n\n /**\n * @notice Returns all pools that support the specified underlying asset\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param asset The underlying asset of vToken\n * @return A list of Comptroller contracts\n */\n function getPoolsSupportedByAsset(\n address poolRegistryAddress,\n address asset\n ) external view returns (address[] memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return poolRegistryInterface.getPoolsSupportedByAsset(asset);\n }\n\n /**\n * @notice Returns the price data for the underlying assets of the specified vTokens\n * @param vTokens The list of vToken addresses\n * @return An array containing the price data for each asset\n */\n function vTokenUnderlyingPriceAll(\n VToken[] calldata vTokens\n ) external view returns (VTokenUnderlyingPrice[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenUnderlyingPrice[] memory res = new VTokenUnderlyingPrice[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenUnderlyingPrice(vTokens[i]);\n }\n return res;\n }\n\n /**\n * @notice Returns the pending rewards for a user for a given pool.\n * @param account The user account.\n * @param comptrollerAddress address\n * @return Pending rewards array\n */\n function getPendingRewards(\n address account,\n address comptrollerAddress\n ) external view returns (RewardSummary[] memory) {\n VToken[] memory markets = ComptrollerInterface(comptrollerAddress).getAllMarkets();\n RewardsDistributor[] memory rewardsDistributors = ComptrollerViewInterface(comptrollerAddress)\n .getRewardDistributors();\n RewardSummary[] memory rewardSummary = new RewardSummary[](rewardsDistributors.length);\n for (uint256 i; i < rewardsDistributors.length; ++i) {\n RewardSummary memory reward;\n reward.distributorAddress = address(rewardsDistributors[i]);\n reward.rewardTokenAddress = address(rewardsDistributors[i].rewardToken());\n reward.totalRewards = rewardsDistributors[i].rewardTokenAccrued(account);\n reward.pendingRewards = _calculateNotDistributedAwards(account, markets, rewardsDistributors[i]);\n rewardSummary[i] = reward;\n }\n return rewardSummary;\n }\n\n /**\n * @notice Returns a summary of a pool's bad debt broken down by market\n *\n * @param comptrollerAddress Address of the comptroller\n *\n * @return badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and\n * a break down of bad debt by market\n */\n function getPoolBadDebt(address comptrollerAddress) external view returns (BadDebtSummary memory) {\n uint256 totalBadDebtUsd;\n\n // Get every market in the pool\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\n VToken[] memory markets = comptroller.getAllMarkets();\n ResilientOracleInterface priceOracle = comptroller.oracle();\n\n BadDebt[] memory badDebts = new BadDebt[](markets.length);\n\n BadDebtSummary memory badDebtSummary;\n badDebtSummary.comptroller = comptrollerAddress;\n badDebtSummary.badDebts = badDebts;\n\n // // Calculate the bad debt is USD per market\n for (uint256 i; i < markets.length; ++i) {\n BadDebt memory badDebt;\n badDebt.vTokenAddress = address(markets[i]);\n badDebt.badDebtUsd =\n (VToken(address(markets[i])).badDebt() * priceOracle.getUnderlyingPrice(address(markets[i]))) /\n EXP_SCALE;\n badDebtSummary.badDebts[i] = badDebt;\n totalBadDebtUsd = totalBadDebtUsd + badDebt.badDebtUsd;\n }\n\n badDebtSummary.totalBadDebtUsd = totalBadDebtUsd;\n\n return badDebtSummary;\n }\n\n /**\n * @notice Queries the user's supply/borrow balances in the specified vToken\n * @param vToken vToken address\n * @param account The user Account\n * @return A struct containing the balances data\n */\n function vTokenBalances(VToken vToken, address account) public returns (VTokenBalances memory) {\n uint256 balanceOf = vToken.balanceOf(account);\n uint256 borrowBalanceCurrent = vToken.borrowBalanceCurrent(account);\n uint256 balanceOfUnderlying = vToken.balanceOfUnderlying(account);\n uint256 tokenBalance;\n uint256 tokenAllowance;\n\n IERC20 underlying = IERC20(vToken.underlying());\n tokenBalance = underlying.balanceOf(account);\n tokenAllowance = underlying.allowance(account, address(vToken));\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 Queries additional information for the pool\n * @param poolRegistryAddress Address of the PoolRegistry\n * @param venusPool The VenusPool Object from PoolRegistry\n * @return Enriched PoolData\n */\n function getPoolDataFromVenusPool(\n address poolRegistryAddress,\n PoolRegistry.VenusPool memory venusPool\n ) public view returns (PoolData memory) {\n // Get tokens in the Pool\n ComptrollerInterface comptrollerInstance = ComptrollerInterface(venusPool.comptroller);\n\n VToken[] memory vTokens = comptrollerInstance.getAllMarkets();\n\n VTokenMetadata[] memory vTokenMetadataItems = vTokenMetadataAll(vTokens);\n\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n\n PoolRegistry.VenusPoolMetaData memory venusPoolMetaData = poolRegistryInterface.getVenusPoolMetadata(\n venusPool.comptroller\n );\n\n ComptrollerViewInterface comptrollerViewInstance = ComptrollerViewInterface(venusPool.comptroller);\n\n PoolData memory poolData = PoolData({\n name: venusPool.name,\n creator: venusPool.creator,\n comptroller: venusPool.comptroller,\n blockPosted: venusPool.blockPosted,\n timestampPosted: venusPool.timestampPosted,\n category: venusPoolMetaData.category,\n logoURL: venusPoolMetaData.logoURL,\n description: venusPoolMetaData.description,\n vTokens: vTokenMetadataItems,\n priceOracle: address(comptrollerViewInstance.oracle()),\n closeFactor: comptrollerViewInstance.closeFactorMantissa(),\n liquidationIncentive: comptrollerViewInstance.liquidationIncentiveMantissa(),\n minLiquidatableCollateral: comptrollerViewInstance.minLiquidatableCollateral()\n });\n\n return poolData;\n }\n\n /**\n * @notice Returns the metadata of VToken\n * @param vToken The address of vToken\n * @return VTokenMetadata struct\n */\n function vTokenMetadata(VToken vToken) public view returns (VTokenMetadata memory) {\n uint256 exchangeRateCurrent = vToken.exchangeRateStored();\n address comptrollerAddress = address(vToken.comptroller());\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\n (bool isListed, uint256 collateralFactorMantissa) = comptroller.markets(address(vToken));\n\n address underlyingAssetAddress = vToken.underlying();\n uint256 underlyingDecimals = IERC20Metadata(underlyingAssetAddress).decimals();\n\n uint256 pausedActions;\n for (uint8 i; i <= uint8(type(Action).max); ++i) {\n uint256 paused = ComptrollerInterface(comptrollerAddress).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 supplyCaps: comptroller.supplyCaps(address(vToken)),\n borrowCaps: comptroller.borrowCaps(address(vToken)),\n totalBorrows: vToken.totalBorrows(),\n totalReserves: vToken.totalReserves(),\n totalSupply: vToken.totalSupply(),\n totalCash: vToken.getCash(),\n isListed: isListed,\n collateralFactorMantissa: collateralFactorMantissa,\n underlyingAssetAddress: underlyingAssetAddress,\n vTokenDecimals: vToken.decimals(),\n underlyingDecimals: underlyingDecimals,\n pausedActions: pausedActions\n });\n }\n\n /**\n * @notice Returns the metadata of all VTokens\n * @param vTokens The list of vToken addresses\n * @return An array of VTokenMetadata structs\n */\n function vTokenMetadataAll(VToken[] memory vTokens) public view returns (VTokenMetadata[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenMetadata[] memory res = new VTokenMetadata[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenMetadata(vTokens[i]);\n }\n return res;\n }\n\n /**\n * @notice Returns the price data for the underlying asset of the specified vToken\n * @param vToken vToken address\n * @return The price data for each asset\n */\n function vTokenUnderlyingPrice(VToken vToken) public view returns (VTokenUnderlyingPrice memory) {\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(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 function _calculateNotDistributedAwards(\n address account,\n VToken[] memory markets,\n RewardsDistributor rewardsDistributor\n ) internal view returns (PendingReward[] memory) {\n PendingReward[] memory pendingRewards = new PendingReward[](markets.length);\n for (uint256 i; i < markets.length; ++i) {\n // Market borrow and supply state we will modify update in-memory, in order to not modify storage\n RewardTokenState memory borrowState;\n (borrowState.index, borrowState.block, borrowState.lastRewardingBlock) = rewardsDistributor\n .rewardTokenBorrowState(address(markets[i]));\n RewardTokenState memory supplyState;\n (supplyState.index, supplyState.block, supplyState.lastRewardingBlock) = rewardsDistributor\n .rewardTokenSupplyState(address(markets[i]));\n Exp memory marketBorrowIndex = Exp({ mantissa: markets[i].borrowIndex() });\n\n // Update market supply and borrow index in-memory\n updateMarketBorrowIndex(address(markets[i]), rewardsDistributor, borrowState, marketBorrowIndex);\n updateMarketSupplyIndex(address(markets[i]), rewardsDistributor, supplyState);\n\n // Calculate pending rewards\n uint256 borrowReward = calculateBorrowerReward(\n address(markets[i]),\n rewardsDistributor,\n account,\n borrowState,\n marketBorrowIndex\n );\n uint256 supplyReward = calculateSupplierReward(\n address(markets[i]),\n rewardsDistributor,\n account,\n supplyState\n );\n\n PendingReward memory pendingReward;\n pendingReward.vTokenAddress = address(markets[i]);\n pendingReward.amount = borrowReward + supplyReward;\n pendingRewards[i] = pendingReward;\n }\n return pendingRewards;\n }\n\n function updateMarketBorrowIndex(\n address vToken,\n RewardsDistributor rewardsDistributor,\n RewardTokenState memory borrowState,\n Exp memory marketBorrowIndex\n ) internal view {\n uint256 borrowSpeed = rewardsDistributor.rewardTokenBorrowSpeeds(vToken);\n uint256 blockNumber = block.number;\n\n if (borrowState.lastRewardingBlock > 0 && blockNumber > borrowState.lastRewardingBlock) {\n blockNumber = borrowState.lastRewardingBlock;\n }\n\n uint256 deltaBlocks = sub_(blockNumber, uint256(borrowState.block));\n if (deltaBlocks > 0 && borrowSpeed > 0) {\n // Remove the total earned interest rate since the opening of the market from total borrows\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint256 tokensAccrued = mul_(deltaBlocks, borrowSpeed);\n Double memory ratio = borrowAmount > 0 ? fraction(tokensAccrued, 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 function updateMarketSupplyIndex(\n address vToken,\n RewardsDistributor rewardsDistributor,\n RewardTokenState memory supplyState\n ) internal view {\n uint256 supplySpeed = rewardsDistributor.rewardTokenSupplySpeeds(vToken);\n uint256 blockNumber = block.number;\n\n if (supplyState.lastRewardingBlock > 0 && blockNumber > supplyState.lastRewardingBlock) {\n blockNumber = supplyState.lastRewardingBlock;\n }\n\n uint256 deltaBlocks = sub_(blockNumber, uint256(supplyState.block));\n if (deltaBlocks > 0 && supplySpeed > 0) {\n uint256 supplyTokens = VToken(vToken).totalSupply();\n uint256 tokensAccrued = mul_(deltaBlocks, supplySpeed);\n Double memory ratio = supplyTokens > 0 ? fraction(tokensAccrued, 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 function calculateBorrowerReward(\n address vToken,\n RewardsDistributor rewardsDistributor,\n address borrower,\n RewardTokenState memory borrowState,\n Exp memory marketBorrowIndex\n ) internal view returns (uint256) {\n Double memory borrowIndex = Double({ mantissa: borrowState.index });\n Double memory borrowerIndex = Double({\n mantissa: rewardsDistributor.rewardTokenBorrowerIndex(vToken, borrower)\n });\n if (borrowerIndex.mantissa == 0 && borrowIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\n // Covers the case where users borrowed tokens before the market's borrow state index was set\n borrowerIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\n }\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\n return borrowerDelta;\n }\n\n function calculateSupplierReward(\n address vToken,\n RewardsDistributor rewardsDistributor,\n address supplier,\n RewardTokenState memory supplyState\n ) internal view returns (uint256) {\n Double memory supplyIndex = Double({ mantissa: supplyState.index });\n Double memory supplierIndex = Double({\n mantissa: rewardsDistributor.rewardTokenSupplierIndex(vToken, supplier)\n });\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\n // Covers the case where users supplied tokens before the market's supply state index was set\n supplierIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\n }\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\n return supplierDelta;\n }\n}\n" + }, + "contracts/Lens/PoolLens.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IERC20Metadata } from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { ExponentialNoError } from \"../ExponentialNoError.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { Action, ComptrollerInterface, ComptrollerViewInterface } from \"../ComptrollerInterface.sol\";\nimport { PoolRegistryInterface } from \"../Pool/PoolRegistryInterface.sol\";\nimport { PoolRegistry } from \"../Pool/PoolRegistry.sol\";\nimport { RewardsDistributor } from \"../Rewards/RewardsDistributor.sol\";\nimport { TimeManagerV8 } from \"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\";\n\n/**\n * @title PoolLens\n * @author Venus\n * @notice The `PoolLens` contract is designed to retrieve important information for each registered pool. A list of essential information\n * for all pools within the lending protocol can be acquired through the function `getAllPools()`. Additionally, the following records can be\n * looked up for specific pools and markets:\n- the vToken balance of a given user;\n- the pool data (oracle address, associated vToken, liquidation incentive, etc) of a pool via its associated comptroller address;\n- the vToken address in a pool for a given asset;\n- a list of all pools that support an asset;\n- the underlying asset price of a vToken;\n- the metadata (exchange/borrow/supply rate, total supply, collateral factor, etc) of any vToken.\n */\ncontract PoolLens is ExponentialNoError, TimeManagerV8 {\n /**\n * @dev Struct for PoolDetails.\n */\n struct PoolData {\n string name;\n address creator;\n address comptroller;\n uint256 blockPosted;\n uint256 timestampPosted;\n string category;\n string logoURL;\n string description;\n address priceOracle;\n uint256 closeFactor;\n uint256 liquidationIncentive;\n uint256 minLiquidatableCollateral;\n VTokenMetadata[] vTokens;\n }\n\n /**\n * @dev Struct for VToken.\n */\n struct VTokenMetadata {\n address vToken;\n uint256 exchangeRateCurrent;\n uint256 supplyRatePerBlockOrTimestamp;\n uint256 borrowRatePerBlockOrTimestamp;\n uint256 reserveFactorMantissa;\n uint256 supplyCaps;\n uint256 borrowCaps;\n uint256 totalBorrows;\n uint256 totalReserves;\n uint256 totalSupply;\n uint256 totalCash;\n bool isListed;\n uint256 collateralFactorMantissa;\n address underlyingAssetAddress;\n uint256 vTokenDecimals;\n uint256 underlyingDecimals;\n uint256 pausedActions;\n }\n\n /**\n * @dev Struct for VTokenBalance.\n */\n struct VTokenBalances {\n address vToken;\n uint256 balanceOf;\n uint256 borrowBalanceCurrent;\n uint256 balanceOfUnderlying;\n uint256 tokenBalance;\n uint256 tokenAllowance;\n }\n\n /**\n * @dev Struct for underlyingPrice of VToken.\n */\n struct VTokenUnderlyingPrice {\n address vToken;\n uint256 underlyingPrice;\n }\n\n /**\n * @dev Struct with pending reward info for a market.\n */\n struct PendingReward {\n address vTokenAddress;\n uint256 amount;\n }\n\n /**\n * @dev Struct with reward distribution totals for a single reward token and distributor.\n */\n struct RewardSummary {\n address distributorAddress;\n address rewardTokenAddress;\n uint256 totalRewards;\n PendingReward[] pendingRewards;\n }\n\n /**\n * @dev Struct used in RewardDistributor to save last updated market state.\n */\n struct RewardTokenState {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block number or timestamp the index was last updated at\n uint256 blockOrTimestamp;\n // The block number or timestamp at which to stop rewards\n uint256 lastRewardingBlockOrTimestamp;\n }\n\n /**\n * @dev Struct with bad debt of a market denominated\n */\n struct BadDebt {\n address vTokenAddress;\n uint256 badDebtUsd;\n }\n\n /**\n * @dev Struct with bad debt total denominated in usd for a pool and an array of BadDebt structs for each market\n */\n struct BadDebtSummary {\n address comptroller;\n uint256 totalBadDebtUsd;\n BadDebt[] badDebts;\n }\n\n /// @notice Address of the core pool comptroller (all markets are returned for this pool, including paused ones)\n address public immutable corePoolComptroller;\n\n /**\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\n * @param blocksPerYear_ The number of blocks per year\n * @param corePoolComptroller_ The address of the core pool comptroller\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor(\n bool timeBased_,\n uint256 blocksPerYear_,\n address corePoolComptroller_\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\n corePoolComptroller = corePoolComptroller_;\n }\n\n /**\n * @notice Queries the user's supply/borrow balances in vTokens\n * @param vTokens The list of vToken addresses\n * @param account The user Account\n * @return A list of structs containing balances data\n */\n function vTokenBalancesAll(VToken[] calldata vTokens, address account) external returns (VTokenBalances[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenBalances[] memory res = new VTokenBalances[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenBalances(vTokens[i], account);\n }\n return res;\n }\n\n /**\n * @notice Queries all pools with addtional details for each of them\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @return Arrays of all Venus pools' data\n */\n function getAllPools(address poolRegistryAddress) external view returns (PoolData[] memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n PoolRegistry.VenusPool[] memory venusPools = poolRegistryInterface.getAllPools();\n uint256 poolLength = venusPools.length;\n\n PoolData[] memory poolDataItems = new PoolData[](poolLength);\n\n for (uint256 i; i < poolLength; ++i) {\n PoolRegistry.VenusPool memory venusPool = venusPools[i];\n PoolData memory poolData = getPoolDataFromVenusPool(poolRegistryAddress, venusPool);\n poolDataItems[i] = poolData;\n }\n\n return poolDataItems;\n }\n\n /**\n * @notice Queries the details of a pool identified by Comptroller address\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param comptroller The Comptroller implementation address\n * @return PoolData structure containing the details of the pool\n */\n function getPoolByComptroller(\n address poolRegistryAddress,\n address comptroller\n ) external view returns (PoolData memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return getPoolDataFromVenusPool(poolRegistryAddress, poolRegistryInterface.getPoolByComptroller(comptroller));\n }\n\n /**\n * @notice Returns vToken holding the specified underlying asset in the specified pool\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param comptroller The pool comptroller\n * @param asset The underlyingAsset of VToken\n * @return Address of the vToken\n */\n function getVTokenForAsset(\n address poolRegistryAddress,\n address comptroller,\n address asset\n ) external view returns (address) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return poolRegistryInterface.getVTokenForAsset(comptroller, asset);\n }\n\n /**\n * @notice Returns all pools that support the specified underlying asset\n * @param poolRegistryAddress The address of the PoolRegistry contract\n * @param asset The underlying asset of vToken\n * @return A list of Comptroller contracts\n */\n function getPoolsSupportedByAsset(\n address poolRegistryAddress,\n address asset\n ) external view returns (address[] memory) {\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n return poolRegistryInterface.getPoolsSupportedByAsset(asset);\n }\n\n /**\n * @notice Returns the price data for the underlying assets of the specified vTokens\n * @param vTokens The list of vToken addresses\n * @return An array containing the price data for each asset\n */\n function vTokenUnderlyingPriceAll(\n VToken[] calldata vTokens\n ) external view returns (VTokenUnderlyingPrice[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenUnderlyingPrice[] memory res = new VTokenUnderlyingPrice[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenUnderlyingPrice(vTokens[i]);\n }\n return res;\n }\n\n /**\n * @notice Returns the pending rewards for a user for a given pool.\n * @param account The user account.\n * @param comptrollerAddress address\n * @return Pending rewards array\n */\n function getPendingRewards(\n address account,\n address comptrollerAddress\n ) external view returns (RewardSummary[] memory) {\n VToken[] memory markets = _getMarkets(ComptrollerInterface(comptrollerAddress));\n RewardsDistributor[] memory rewardsDistributors = ComptrollerViewInterface(comptrollerAddress)\n .getRewardDistributors();\n RewardSummary[] memory rewardSummary = new RewardSummary[](rewardsDistributors.length);\n for (uint256 i; i < rewardsDistributors.length; ++i) {\n RewardSummary memory reward;\n reward.distributorAddress = address(rewardsDistributors[i]);\n reward.rewardTokenAddress = address(rewardsDistributors[i].rewardToken());\n reward.totalRewards = rewardsDistributors[i].rewardTokenAccrued(account);\n reward.pendingRewards = _calculateNotDistributedAwards(account, markets, rewardsDistributors[i]);\n rewardSummary[i] = reward;\n }\n return rewardSummary;\n }\n\n /**\n * @notice Returns a summary of a pool's bad debt broken down by market\n *\n * @param comptrollerAddress Address of the comptroller\n *\n * @return badDebtSummary A struct with comptroller address, total bad debut denominated in usd, and\n * a break down of bad debt by market\n */\n function getPoolBadDebt(address comptrollerAddress) external view returns (BadDebtSummary memory) {\n uint256 totalBadDebtUsd;\n\n // Get every listed market in the pool\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\n VToken[] memory markets = _getMarkets(ComptrollerInterface(comptrollerAddress));\n ResilientOracleInterface priceOracle = comptroller.oracle();\n\n BadDebt[] memory badDebts = new BadDebt[](markets.length);\n\n BadDebtSummary memory badDebtSummary;\n badDebtSummary.comptroller = comptrollerAddress;\n badDebtSummary.badDebts = badDebts;\n\n // // Calculate the bad debt is USD per market\n for (uint256 i; i < markets.length; ++i) {\n BadDebt memory badDebt;\n badDebt.vTokenAddress = address(markets[i]);\n badDebt.badDebtUsd =\n (VToken(address(markets[i])).badDebt() * priceOracle.getUnderlyingPrice(address(markets[i]))) /\n EXP_SCALE;\n badDebtSummary.badDebts[i] = badDebt;\n totalBadDebtUsd = totalBadDebtUsd + badDebt.badDebtUsd;\n }\n\n badDebtSummary.totalBadDebtUsd = totalBadDebtUsd;\n\n return badDebtSummary;\n }\n\n /**\n * @notice Queries the user's supply/borrow balances in the specified vToken\n * @param vToken vToken address\n * @param account The user Account\n * @return A struct containing the balances data\n */\n function vTokenBalances(VToken vToken, address account) public returns (VTokenBalances memory) {\n uint256 balanceOf = vToken.balanceOf(account);\n uint256 borrowBalanceCurrent = vToken.borrowBalanceCurrent(account);\n uint256 balanceOfUnderlying = vToken.balanceOfUnderlying(account);\n uint256 tokenBalance;\n uint256 tokenAllowance;\n\n IERC20 underlying = IERC20(vToken.underlying());\n tokenBalance = underlying.balanceOf(account);\n tokenAllowance = underlying.allowance(account, address(vToken));\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 Queries additional information for the pool\n * @param poolRegistryAddress Address of the PoolRegistry\n * @param venusPool The VenusPool Object from PoolRegistry\n * @return Enriched PoolData\n */\n function getPoolDataFromVenusPool(\n address poolRegistryAddress,\n PoolRegistry.VenusPool memory venusPool\n ) public view returns (PoolData memory) {\n // Get tokens in the Pool\n ComptrollerInterface comptrollerInstance = ComptrollerInterface(venusPool.comptroller);\n\n VToken[] memory vTokens = _getMarkets(comptrollerInstance);\n\n VTokenMetadata[] memory vTokenMetadataItems = vTokenMetadataAll(vTokens);\n\n PoolRegistryInterface poolRegistryInterface = PoolRegistryInterface(poolRegistryAddress);\n\n PoolRegistry.VenusPoolMetaData memory venusPoolMetaData = poolRegistryInterface.getVenusPoolMetadata(\n venusPool.comptroller\n );\n\n ComptrollerViewInterface comptrollerViewInstance = ComptrollerViewInterface(venusPool.comptroller);\n\n PoolData memory poolData = PoolData({\n name: venusPool.name,\n creator: venusPool.creator,\n comptroller: venusPool.comptroller,\n blockPosted: venusPool.blockPosted,\n timestampPosted: venusPool.timestampPosted,\n category: venusPoolMetaData.category,\n logoURL: venusPoolMetaData.logoURL,\n description: venusPoolMetaData.description,\n vTokens: vTokenMetadataItems,\n priceOracle: address(comptrollerViewInstance.oracle()),\n closeFactor: comptrollerViewInstance.closeFactorMantissa(),\n liquidationIncentive: comptrollerViewInstance.liquidationIncentiveMantissa(),\n minLiquidatableCollateral: comptrollerViewInstance.minLiquidatableCollateral()\n });\n\n return poolData;\n }\n\n /**\n * @notice Returns the metadata of VToken\n * @param vToken The address of vToken\n * @return VTokenMetadata struct\n */\n function vTokenMetadata(VToken vToken) public view returns (VTokenMetadata memory) {\n uint256 exchangeRateCurrent = vToken.exchangeRateStored();\n address comptrollerAddress = address(vToken.comptroller());\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(comptrollerAddress);\n (bool isListed, uint256 collateralFactorMantissa) = comptroller.markets(address(vToken));\n\n address underlyingAssetAddress = vToken.underlying();\n uint256 underlyingDecimals = IERC20Metadata(underlyingAssetAddress).decimals();\n\n uint256 pausedActions;\n for (uint8 i; i <= uint8(type(Action).max); ++i) {\n uint256 paused = ComptrollerInterface(comptrollerAddress).actionPaused(address(vToken), Action(i)) ? 1 : 0;\n pausedActions |= paused << i;\n }\n\n uint256 supplyRatePerBlock;\n\n if (vToken.totalSupply() > 0) {\n supplyRatePerBlock = vToken.supplyRatePerBlock();\n }\n\n return\n VTokenMetadata({\n vToken: address(vToken),\n exchangeRateCurrent: exchangeRateCurrent,\n supplyRatePerBlockOrTimestamp: supplyRatePerBlock,\n borrowRatePerBlockOrTimestamp: vToken.borrowRatePerBlock(),\n reserveFactorMantissa: vToken.reserveFactorMantissa(),\n supplyCaps: comptroller.supplyCaps(address(vToken)),\n borrowCaps: comptroller.borrowCaps(address(vToken)),\n totalBorrows: vToken.totalBorrows(),\n totalReserves: vToken.totalReserves(),\n totalSupply: vToken.totalSupply(),\n totalCash: vToken.getCash(),\n isListed: isListed,\n collateralFactorMantissa: collateralFactorMantissa,\n underlyingAssetAddress: underlyingAssetAddress,\n vTokenDecimals: vToken.decimals(),\n underlyingDecimals: underlyingDecimals,\n pausedActions: pausedActions\n });\n }\n\n /**\n * @notice Returns the metadata of all VTokens\n * @param vTokens The list of vToken addresses\n * @return An array of VTokenMetadata structs\n */\n function vTokenMetadataAll(VToken[] memory vTokens) public view returns (VTokenMetadata[] memory) {\n uint256 vTokenCount = vTokens.length;\n VTokenMetadata[] memory res = new VTokenMetadata[](vTokenCount);\n for (uint256 i; i < vTokenCount; ++i) {\n res[i] = vTokenMetadata(vTokens[i]);\n }\n return res;\n }\n\n /**\n * @notice Returns the price data for the underlying asset of the specified vToken\n * @param vToken vToken address\n * @return The price data for each asset\n */\n function vTokenUnderlyingPrice(VToken vToken) public view returns (VTokenUnderlyingPrice memory) {\n ComptrollerViewInterface comptroller = ComptrollerViewInterface(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 Returns markets from a comptroller. For the core pool, all markets are returned.\n * For other pools, markets with zero internalCash are filtered.\n * @param comptroller The comptroller to query\n * @return An array of VToken addresses\n */\n function _getMarkets(ComptrollerInterface comptroller) internal view returns (VToken[] memory) {\n VToken[] memory allMarkets = comptroller.getAllMarkets();\n\n if (address(comptroller) == corePoolComptroller) {\n return allMarkets;\n }\n\n // Single-loop filter: pack active markets to the front of allMarkets\n uint256 count;\n uint256 len = allMarkets.length;\n for (uint256 i; i < len; ++i) {\n if (allMarkets[i].internalCash() > 0) {\n allMarkets[count] = allMarkets[i];\n ++count;\n }\n }\n\n // Trim the array to the active count\n assembly {\n mstore(allMarkets, count)\n }\n\n return allMarkets;\n }\n\n function _calculateNotDistributedAwards(\n address account,\n VToken[] memory markets,\n RewardsDistributor rewardsDistributor\n ) internal view returns (PendingReward[] memory) {\n PendingReward[] memory pendingRewards = new PendingReward[](markets.length);\n\n for (uint256 i; i < markets.length; ++i) {\n // Market borrow and supply state we will modify update in-memory, in order to not modify storage\n RewardTokenState memory borrowState;\n RewardTokenState memory supplyState;\n\n if (isTimeBased) {\n (\n borrowState.index,\n borrowState.blockOrTimestamp,\n borrowState.lastRewardingBlockOrTimestamp\n ) = rewardsDistributor.rewardTokenBorrowStateTimeBased(address(markets[i]));\n (\n supplyState.index,\n supplyState.blockOrTimestamp,\n supplyState.lastRewardingBlockOrTimestamp\n ) = rewardsDistributor.rewardTokenSupplyStateTimeBased(address(markets[i]));\n } else {\n (\n borrowState.index,\n borrowState.blockOrTimestamp,\n borrowState.lastRewardingBlockOrTimestamp\n ) = rewardsDistributor.rewardTokenBorrowState(address(markets[i]));\n (\n supplyState.index,\n supplyState.blockOrTimestamp,\n supplyState.lastRewardingBlockOrTimestamp\n ) = rewardsDistributor.rewardTokenSupplyState(address(markets[i]));\n }\n\n Exp memory marketBorrowIndex = Exp({ mantissa: markets[i].borrowIndex() });\n\n // Update market supply and borrow index in-memory\n updateMarketBorrowIndex(address(markets[i]), rewardsDistributor, borrowState, marketBorrowIndex);\n updateMarketSupplyIndex(address(markets[i]), rewardsDistributor, supplyState);\n\n // Calculate pending rewards\n uint256 borrowReward = calculateBorrowerReward(\n address(markets[i]),\n rewardsDistributor,\n account,\n borrowState,\n marketBorrowIndex\n );\n uint256 supplyReward = calculateSupplierReward(\n address(markets[i]),\n rewardsDistributor,\n account,\n supplyState\n );\n\n PendingReward memory pendingReward;\n pendingReward.vTokenAddress = address(markets[i]);\n pendingReward.amount = borrowReward + supplyReward;\n pendingRewards[i] = pendingReward;\n }\n return pendingRewards;\n }\n\n function updateMarketBorrowIndex(\n address vToken,\n RewardsDistributor rewardsDistributor,\n RewardTokenState memory borrowState,\n Exp memory marketBorrowIndex\n ) internal view {\n uint256 borrowSpeed = rewardsDistributor.rewardTokenBorrowSpeeds(vToken);\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n if (\n borrowState.lastRewardingBlockOrTimestamp > 0 &&\n blockNumberOrTimestamp > borrowState.lastRewardingBlockOrTimestamp\n ) {\n blockNumberOrTimestamp = borrowState.lastRewardingBlockOrTimestamp;\n }\n\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, borrowState.blockOrTimestamp);\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\n // Remove the total earned interest rate since the opening of the market from total borrows\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, borrowSpeed);\n Double memory ratio = borrowAmount > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\n } else if (deltaBlocksOrTimestamp > 0) {\n borrowState.blockOrTimestamp = blockNumberOrTimestamp;\n }\n }\n\n function updateMarketSupplyIndex(\n address vToken,\n RewardsDistributor rewardsDistributor,\n RewardTokenState memory supplyState\n ) internal view {\n uint256 supplySpeed = rewardsDistributor.rewardTokenSupplySpeeds(vToken);\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n if (\n supplyState.lastRewardingBlockOrTimestamp > 0 &&\n blockNumberOrTimestamp > supplyState.lastRewardingBlockOrTimestamp\n ) {\n blockNumberOrTimestamp = supplyState.lastRewardingBlockOrTimestamp;\n }\n\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, supplyState.blockOrTimestamp);\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\n uint256 supplyTokens = VToken(vToken).totalSupply();\n uint256 tokensAccrued = mul_(deltaBlocksOrTimestamp, supplySpeed);\n Double memory ratio = supplyTokens > 0 ? fraction(tokensAccrued, 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.blockOrTimestamp = blockNumberOrTimestamp;\n } else if (deltaBlocksOrTimestamp > 0) {\n supplyState.blockOrTimestamp = blockNumberOrTimestamp;\n }\n }\n\n function calculateBorrowerReward(\n address vToken,\n RewardsDistributor rewardsDistributor,\n address borrower,\n RewardTokenState memory borrowState,\n Exp memory marketBorrowIndex\n ) internal view returns (uint256) {\n Double memory borrowIndex = Double({ mantissa: borrowState.index });\n Double memory borrowerIndex = Double({\n mantissa: rewardsDistributor.rewardTokenBorrowerIndex(vToken, borrower)\n });\n if (borrowerIndex.mantissa == 0 && borrowIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\n // Covers the case where users borrowed tokens before the market's borrow state index was set\n borrowerIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\n }\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\n return borrowerDelta;\n }\n\n function calculateSupplierReward(\n address vToken,\n RewardsDistributor rewardsDistributor,\n address supplier,\n RewardTokenState memory supplyState\n ) internal view returns (uint256) {\n Double memory supplyIndex = Double({ mantissa: supplyState.index });\n Double memory supplierIndex = Double({\n mantissa: rewardsDistributor.rewardTokenSupplierIndex(vToken, supplier)\n });\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa >= rewardsDistributor.INITIAL_INDEX()) {\n // Covers the case where users supplied tokens before the market's supply state index was set\n supplierIndex.mantissa = rewardsDistributor.INITIAL_INDEX();\n }\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\n return supplierDelta;\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\nlibrary ApproveOrRevert {\n /// @notice Thrown if a contract is unable to approve a transfer\n error 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\n function approveOrRevert(IERC20Upgradeable token, address spender, uint256 amount) internal {\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}\n" + }, + "contracts/lib/constants.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\n/// @dev The approximate number of seconds per year\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\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" + }, + "contracts/lib/TokenDebtTracker.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.25;\n\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\n\n/**\n * @title TokenDebtTracker\n * @author Venus\n * @notice TokenDebtTracker is an abstract contract that handles transfers _out_ of the inheriting contract.\n * If there is an error transferring out (due to any reason, e.g. the token contract restricted the user from\n * receiving incoming transfers), the amount is recorded as a debt that can be claimed later.\n * @dev Note that the inheriting contract keeps some amount of users' tokens on its balance, so be careful when\n * using balanceOf(address(this))!\n */\nabstract contract TokenDebtTracker is Initializable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /**\n * @notice Mapping (IERC20Upgradeable token => (address user => uint256 amount)).\n * Tracks failed transfers: when a token transfer fails, we record the\n * amount of the transfer, so that the user can redeem this debt later.\n */\n mapping(IERC20Upgradeable => mapping(address => uint256)) public tokenDebt;\n\n /**\n * @notice Mapping (IERC20Upgradeable token => uint256 amount) shows how many\n * tokens the contract owes to all users. This is useful for accounting to\n * understand how much of balanceOf(address(this)) is already owed to users.\n */\n mapping(IERC20Upgradeable => uint256) public totalTokenDebt;\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 /**\n * @notice Emitted when the contract's debt to the user is increased due to a failed transfer\n * @param token Token address\n * @param user User address\n * @param amount The amount of debt added\n */\n event TokenDebtAdded(address indexed token, address indexed user, uint256 amount);\n\n /**\n * @notice Emitted when a user claims tokens that the contract owes them\n * @param token Token address\n * @param user User address\n * @param amount The amount transferred\n */\n event TokenDebtClaimed(address indexed token, address indexed user, uint256 amount);\n\n /**\n * @notice Thrown if the user tries to claim more tokens than they are owed\n * @param token The token the user is trying to claim\n * @param owedAmount The amount of tokens the contract owes to the user\n * @param amount The amount of tokens the user is trying to claim\n */\n error InsufficientDebt(address token, address user, uint256 owedAmount, uint256 amount);\n\n /**\n * @notice Thrown if trying to transfer more tokens than the contract currently has\n * @param token The token the contract is trying to transfer\n * @param recipient The recipient of the transfer\n * @param amount The amount of tokens the contract is trying to transfer\n * @param availableBalance The amount of tokens the contract currently has\n */\n error InsufficientBalance(address token, address recipient, uint256 amount, uint256 availableBalance);\n\n /**\n * @notice Transfers the tokens we owe to msg.sender, if any\n * @param token The token to claim\n * @param amount_ The amount of tokens to claim (or max uint256 to claim all)\n * @custom:error InsufficientDebt The contract doesn't have enough debt to the user\n */\n function claimTokenDebt(IERC20Upgradeable token, uint256 amount_) external {\n uint256 owedAmount = tokenDebt[token][msg.sender];\n uint256 amount = (amount_ == type(uint256).max ? owedAmount : amount_);\n if (amount > owedAmount) {\n revert InsufficientDebt(address(token), msg.sender, owedAmount, amount);\n }\n unchecked {\n // Safe because we revert if amount > owedAmount above\n tokenDebt[token][msg.sender] = owedAmount - amount;\n }\n totalTokenDebt[token] -= amount;\n emit TokenDebtClaimed(address(token), msg.sender, amount);\n token.safeTransfer(msg.sender, amount);\n }\n\n // solhint-disable-next-line func-name-mixedcase\n function __TokenDebtTracker_init() internal onlyInitializing {\n __TokenDebtTracker_init_unchained();\n }\n\n // solhint-disable-next-line func-name-mixedcase, no-empty-blocks\n function __TokenDebtTracker_init_unchained() internal onlyInitializing {}\n\n /**\n * @dev Transfers tokens to the recipient if the contract has enough balance, or\n * records the debt if the transfer fails due to reasons unrelated to the contract's\n * balance (e.g. if the token forbids transfers to the recipient).\n * @param token The token to transfer\n * @param to The recipient of the transfer\n * @param amount The amount to transfer\n * @custom:error InsufficientBalance The contract doesn't have enough balance to transfer\n */\n function _transferOutOrTrackDebt(IERC20Upgradeable token, address to, uint256 amount) internal {\n uint256 balance = token.balanceOf(address(this));\n if (balance < amount) {\n revert InsufficientBalance(address(token), address(this), amount, balance);\n }\n _transferOutOrTrackDebtSkippingBalanceCheck(token, to, amount);\n }\n\n /**\n * @dev Transfers tokens to the recipient, or records the debt if the transfer fails\n * due to any reason, including insufficient balance.\n * @param token The token to transfer\n * @param to The recipient of the transfer\n * @param amount The amount to transfer\n */\n function _transferOutOrTrackDebtSkippingBalanceCheck(IERC20Upgradeable token, address to, uint256 amount) internal {\n // We can't use safeTransfer here because we can't try-catch internal calls\n bool success = _tryTransferOut(token, to, amount);\n if (!success) {\n tokenDebt[token][to] += amount;\n totalTokenDebt[token] += amount;\n emit TokenDebtAdded(address(token), to, amount);\n }\n }\n\n /**\n * @dev Either transfers tokens to the recepient or returns false. Supports tokens\n * thet revert or return false to indicate failure, and the non-compliant ones\n * that do not return any value.\n * @param token The token to transfer\n * @param to The recipient of the transfer\n * @param amount The amount to transfer\n * @return true if the transfer succeeded, false otherwise\n */\n function _tryTransferOut(IERC20Upgradeable token, address to, uint256 amount) private returns (bool) {\n bytes memory callData = abi.encodeCall(token.transfer, (to, amount));\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = address(token).call(callData);\n return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;\n }\n}\n" + }, + "contracts/lib/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 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" + }, + "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" + }, + "contracts/Pool/PoolRegistry.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\n\nimport { PoolRegistryInterface } from \"./PoolRegistryInterface.sol\";\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { ensureNonzeroAddress } from \"../lib/validators.sol\";\n\n/**\n * @title PoolRegistry\n * @author Venus\n * @notice The Isolated Pools architecture centers around the `PoolRegistry` contract. The `PoolRegistry` maintains a directory of isolated lending\n * pools and can perform actions like creating and registering new pools, adding new markets to existing pools, setting and updating the pool's required\n * metadata, and providing the getter methods to get information on the pools.\n *\n * Isolated lending has three main components: PoolRegistry, pools, and markets. The PoolRegistry is responsible for managing pools.\n * It can create new pools, update pool metadata and manage markets within pools. PoolRegistry contains getter methods to get the details of\n * any existing pool like `getVTokenForAsset` and `getPoolsSupportedByAsset`. It also contains methods for updating pool metadata (`updatePoolMetadata`)\n * and setting pool name (`setPoolName`).\n *\n * The directory of pools is managed through two mappings: `_poolByComptroller` which is a hashmap with the comptroller address as the key and `VenusPool` as\n * the value and `_poolsByID` which is an array of comptroller addresses. Individual pools can be accessed by calling `getPoolByComptroller` with the pool's\n * comptroller address. `_poolsByID` is used to iterate through all of the pools.\n *\n * PoolRegistry also contains a map of asset addresses called `_supportedPools` that maps to an array of assets suppored by each pool. This array of pools by\n * asset is retrieved by calling `getPoolsSupportedByAsset`.\n *\n * PoolRegistry registers new isolated pools in the directory with the `createRegistryPool` method. Isolated pools are composed of independent markets with\n * specific assets and custom risk management configurations according to their markets.\n */\ncontract PoolRegistry is Ownable2StepUpgradeable, AccessControlledV8, PoolRegistryInterface {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n struct AddMarketInput {\n VToken vToken;\n uint256 collateralFactor;\n uint256 liquidationThreshold;\n uint256 initialSupply;\n address vTokenReceiver;\n uint256 supplyCap;\n uint256 borrowCap;\n }\n\n uint256 internal constant MAX_POOL_NAME_LENGTH = 100;\n\n /**\n * @notice Maps pool's comptroller address to metadata.\n */\n mapping(address => VenusPoolMetaData) public metadata;\n\n /**\n * @dev Maps pool ID to pool's comptroller address\n */\n mapping(uint256 => address) private _poolsByID;\n\n /**\n * @dev Total number of pools created.\n */\n uint256 private _numberOfPools;\n\n /**\n * @dev Maps comptroller address to Venus pool Index.\n */\n mapping(address => VenusPool) private _poolByComptroller;\n\n /**\n * @dev Maps pool's comptroller address to asset to vToken.\n */\n mapping(address => mapping(address => address)) private _vTokens;\n\n /**\n * @dev Maps asset to list of supported pools.\n */\n mapping(address => address[]) private _supportedPools;\n\n /**\n * @notice Emitted when a new Venus pool is added to the directory.\n */\n event PoolRegistered(address indexed comptroller, VenusPool pool);\n\n /**\n * @notice Emitted when a pool name is set.\n */\n event PoolNameSet(address indexed comptroller, string oldName, string newName);\n\n /**\n * @notice Emitted when a pool metadata is updated.\n */\n event PoolMetadataUpdated(\n address indexed comptroller,\n VenusPoolMetaData oldMetadata,\n VenusPoolMetaData newMetadata\n );\n\n /**\n * @notice Emitted when a Market is added to the pool.\n */\n event MarketAdded(address indexed comptroller, address indexed vTokenAddress);\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor() {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the deployer to owner\n * @param accessControlManager_ AccessControlManager contract address\n */\n function initialize(address accessControlManager_) external initializer {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n }\n\n /**\n * @notice Adds a new Venus pool to the directory\n * @dev Price oracle must be configured before adding a pool\n * @param name The name of the pool\n * @param comptroller Pool's Comptroller contract\n * @param closeFactor The pool's close factor (scaled by 1e18)\n * @param liquidationIncentive The pool's liquidation incentive (scaled by 1e18)\n * @param minLiquidatableCollateral Minimal collateral for regular (non-batch) liquidations flow\n * @return index The index of the registered Venus pool\n * @custom:error ZeroAddressNotAllowed is thrown when Comptroller address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when price oracle address is zero\n */\n function addPool(\n string calldata name,\n Comptroller comptroller,\n uint256 closeFactor,\n uint256 liquidationIncentive,\n uint256 minLiquidatableCollateral\n ) external virtual returns (uint256 index) {\n _checkAccessAllowed(\"addPool(string,address,uint256,uint256,uint256)\");\n // Input validation\n ensureNonzeroAddress(address(comptroller));\n ensureNonzeroAddress(address(comptroller.oracle()));\n\n uint256 poolId = _registerPool(name, address(comptroller));\n\n // Set Venus pool parameters\n comptroller.setCloseFactor(closeFactor);\n comptroller.setLiquidationIncentive(liquidationIncentive);\n comptroller.setMinLiquidatableCollateral(minLiquidatableCollateral);\n\n return poolId;\n }\n\n /**\n * @notice Add a market to an existing pool and then mint to provide initial supply\n * @param input The structure describing the parameters for adding a market to a pool\n * @custom:error ZeroAddressNotAllowed is thrown when vToken address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when vTokenReceiver address is zero\n */\n function addMarket(AddMarketInput memory input) external {\n _checkAccessAllowed(\"addMarket(AddMarketInput)\");\n ensureNonzeroAddress(address(input.vToken));\n ensureNonzeroAddress(input.vTokenReceiver);\n require(input.initialSupply > 0, \"PoolRegistry: initialSupply is zero\");\n\n VToken vToken = input.vToken;\n address vTokenAddress = address(vToken);\n address comptrollerAddress = address(vToken.comptroller());\n Comptroller comptroller = Comptroller(comptrollerAddress);\n address underlyingAddress = vToken.underlying();\n IERC20Upgradeable underlying = IERC20Upgradeable(underlyingAddress);\n\n require(_poolByComptroller[comptrollerAddress].creator != address(0), \"PoolRegistry: Pool not registered\");\n // solhint-disable-next-line reason-string\n require(\n _vTokens[comptrollerAddress][underlyingAddress] == address(0),\n \"PoolRegistry: Market already added for asset comptroller combination\"\n );\n\n comptroller.supportMarket(vToken);\n comptroller.setCollateralFactor(vToken, input.collateralFactor, input.liquidationThreshold);\n\n uint256[] memory newSupplyCaps = new uint256[](1);\n uint256[] memory newBorrowCaps = new uint256[](1);\n VToken[] memory vTokens = new VToken[](1);\n\n newSupplyCaps[0] = input.supplyCap;\n newBorrowCaps[0] = input.borrowCap;\n vTokens[0] = vToken;\n\n comptroller.setMarketSupplyCaps(vTokens, newSupplyCaps);\n comptroller.setMarketBorrowCaps(vTokens, newBorrowCaps);\n\n _vTokens[comptrollerAddress][underlyingAddress] = vTokenAddress;\n _supportedPools[underlyingAddress].push(comptrollerAddress);\n\n uint256 amountToSupply = _transferIn(underlying, msg.sender, input.initialSupply);\n underlying.forceApprove(vTokenAddress, 0);\n underlying.forceApprove(vTokenAddress, amountToSupply);\n vToken.mintBehalf(input.vTokenReceiver, amountToSupply);\n\n emit MarketAdded(comptrollerAddress, vTokenAddress);\n }\n\n /**\n * @notice Modify existing Venus pool name\n * @param comptroller Pool's Comptroller\n * @param name New pool name\n */\n function setPoolName(address comptroller, string calldata name) external {\n _checkAccessAllowed(\"setPoolName(address,string)\");\n _ensureValidName(name);\n VenusPool storage pool = _poolByComptroller[comptroller];\n string memory oldName = pool.name;\n pool.name = name;\n emit PoolNameSet(comptroller, oldName, name);\n }\n\n /**\n * @notice Update metadata of an existing pool\n * @param comptroller Pool's Comptroller\n * @param metadata_ New pool metadata\n */\n function updatePoolMetadata(address comptroller, VenusPoolMetaData calldata metadata_) external {\n _checkAccessAllowed(\"updatePoolMetadata(address,VenusPoolMetaData)\");\n VenusPoolMetaData memory oldMetadata = metadata[comptroller];\n metadata[comptroller] = metadata_;\n emit PoolMetadataUpdated(comptroller, oldMetadata, metadata_);\n }\n\n /**\n * @notice Returns arrays of all Venus pools' data\n * @dev This function is not designed to be called in a transaction: it is too gas-intensive\n * @return A list of all pools within PoolRegistry, with details for each pool\n */\n function getAllPools() external view override returns (VenusPool[] memory) {\n uint256 numberOfPools_ = _numberOfPools; // storage load to save gas\n VenusPool[] memory _pools = new VenusPool[](numberOfPools_);\n for (uint256 i = 1; i <= numberOfPools_; ++i) {\n address comptroller = _poolsByID[i];\n _pools[i - 1] = (_poolByComptroller[comptroller]);\n }\n return _pools;\n }\n\n /**\n * @param comptroller The comptroller proxy address associated to the pool\n * @return Returns Venus pool\n */\n function getPoolByComptroller(address comptroller) external view override returns (VenusPool memory) {\n return _poolByComptroller[comptroller];\n }\n\n /**\n * @param comptroller comptroller of Venus pool\n * @return Returns Metadata of Venus pool\n */\n function getVenusPoolMetadata(address comptroller) external view override returns (VenusPoolMetaData memory) {\n return metadata[comptroller];\n }\n\n function getVTokenForAsset(address comptroller, address asset) external view override returns (address) {\n return _vTokens[comptroller][asset];\n }\n\n function getPoolsSupportedByAsset(address asset) external view override returns (address[] memory) {\n return _supportedPools[asset];\n }\n\n /**\n * @dev Adds a new Venus pool to the directory (without checking msg.sender).\n * @param name The name of the pool\n * @param comptroller The pool's Comptroller proxy contract address\n * @return The index of the registered Venus pool\n */\n function _registerPool(string calldata name, address comptroller) internal returns (uint256) {\n VenusPool storage storedPool = _poolByComptroller[comptroller];\n\n require(storedPool.creator == address(0), \"PoolRegistry: Pool already exists in the directory.\");\n _ensureValidName(name);\n\n ++_numberOfPools;\n uint256 numberOfPools_ = _numberOfPools; // cache on stack to save storage read gas\n\n VenusPool memory pool = VenusPool(name, msg.sender, comptroller, block.number, block.timestamp);\n\n _poolsByID[numberOfPools_] = comptroller;\n _poolByComptroller[comptroller] = pool;\n\n emit PoolRegistered(comptroller, pool);\n return numberOfPools_;\n }\n\n function _transferIn(IERC20Upgradeable token, address from, uint256 amount) internal returns (uint256) {\n uint256 balanceBefore = token.balanceOf(address(this));\n token.safeTransferFrom(from, address(this), amount);\n uint256 balanceAfter = token.balanceOf(address(this));\n return balanceAfter - balanceBefore;\n }\n\n function _ensureValidName(string calldata name) internal pure {\n require(bytes(name).length <= MAX_POOL_NAME_LENGTH, \"Pool's name is too large\");\n }\n}\n" + }, + "contracts/Pool/PoolRegistryInterface.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 /**\n * @notice Struct for a Venus interest rate pool metadata.\n */\n struct VenusPoolMetaData {\n string category;\n string logoURL;\n string description;\n }\n\n /// @notice Get all pools in PoolRegistry\n function getAllPools() external view returns (VenusPool[] memory);\n\n /// @notice Get a pool by comptroller address\n function getPoolByComptroller(address comptroller) external view returns (VenusPool memory);\n\n /// @notice Get the address of the VToken contract in the Pool where the underlying token is the provided 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 /// @notice Get the metadata of a Pool by comptroller address\n function getVenusPoolMetadata(address comptroller) external view returns (VenusPoolMetaData memory);\n}\n" + }, + "contracts/Rewards/RewardsDistributor.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\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 { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { TimeManagerV8 } from \"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\";\n\nimport { ExponentialNoError } from \"../ExponentialNoError.sol\";\nimport { VToken } from \"../VToken.sol\";\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { MaxLoopsLimitHelper } from \"../MaxLoopsLimitHelper.sol\";\nimport { RewardsDistributorStorage } from \"./RewardsDistributorStorage.sol\";\n\n/**\n * @title `RewardsDistributor`\n * @author Venus\n * @notice Contract used to configure, track and distribute rewards to users based on their actions (borrows and supplies) in the protocol.\n * Users can receive additional rewards through a `RewardsDistributor`. Each `RewardsDistributor` proxy is initialized with a specific reward\n * token and `Comptroller`, which can then distribute the reward token to users that supply or borrow in the associated pool.\n * Authorized users can set the reward token borrow and supply speeds for each market in the pool. This sets a fixed amount of reward\n * token to be released each slot (block or second) for borrowers and suppliers, which is distributed based on a user’s percentage of the borrows or supplies\n * respectively. The owner can also set up reward distributions to contributor addresses (distinct from suppliers and borrowers) by setting\n * their contributor reward token speed, which similarly allocates a fixed amount of reward token per slot (block or second).\n *\n * The owner has the ability to transfer any amount of reward tokens held by the contract to any other address. Rewards are not distributed\n * automatically and must be claimed by a user calling `claimRewardToken()`. Users should be aware that it is up to the owner and other centralized\n * entities to ensure that the `RewardsDistributor` holds enough tokens to distribute the accumulated rewards of users and contributors.\n */\ncontract RewardsDistributor is\n ExponentialNoError,\n Ownable2StepUpgradeable,\n AccessControlledV8,\n MaxLoopsLimitHelper,\n RewardsDistributorStorage,\n TimeManagerV8\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice The initial REWARD TOKEN index for a market\n uint224 public constant INITIAL_INDEX = 1e36;\n\n /// @notice Emitted when REWARD TOKEN is distributed to a supplier\n event DistributedSupplierRewardToken(\n VToken indexed vToken,\n address indexed supplier,\n uint256 rewardTokenDelta,\n uint256 rewardTokenTotal,\n uint256 rewardTokenSupplyIndex\n );\n\n /// @notice Emitted when REWARD TOKEN is distributed to a borrower\n event DistributedBorrowerRewardToken(\n VToken indexed vToken,\n address indexed borrower,\n uint256 rewardTokenDelta,\n uint256 rewardTokenTotal,\n uint256 rewardTokenBorrowIndex\n );\n\n /// @notice Emitted when a new supply-side REWARD TOKEN speed is calculated for a market\n event RewardTokenSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /// @notice Emitted when a new borrow-side REWARD TOKEN speed is calculated for a market\n event RewardTokenBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /// @notice Emitted when REWARD TOKEN is granted by admin\n event RewardTokenGranted(address indexed recipient, uint256 amount);\n\n /// @notice Emitted when a new REWARD TOKEN speed is set for a contributor\n event ContributorRewardTokenSpeedUpdated(address indexed contributor, uint256 newSpeed);\n\n /// @notice Emitted when a market is initialized\n event MarketInitialized(address indexed vToken);\n\n /// @notice Emitted when a reward token supply index is updated\n event RewardTokenSupplyIndexUpdated(address indexed vToken);\n\n /// @notice Emitted when a reward token borrow index is updated\n event RewardTokenBorrowIndexUpdated(address indexed vToken, Exp marketBorrowIndex);\n\n /// @notice Emitted when a reward for contributor is updated\n event ContributorRewardsUpdated(address indexed contributor, uint256 rewardAccrued);\n\n /// @notice Emitted when a reward token last rewarding block for supply is updated\n event SupplyLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\n\n /// @notice Emitted when a reward token last rewarding block for borrow is updated\n event BorrowLastRewardingBlockUpdated(address indexed vToken, uint32 newBlock);\n\n /// @notice Emitted when a reward token last rewarding timestamp for supply is updated\n event SupplyLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\n\n /// @notice Emitted when a reward token last rewarding timestamp for borrow is updated\n event BorrowLastRewardingBlockTimestampUpdated(address indexed vToken, uint256 newTimestamp);\n\n modifier onlyComptroller() {\n require(address(comptroller) == msg.sender, \"Only comptroller can call this function\");\n _;\n }\n\n /**\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\n * @param blocksPerYear_ The number of blocks per year\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor(bool timeBased_, uint256 blocksPerYear_) TimeManagerV8(timeBased_, blocksPerYear_) {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /**\n * @notice RewardsDistributor initializer\n * @dev Initializes the deployer to owner\n * @param comptroller_ Comptroller to attach the reward distributor to\n * @param rewardToken_ Reward token to distribute\n * @param loopsLimit_ Maximum number of iterations for the loops in this contract\n * @param accessControlManager_ AccessControlManager contract address\n */\n function initialize(\n Comptroller comptroller_,\n IERC20Upgradeable rewardToken_,\n uint256 loopsLimit_,\n address accessControlManager_\n ) external initializer {\n comptroller = comptroller_;\n rewardToken = rewardToken_;\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n\n _setMaxLoopsLimit(loopsLimit_);\n }\n\n /**\n * @notice Initializes the market state for a specific vToken\n * @param vToken The address of the vToken to be initialized\n * @custom:event MarketInitialized emits on success\n * @custom:access Only Comptroller\n */\n function initializeMarket(address vToken) external onlyComptroller {\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n isTimeBased\n ? _initializeMarketTimestampBased(vToken, blockNumberOrTimestamp)\n : _initializeMarketBlockBased(vToken, safe32(blockNumberOrTimestamp, \"block number exceeds 32 bits\"));\n\n emit MarketInitialized(vToken);\n }\n\n /*** Reward Token Distribution ***/\n\n /**\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them\n * Borrowers will begin to accrue after the first interaction with the protocol.\n * @dev This function should only be called when the user has a borrow position in the market\n * (e.g. Comptroller.preBorrowHook, and Comptroller.preRepayHook)\n * We avoid an external call to check if they are in the market to save gas because this function is called in many places\n * @param vToken The market in which the borrower is interacting\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\n * @param marketBorrowIndex The current global borrow index of vToken\n */\n function distributeBorrowerRewardToken(\n address vToken,\n address borrower,\n Exp memory marketBorrowIndex\n ) external onlyComptroller {\n _distributeBorrowerRewardToken(vToken, borrower, marketBorrowIndex);\n }\n\n function updateRewardTokenSupplyIndex(address vToken) external onlyComptroller {\n _updateRewardTokenSupplyIndex(vToken);\n }\n\n /**\n * @notice Transfer REWARD TOKEN to the recipient\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all\n * @param recipient The address of the recipient to transfer REWARD TOKEN to\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\n */\n function grantRewardToken(address recipient, uint256 amount) external onlyOwner {\n uint256 amountLeft = _grantRewardToken(recipient, amount);\n require(amountLeft == 0, \"insufficient rewardToken for grant\");\n emit RewardTokenGranted(recipient, amount);\n }\n\n function updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) external onlyComptroller {\n _updateRewardTokenBorrowIndex(vToken, marketBorrowIndex);\n }\n\n /**\n * @notice Set REWARD TOKEN borrow and supply speeds for the specified markets\n * @param vTokens The markets whose REWARD TOKEN speed to update\n * @param supplySpeeds New supply-side REWARD TOKEN speed for the corresponding market\n * @param borrowSpeeds New borrow-side REWARD TOKEN speed for the corresponding market\n */\n function setRewardTokenSpeeds(\n VToken[] memory vTokens,\n uint256[] memory supplySpeeds,\n uint256[] memory borrowSpeeds\n ) external {\n _checkAccessAllowed(\"setRewardTokenSpeeds(address[],uint256[],uint256[])\");\n uint256 numTokens = vTokens.length;\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \"invalid setRewardTokenSpeeds\");\n\n for (uint256 i; i < numTokens; ++i) {\n _setRewardTokenSpeed(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\n }\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding block for the specified markets, used when contract is block based\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\n * @param supplyLastRewardingBlocks New supply-side REWARD TOKEN last rewarding block for the corresponding market\n * @param borrowLastRewardingBlocks New borrow-side REWARD TOKEN last rewarding block for the corresponding market\n */\n function setLastRewardingBlocks(\n VToken[] calldata vTokens,\n uint32[] calldata supplyLastRewardingBlocks,\n uint32[] calldata borrowLastRewardingBlocks\n ) external {\n _checkAccessAllowed(\"setLastRewardingBlocks(address[],uint32[],uint32[])\");\n require(!isTimeBased, \"Block-based operation only\");\n\n uint256 numTokens = vTokens.length;\n require(\n numTokens == supplyLastRewardingBlocks.length && numTokens == borrowLastRewardingBlocks.length,\n \"RewardsDistributor::setLastRewardingBlocks invalid input\"\n );\n\n for (uint256 i; i < numTokens; ) {\n _setLastRewardingBlock(vTokens[i], supplyLastRewardingBlocks[i], borrowLastRewardingBlocks[i]);\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding block timestamp for the specified markets, used when contract is time based\n * @param vTokens The markets whose REWARD TOKEN last rewarding block to update\n * @param supplyLastRewardingBlockTimestamps New supply-side REWARD TOKEN last rewarding block timestamp for the corresponding market\n * @param borrowLastRewardingBlockTimestamps New borrow-side REWARD TOKEN last rewarding block timestamp for the corresponding market\n */\n function setLastRewardingBlockTimestamps(\n VToken[] calldata vTokens,\n uint256[] calldata supplyLastRewardingBlockTimestamps,\n uint256[] calldata borrowLastRewardingBlockTimestamps\n ) external {\n _checkAccessAllowed(\"setLastRewardingBlockTimestamps(address[],uint256[],uint256[])\");\n require(isTimeBased, \"Time-based operation only\");\n\n uint256 numTokens = vTokens.length;\n require(\n numTokens == supplyLastRewardingBlockTimestamps.length &&\n numTokens == borrowLastRewardingBlockTimestamps.length,\n \"RewardsDistributor::setLastRewardingBlockTimestamps invalid input\"\n );\n\n for (uint256 i; i < numTokens; ) {\n _setLastRewardingBlockTimestamp(\n vTokens[i],\n supplyLastRewardingBlockTimestamps[i],\n borrowLastRewardingBlockTimestamps[i]\n );\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Set REWARD TOKEN speed for a single contributor\n * @param contributor The contributor whose REWARD TOKEN speed to update\n * @param rewardTokenSpeed New REWARD TOKEN speed for contributor\n */\n function setContributorRewardTokenSpeed(address contributor, uint256 rewardTokenSpeed) external onlyOwner {\n // note that REWARD TOKEN speed could be set to 0 to halt liquidity rewards for a contributor\n updateContributorRewards(contributor);\n if (rewardTokenSpeed == 0) {\n // release storage\n delete lastContributorBlock[contributor];\n } else {\n lastContributorBlock[contributor] = getBlockNumberOrTimestamp();\n }\n rewardTokenContributorSpeeds[contributor] = rewardTokenSpeed;\n\n emit ContributorRewardTokenSpeedUpdated(contributor, rewardTokenSpeed);\n }\n\n function distributeSupplierRewardToken(address vToken, address supplier) external onlyComptroller {\n _distributeSupplierRewardToken(vToken, supplier);\n }\n\n /**\n * @notice Claim all the rewardToken accrued by holder in all markets\n * @param holder The address to claim REWARD TOKEN for\n */\n function claimRewardToken(address holder) external {\n return claimRewardToken(holder, comptroller.getAllMarkets());\n }\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) external onlyOwner {\n _setMaxLoopsLimit(limit);\n }\n\n /**\n * @notice Calculate additional accrued REWARD TOKEN for a contributor since last accrual\n * @param contributor The address to calculate contributor rewards for\n */\n function updateContributorRewards(address contributor) public {\n uint256 rewardTokenSpeed = rewardTokenContributorSpeeds[contributor];\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n uint256 deltaBlocksOrTimestamp = sub_(blockNumberOrTimestamp, lastContributorBlock[contributor]);\n if (deltaBlocksOrTimestamp > 0 && rewardTokenSpeed > 0) {\n uint256 newAccrued = mul_(deltaBlocksOrTimestamp, rewardTokenSpeed);\n uint256 contributorAccrued = add_(rewardTokenAccrued[contributor], newAccrued);\n\n rewardTokenAccrued[contributor] = contributorAccrued;\n lastContributorBlock[contributor] = blockNumberOrTimestamp;\n\n emit ContributorRewardsUpdated(contributor, rewardTokenAccrued[contributor]);\n }\n }\n\n /**\n * @notice Claim all the rewardToken accrued by holder in the specified markets\n * @param holder The address to claim REWARD TOKEN for\n * @param vTokens The list of markets to claim REWARD TOKEN in\n */\n function claimRewardToken(address holder, VToken[] memory vTokens) public {\n uint256 vTokensCount = vTokens.length;\n\n _ensureMaxLoops(vTokensCount);\n\n for (uint256 i; i < vTokensCount; ++i) {\n VToken vToken = vTokens[i];\n require(comptroller.isMarketListed(vToken), \"market must be listed\");\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\n _distributeBorrowerRewardToken(address(vToken), holder, borrowIndex);\n _updateRewardTokenSupplyIndex(address(vToken));\n _distributeSupplierRewardToken(address(vToken), holder);\n }\n rewardTokenAccrued[holder] = _grantRewardToken(holder, rewardTokenAccrued[holder]);\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding block for a single market.\n * @param vToken market's whose reward token last rewarding block to be updated\n * @param supplyLastRewardingBlock New supply-side REWARD TOKEN last rewarding block for market\n * @param borrowLastRewardingBlock New borrow-side REWARD TOKEN last rewarding block for market\n */\n function _setLastRewardingBlock(\n VToken vToken,\n uint32 supplyLastRewardingBlock,\n uint32 borrowLastRewardingBlock\n ) internal {\n require(comptroller.isMarketListed(vToken), \"rewardToken market is not listed\");\n\n uint256 blockNumber = getBlockNumberOrTimestamp();\n\n require(supplyLastRewardingBlock > blockNumber, \"setting last rewarding block in the past is not allowed\");\n require(borrowLastRewardingBlock > blockNumber, \"setting last rewarding block in the past is not allowed\");\n\n uint32 currentSupplyLastRewardingBlock = rewardTokenSupplyState[address(vToken)].lastRewardingBlock;\n uint32 currentBorrowLastRewardingBlock = rewardTokenBorrowState[address(vToken)].lastRewardingBlock;\n\n require(\n currentSupplyLastRewardingBlock == 0 || currentSupplyLastRewardingBlock > blockNumber,\n \"this RewardsDistributor is already locked\"\n );\n require(\n currentBorrowLastRewardingBlock == 0 || currentBorrowLastRewardingBlock > blockNumber,\n \"this RewardsDistributor is already locked\"\n );\n\n if (currentSupplyLastRewardingBlock != supplyLastRewardingBlock) {\n rewardTokenSupplyState[address(vToken)].lastRewardingBlock = supplyLastRewardingBlock;\n emit SupplyLastRewardingBlockUpdated(address(vToken), supplyLastRewardingBlock);\n }\n\n if (currentBorrowLastRewardingBlock != borrowLastRewardingBlock) {\n rewardTokenBorrowState[address(vToken)].lastRewardingBlock = borrowLastRewardingBlock;\n emit BorrowLastRewardingBlockUpdated(address(vToken), borrowLastRewardingBlock);\n }\n }\n\n /**\n * @notice Set REWARD TOKEN last rewarding timestamp for a single market.\n * @param vToken market's whose reward token last rewarding timestamp to be updated\n * @param supplyLastRewardingBlockTimestamp New supply-side REWARD TOKEN last rewarding timestamp for market\n * @param borrowLastRewardingBlockTimestamp New borrow-side REWARD TOKEN last rewarding timestamp for market\n */\n function _setLastRewardingBlockTimestamp(\n VToken vToken,\n uint256 supplyLastRewardingBlockTimestamp,\n uint256 borrowLastRewardingBlockTimestamp\n ) internal {\n require(comptroller.isMarketListed(vToken), \"rewardToken market is not listed\");\n\n uint256 blockTimestamp = getBlockNumberOrTimestamp();\n\n require(\n supplyLastRewardingBlockTimestamp > blockTimestamp,\n \"setting last rewarding timestamp in the past is not allowed\"\n );\n require(\n borrowLastRewardingBlockTimestamp > blockTimestamp,\n \"setting last rewarding timestamp in the past is not allowed\"\n );\n\n uint256 currentSupplyLastRewardingBlockTimestamp = rewardTokenSupplyStateTimeBased[address(vToken)]\n .lastRewardingTimestamp;\n uint256 currentBorrowLastRewardingBlockTimestamp = rewardTokenBorrowStateTimeBased[address(vToken)]\n .lastRewardingTimestamp;\n\n require(\n currentSupplyLastRewardingBlockTimestamp == 0 || currentSupplyLastRewardingBlockTimestamp > blockTimestamp,\n \"this RewardsDistributor is already locked\"\n );\n require(\n currentBorrowLastRewardingBlockTimestamp == 0 || currentBorrowLastRewardingBlockTimestamp > blockTimestamp,\n \"this RewardsDistributor is already locked\"\n );\n\n if (currentSupplyLastRewardingBlockTimestamp != supplyLastRewardingBlockTimestamp) {\n rewardTokenSupplyStateTimeBased[address(vToken)].lastRewardingTimestamp = supplyLastRewardingBlockTimestamp;\n emit SupplyLastRewardingBlockTimestampUpdated(address(vToken), supplyLastRewardingBlockTimestamp);\n }\n\n if (currentBorrowLastRewardingBlockTimestamp != borrowLastRewardingBlockTimestamp) {\n rewardTokenBorrowStateTimeBased[address(vToken)].lastRewardingTimestamp = borrowLastRewardingBlockTimestamp;\n emit BorrowLastRewardingBlockTimestampUpdated(address(vToken), borrowLastRewardingBlockTimestamp);\n }\n }\n\n /**\n * @notice Set REWARD TOKEN speed for a single market.\n * @param vToken market's whose reward token rate to be updated\n * @param supplySpeed New supply-side REWARD TOKEN speed for market\n * @param borrowSpeed New borrow-side REWARD TOKEN speed for market\n */\n function _setRewardTokenSpeed(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\n require(comptroller.isMarketListed(vToken), \"rewardToken market is not listed\");\n\n if (rewardTokenSupplySpeeds[address(vToken)] != supplySpeed) {\n // Supply speed updated so let's update supply state to ensure that\n // 1. REWARD TOKEN accrued properly for the old speed, and\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\n _updateRewardTokenSupplyIndex(address(vToken));\n\n // Update speed and emit event\n rewardTokenSupplySpeeds[address(vToken)] = supplySpeed;\n emit RewardTokenSupplySpeedUpdated(vToken, supplySpeed);\n }\n\n if (rewardTokenBorrowSpeeds[address(vToken)] != borrowSpeed) {\n // Borrow speed updated so let's update borrow state to ensure that\n // 1. REWARD TOKEN accrued properly for the old speed, and\n // 2. REWARD TOKEN accrued at the new speed starts after this block.\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n _updateRewardTokenBorrowIndex(address(vToken), borrowIndex);\n\n // Update speed and emit event\n rewardTokenBorrowSpeeds[address(vToken)] = borrowSpeed;\n emit RewardTokenBorrowSpeedUpdated(vToken, borrowSpeed);\n }\n }\n\n /**\n * @notice Calculate REWARD TOKEN 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 REWARD TOKEN to\n */\n function _distributeSupplierRewardToken(address vToken, address supplier) internal {\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\n\n uint256 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\n uint256 supplierIndex = rewardTokenSupplierIndex[vToken][supplier];\n\n // Update supplier's index to the current index since we are distributing accrued REWARD TOKEN\n rewardTokenSupplierIndex[vToken][supplier] = supplyIndex;\n\n if (supplierIndex == 0 && supplyIndex >= INITIAL_INDEX) {\n // Covers the case where users supplied tokens before the market's supply state index was set.\n // Rewards the user with REWARD TOKEN accrued from the start of when supplier rewards were first\n // set for the market.\n supplierIndex = INITIAL_INDEX;\n }\n\n // Calculate change in the cumulative sum of the REWARD TOKEN per vToken accrued\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\n\n uint256 supplierTokens = VToken(vToken).balanceOf(supplier);\n\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerVToken\n uint256 supplierDelta = mul_(supplierTokens, deltaIndex);\n\n uint256 supplierAccrued = add_(rewardTokenAccrued[supplier], supplierDelta);\n rewardTokenAccrued[supplier] = supplierAccrued;\n\n emit DistributedSupplierRewardToken(VToken(vToken), supplier, supplierDelta, supplierAccrued, supplyIndex);\n }\n\n /**\n * @notice Calculate reward token accrued by a borrower and possibly transfer it to them.\n * @param vToken The market in which the borrower is interacting\n * @param borrower The address of the borrower to distribute REWARD TOKEN to\n * @param marketBorrowIndex The current global borrow index of vToken\n */\n function _distributeBorrowerRewardToken(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\n\n uint256 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\n uint256 borrowerIndex = rewardTokenBorrowerIndex[vToken][borrower];\n\n // Update borrowers's index to the current index since we are distributing accrued REWARD TOKEN\n rewardTokenBorrowerIndex[vToken][borrower] = borrowIndex;\n\n if (borrowerIndex == 0 && borrowIndex >= INITIAL_INDEX) {\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\n // Rewards the user with REWARD TOKEN accrued from the start of when borrower rewards were first\n // set for the market.\n borrowerIndex = INITIAL_INDEX;\n }\n\n // Calculate change in the cumulative sum of the REWARD TOKEN per borrowed unit accrued\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\n\n uint256 borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\n\n // Calculate REWARD TOKEN accrued: vTokenAmount * accruedPerBorrowedUnit\n if (borrowerAmount != 0) {\n uint256 borrowerDelta = mul_(borrowerAmount, deltaIndex);\n\n uint256 borrowerAccrued = add_(rewardTokenAccrued[borrower], borrowerDelta);\n rewardTokenAccrued[borrower] = borrowerAccrued;\n\n emit DistributedBorrowerRewardToken(VToken(vToken), borrower, borrowerDelta, borrowerAccrued, borrowIndex);\n }\n }\n\n /**\n * @notice Transfer REWARD TOKEN to the user.\n * @dev Note: If there is not enough REWARD TOKEN, we do not perform the transfer all.\n * @param user The address of the user to transfer REWARD TOKEN to\n * @param amount The amount of REWARD TOKEN to (possibly) transfer\n * @return The amount of REWARD TOKEN which was NOT transferred to the user\n */\n function _grantRewardToken(address user, uint256 amount) internal returns (uint256) {\n uint256 rewardTokenRemaining = rewardToken.balanceOf(address(this));\n if (amount > 0 && amount <= rewardTokenRemaining) {\n rewardToken.safeTransfer(user, amount);\n return 0;\n }\n return amount;\n }\n\n /**\n * @notice Accrue REWARD TOKEN to the market by updating the supply index\n * @param vToken The market whose supply index to update\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\n */\n function _updateRewardTokenSupplyIndex(address vToken) internal {\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n TimeBasedRewardToken storage supplyStateTimeBased = rewardTokenSupplyStateTimeBased[vToken];\n\n uint256 supplySpeed = rewardTokenSupplySpeeds[vToken];\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n if (!isTimeBased) {\n safe32(blockNumberOrTimestamp, \"block number exceeds 32 bits\");\n }\n\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\n ? supplyStateTimeBased.lastRewardingTimestamp\n : uint256(supplyState.lastRewardingBlock);\n\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\n }\n\n uint256 deltaBlocksOrTimestamp = sub_(\n blockNumberOrTimestamp,\n (isTimeBased ? supplyStateTimeBased.timestamp : uint256(supplyState.block))\n );\n if (deltaBlocksOrTimestamp > 0 && supplySpeed > 0) {\n uint256 supplyTokens = VToken(vToken).totalSupply();\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, supplySpeed);\n Double memory ratio = supplyTokens > 0\n ? fraction(accruedSinceUpdate, supplyTokens)\n : Double({ mantissa: 0 });\n uint224 supplyIndex = isTimeBased ? supplyStateTimeBased.index : supplyState.index;\n uint224 index = safe224(\n add_(Double({ mantissa: supplyIndex }), ratio).mantissa,\n \"new index exceeds 224 bits\"\n );\n\n if (isTimeBased) {\n supplyStateTimeBased.index = index;\n supplyStateTimeBased.timestamp = blockNumberOrTimestamp;\n } else {\n supplyState.index = index;\n supplyState.block = uint32(blockNumberOrTimestamp);\n }\n } else if (deltaBlocksOrTimestamp > 0) {\n isTimeBased ? supplyStateTimeBased.timestamp = blockNumberOrTimestamp : supplyState.block = uint32(\n blockNumberOrTimestamp\n );\n }\n\n emit RewardTokenSupplyIndexUpdated(vToken);\n }\n\n /**\n * @notice Accrue REWARD TOKEN to the market by updating the borrow index\n * @param vToken The market whose borrow index to update\n * @param marketBorrowIndex The current global borrow index of vToken\n * @dev Index is a cumulative sum of the REWARD TOKEN per vToken accrued\n */\n function _updateRewardTokenBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\n RewardToken storage borrowState = rewardTokenBorrowState[vToken];\n TimeBasedRewardToken storage borrowStateTimeBased = rewardTokenBorrowStateTimeBased[vToken];\n\n uint256 borrowSpeed = rewardTokenBorrowSpeeds[vToken];\n uint256 blockNumberOrTimestamp = getBlockNumberOrTimestamp();\n\n if (!isTimeBased) {\n safe32(blockNumberOrTimestamp, \"block number exceeds 32 bits\");\n }\n\n uint256 lastRewardingBlockOrTimestamp = isTimeBased\n ? borrowStateTimeBased.lastRewardingTimestamp\n : uint256(borrowState.lastRewardingBlock);\n\n if (lastRewardingBlockOrTimestamp > 0 && blockNumberOrTimestamp > lastRewardingBlockOrTimestamp) {\n blockNumberOrTimestamp = lastRewardingBlockOrTimestamp;\n }\n\n uint256 deltaBlocksOrTimestamp = sub_(\n blockNumberOrTimestamp,\n (isTimeBased ? borrowStateTimeBased.timestamp : uint256(borrowState.block))\n );\n if (deltaBlocksOrTimestamp > 0 && borrowSpeed > 0) {\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint256 accruedSinceUpdate = mul_(deltaBlocksOrTimestamp, borrowSpeed);\n Double memory ratio = borrowAmount > 0\n ? fraction(accruedSinceUpdate, borrowAmount)\n : Double({ mantissa: 0 });\n uint224 borrowIndex = isTimeBased ? borrowStateTimeBased.index : borrowState.index;\n uint224 index = safe224(\n add_(Double({ mantissa: borrowIndex }), ratio).mantissa,\n \"new index exceeds 224 bits\"\n );\n\n if (isTimeBased) {\n borrowStateTimeBased.index = index;\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\n } else {\n borrowState.index = index;\n borrowState.block = uint32(blockNumberOrTimestamp);\n }\n } else if (deltaBlocksOrTimestamp > 0) {\n if (isTimeBased) {\n borrowStateTimeBased.timestamp = blockNumberOrTimestamp;\n } else {\n borrowState.block = uint32(blockNumberOrTimestamp);\n }\n }\n\n emit RewardTokenBorrowIndexUpdated(vToken, marketBorrowIndex);\n }\n\n /**\n * @notice Initializes the market state for a specific vToken called when contract is block-based\n * @param vToken The address of the vToken to be initialized\n * @param blockNumber current block number\n */\n function _initializeMarketBlockBased(address vToken, uint32 blockNumber) internal {\n RewardToken storage supplyState = rewardTokenSupplyState[vToken];\n RewardToken storage borrowState = rewardTokenBorrowState[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 = INITIAL_INDEX;\n }\n\n if (borrowState.index == 0) {\n // Initialize borrow state index with default value\n borrowState.index = INITIAL_INDEX;\n }\n\n /*\n * Update market state block numbers\n */\n supplyState.block = borrowState.block = blockNumber;\n }\n\n /**\n * @notice Initializes the market state for a specific vToken called when contract is time-based\n * @param vToken The address of the vToken to be initialized\n * @param blockTimestamp current block timestamp\n */\n function _initializeMarketTimestampBased(address vToken, uint256 blockTimestamp) internal {\n TimeBasedRewardToken storage supplyState = rewardTokenSupplyStateTimeBased[vToken];\n TimeBasedRewardToken storage borrowState = rewardTokenBorrowStateTimeBased[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 = INITIAL_INDEX;\n }\n\n if (borrowState.index == 0) {\n // Initialize borrow state index with default value\n borrowState.index = INITIAL_INDEX;\n }\n\n /*\n * Update market state block timestamp\n */\n supplyState.timestamp = borrowState.timestamp = blockTimestamp;\n }\n}\n" + }, + "contracts/Rewards/RewardsDistributorStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\nimport { Comptroller } from \"../Comptroller.sol\";\n\n/**\n * @title RewardsDistributorStorage\n * @author Venus\n * @dev Storage for RewardsDistributor\n */\ncontract RewardsDistributorStorage {\n struct RewardToken {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block number the index was last updated at\n uint32 block;\n // The block number at which to stop rewards\n uint32 lastRewardingBlock;\n }\n\n struct TimeBasedRewardToken {\n // The market's last updated rewardTokenBorrowIndex or rewardTokenSupplyIndex\n uint224 index;\n // The block timestamp the index was last updated at\n uint256 timestamp;\n // The block timestamp at which to stop rewards\n uint256 lastRewardingTimestamp;\n }\n\n /// @notice The REWARD TOKEN market supply state for each market\n mapping(address => RewardToken) public rewardTokenSupplyState;\n\n /// @notice The REWARD TOKEN borrow index for each market for each supplier as of the last time they accrued REWARD TOKEN\n mapping(address => mapping(address => uint256)) public rewardTokenSupplierIndex;\n\n /// @notice The REWARD TOKEN accrued but not yet transferred to each user\n mapping(address => uint256) public rewardTokenAccrued;\n\n /// @notice The rate at which rewardToken is distributed to the corresponding borrow market per slot (block or second)\n mapping(address => uint256) public rewardTokenBorrowSpeeds;\n\n /// @notice The rate at which rewardToken is distributed to the corresponding supply market per slot (block or second)\n mapping(address => uint256) public rewardTokenSupplySpeeds;\n\n /// @notice The REWARD TOKEN market borrow state for each market\n mapping(address => RewardToken) public rewardTokenBorrowState;\n\n /// @notice The portion of REWARD TOKEN that each contributor receives per slot (block or second)\n mapping(address => uint256) public rewardTokenContributorSpeeds;\n\n /// @notice Last slot (block or second) at which a contributor's REWARD TOKEN rewards have been allocated\n mapping(address => uint256) public lastContributorBlock;\n\n /// @notice The REWARD TOKEN borrow index for each market for each borrower as of the last time they accrued REWARD TOKEN\n mapping(address => mapping(address => uint256)) public rewardTokenBorrowerIndex;\n\n Comptroller internal comptroller;\n\n IERC20Upgradeable public rewardToken;\n\n /// @notice The REWARD TOKEN market supply state for each market\n mapping(address => TimeBasedRewardToken) public rewardTokenSupplyStateTimeBased;\n\n /// @notice The REWARD TOKEN market borrow state for each market\n mapping(address => TimeBasedRewardToken) public rewardTokenBorrowStateTimeBased;\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[37] private __gap;\n}\n" + }, + "contracts/Shortfall/IRiskFund.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\n/**\n * @title IRiskFund\n * @author Venus\n * @notice Interface implemented by `RiskFund`.\n */\ninterface IRiskFund {\n function transferReserveForAuction(address comptroller, uint256 amount) external returns (uint256);\n\n function convertibleBaseAsset() external view returns (address);\n\n function getPoolsBaseAssetReserves(address comptroller) external view returns (uint256);\n}\n" + }, + "contracts/Shortfall/Shortfall.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\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 { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\nimport { TimeManagerV8 } from \"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\";\n\nimport { VToken } from \"../VToken.sol\";\nimport { ComptrollerInterface, ComptrollerViewInterface } from \"../ComptrollerInterface.sol\";\nimport { IRiskFund } from \"./IRiskFund.sol\";\nimport { PoolRegistry } from \"../Pool/PoolRegistry.sol\";\nimport { PoolRegistryInterface } from \"../Pool/PoolRegistryInterface.sol\";\nimport { TokenDebtTracker } from \"../lib/TokenDebtTracker.sol\";\nimport { ShortfallStorage } from \"./ShortfallStorage.sol\";\nimport { EXP_SCALE } from \"../lib/constants.sol\";\n\n/**\n * @title Shortfall\n * @author Venus\n * @notice Shortfall is an auction contract designed to auction off the `convertibleBaseAsset` accumulated in `RiskFund`. The `convertibleBaseAsset`\n * is auctioned in exchange for users paying off the pool's bad debt. An auction can be started by anyone once a pool's bad debt has reached a minimum value.\n * This value is set and can be changed by the authorized accounts. If the pool’s bad debt exceeds the risk fund plus a 10% incentive, then the auction winner\n * is determined by who will pay off the largest percentage of the pool's bad debt. The auction winner then exchanges for the entire risk fund. Otherwise,\n * if the risk fund covers the pool's bad debt plus the 10% incentive, then the auction winner is determined by who will take the smallest percentage of the\n * risk fund in exchange for paying off all the pool's bad debt.\n */\ncontract Shortfall is\n Ownable2StepUpgradeable,\n AccessControlledV8,\n ReentrancyGuardUpgradeable,\n TokenDebtTracker,\n ShortfallStorage,\n TimeManagerV8\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @dev Max basis points i.e., 100%\n uint256 private constant MAX_BPS = 10000;\n\n // @notice Default incentive basis points (BPS) for the auction participants, set to 10%\n uint256 private constant DEFAULT_INCENTIVE_BPS = 1000;\n\n // @notice Default block or timestamp limit for the next bidder to place a bid\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n uint256 private immutable DEFAULT_NEXT_BIDDER_BLOCK_OR_TIMESTAMP_LIMIT;\n\n // @notice Default number of blocks or seconds to wait for the first bidder before starting the auction\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n uint256 private immutable DEFAULT_WAIT_FOR_FIRST_BIDDER;\n\n /// @notice Emitted when a auction starts\n event AuctionStarted(\n address indexed comptroller,\n uint256 auctionStartBlockOrTimestamp,\n AuctionType auctionType,\n VToken[] markets,\n uint256[] marketsDebt,\n uint256 seizedRiskFund,\n uint256 startBidBps\n );\n\n /// @notice Emitted when a bid is placed\n event BidPlaced(\n address indexed comptroller,\n uint256 auctionStartBlockOrTimestamp,\n uint256 bidBps,\n address indexed bidder\n );\n\n /// @notice Emitted when a auction is completed\n event AuctionClosed(\n address indexed comptroller,\n uint256 auctionStartBlockOrTimestamp,\n address indexed highestBidder,\n uint256 highestBidBps,\n uint256 seizedRiskFind,\n VToken[] markets,\n uint256[] marketDebt\n );\n\n /// @notice Emitted when a auction is restarted\n event AuctionRestarted(address indexed comptroller, uint256 auctionStartBlockOrTimestamp);\n\n /// @notice Emitted when pool registry address is updated\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\n\n /// @notice Emitted when minimum pool bad debt is updated\n event MinimumPoolBadDebtUpdated(uint256 oldMinimumPoolBadDebt, uint256 newMinimumPoolBadDebt);\n\n /// @notice Emitted when wait for first bidder block or timestamp count is updated\n event WaitForFirstBidderUpdated(uint256 oldWaitForFirstBidder, uint256 newWaitForFirstBidder);\n\n /// @notice Emitted when next bidder block or timestamp limit is updated\n event NextBidderBlockLimitUpdated(\n uint256 oldNextBidderBlockOrTimestampLimit,\n uint256 newNextBidderBlockOrTimestampLimit\n );\n\n /// @notice Emitted when incentiveBps is updated\n event IncentiveBpsUpdated(uint256 oldIncentiveBps, uint256 newIncentiveBps);\n\n /// @notice Emitted when auctions are paused\n event AuctionsPaused(address sender);\n\n /// @notice Emitted when auctions are unpaused\n event AuctionsResumed(address sender);\n\n /**\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\n * @param blocksPerYear_ The number of blocks per year\n * @param nextBidderBlockOrTimestampLimit_ Default block or timestamp limit for the next bidder to place a bid\n * @param waitForFirstBidder_ Default number of blocks or seconds to wait for the first bidder before starting the auction\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor(\n bool timeBased_,\n uint256 blocksPerYear_,\n uint256 nextBidderBlockOrTimestampLimit_,\n uint256 waitForFirstBidder_\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\n ensureNonzeroValue(nextBidderBlockOrTimestampLimit_);\n ensureNonzeroValue(waitForFirstBidder_);\n\n DEFAULT_NEXT_BIDDER_BLOCK_OR_TIMESTAMP_LIMIT = nextBidderBlockOrTimestampLimit_;\n DEFAULT_WAIT_FOR_FIRST_BIDDER = waitForFirstBidder_;\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 Initialize the shortfall contract\n * @param riskFund_ RiskFund contract address\n * @param minimumPoolBadDebt_ Minimum bad debt in base asset for a pool to start auction\n * @param accessControlManager_ AccessControlManager contract address\n * @custom:error ZeroAddressNotAllowed is thrown when convertible base asset address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when risk fund address is zero\n */\n function initialize(\n IRiskFund riskFund_,\n uint256 minimumPoolBadDebt_,\n address accessControlManager_\n ) external initializer {\n ensureNonzeroAddress(address(riskFund_));\n require(minimumPoolBadDebt_ != 0, \"invalid minimum pool bad debt\");\n\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n __ReentrancyGuard_init();\n __TokenDebtTracker_init();\n minimumPoolBadDebt = minimumPoolBadDebt_;\n riskFund = riskFund_;\n incentiveBps = DEFAULT_INCENTIVE_BPS;\n auctionsPaused = false;\n\n waitForFirstBidder = DEFAULT_WAIT_FOR_FIRST_BIDDER;\n nextBidderBlockLimit = DEFAULT_NEXT_BIDDER_BLOCK_OR_TIMESTAMP_LIMIT;\n }\n\n /**\n * @notice Place a bid greater than the previous in an ongoing auction\n * @param comptroller Comptroller address of the pool\n * @param bidBps The bid percent of the risk fund or bad debt depending on auction type\n * @param auctionStartBlockOrTimestamp The block number or timestamp when auction started\n * @custom:event Emits BidPlaced event on success\n */\n function placeBid(address comptroller, uint256 bidBps, uint256 auctionStartBlockOrTimestamp) external nonReentrant {\n Auction storage auction = auctions[comptroller];\n\n require(auction.startBlockOrTimestamp == auctionStartBlockOrTimestamp, \"auction has been restarted\");\n require(_isStarted(auction), \"no on-going auction\");\n require(!_isStale(auction), \"auction is stale, restart it\");\n require(bidBps > 0, \"basis points cannot be zero\");\n require(bidBps <= MAX_BPS, \"basis points cannot be more than 10000\");\n require(\n (auction.auctionType == AuctionType.LARGE_POOL_DEBT &&\n ((auction.highestBidder != address(0) && bidBps > auction.highestBidBps) ||\n (auction.highestBidder == address(0) && bidBps >= auction.startBidBps))) ||\n (auction.auctionType == AuctionType.LARGE_RISK_FUND &&\n ((auction.highestBidder != address(0) && bidBps < auction.highestBidBps) ||\n (auction.highestBidder == address(0) && bidBps <= auction.startBidBps))),\n \"your bid is not the highest\"\n );\n\n uint256 marketsCount = auction.markets.length;\n for (uint256 i; i < marketsCount; ++i) {\n VToken vToken = VToken(address(auction.markets[i]));\n IERC20Upgradeable erc20 = IERC20Upgradeable(address(vToken.underlying()));\n\n if (auction.highestBidder != address(0)) {\n _transferOutOrTrackDebt(erc20, auction.highestBidder, auction.bidAmount[auction.markets[i]]);\n }\n uint256 balanceBefore = erc20.balanceOf(address(this));\n\n if (auction.auctionType == AuctionType.LARGE_POOL_DEBT) {\n uint256 currentBidAmount = ((auction.marketDebt[auction.markets[i]] * bidBps) / MAX_BPS);\n erc20.safeTransferFrom(msg.sender, address(this), currentBidAmount);\n } else {\n erc20.safeTransferFrom(msg.sender, address(this), auction.marketDebt[auction.markets[i]]);\n }\n\n uint256 balanceAfter = erc20.balanceOf(address(this));\n auction.bidAmount[auction.markets[i]] = balanceAfter - balanceBefore;\n }\n\n auction.highestBidder = msg.sender;\n auction.highestBidBps = bidBps;\n auction.highestBidBlockOrTimestamp = getBlockNumberOrTimestamp();\n\n emit BidPlaced(comptroller, auction.startBlockOrTimestamp, bidBps, msg.sender);\n }\n\n /**\n * @notice Close an auction\n * @param comptroller Comptroller address of the pool\n * @custom:event Emits AuctionClosed event on successful close\n */\n function closeAuction(address comptroller) external nonReentrant {\n Auction storage auction = auctions[comptroller];\n\n require(_isStarted(auction), \"no on-going auction\");\n require(\n getBlockNumberOrTimestamp() > auction.highestBidBlockOrTimestamp + nextBidderBlockLimit &&\n auction.highestBidder != address(0),\n \"waiting for next bidder. cannot close auction\"\n );\n\n uint256 marketsCount = auction.markets.length;\n uint256[] memory marketsDebt = new uint256[](marketsCount);\n\n auction.status = AuctionStatus.ENDED;\n\n for (uint256 i; i < marketsCount; ++i) {\n VToken vToken = VToken(address(auction.markets[i]));\n IERC20Upgradeable erc20 = IERC20Upgradeable(address(vToken.underlying()));\n\n uint256 balanceBefore = erc20.balanceOf(address(auction.markets[i]));\n erc20.safeTransfer(address(auction.markets[i]), auction.bidAmount[auction.markets[i]]);\n uint256 balanceAfter = erc20.balanceOf(address(auction.markets[i]));\n marketsDebt[i] = balanceAfter - balanceBefore;\n\n auction.markets[i].badDebtRecovered(marketsDebt[i]);\n }\n\n uint256 riskFundBidAmount;\n\n if (auction.auctionType == AuctionType.LARGE_POOL_DEBT) {\n riskFundBidAmount = auction.seizedRiskFund;\n } else {\n riskFundBidAmount = (auction.seizedRiskFund * auction.highestBidBps) / MAX_BPS;\n }\n\n address convertibleBaseAsset = riskFund.convertibleBaseAsset();\n\n uint256 transferredAmount = riskFund.transferReserveForAuction(comptroller, riskFundBidAmount);\n _transferOutOrTrackDebt(IERC20Upgradeable(convertibleBaseAsset), auction.highestBidder, riskFundBidAmount);\n\n emit AuctionClosed(\n comptroller,\n auction.startBlockOrTimestamp,\n auction.highestBidder,\n auction.highestBidBps,\n transferredAmount,\n auction.markets,\n marketsDebt\n );\n }\n\n /**\n * @notice Start a auction when there is not currently one active\n * @param comptroller Comptroller address of the pool\n * @custom:event Emits AuctionStarted event on success\n * @custom:event Errors if auctions are paused\n */\n function startAuction(address comptroller) external nonReentrant {\n require(!auctionsPaused, \"Auctions are paused\");\n _startAuction(comptroller);\n }\n\n /**\n * @notice Restart an auction\n * @param comptroller Address of the pool\n * @custom:event Emits AuctionRestarted event on successful restart\n */\n function restartAuction(address comptroller) external nonReentrant {\n Auction storage auction = auctions[comptroller];\n\n require(!auctionsPaused, \"auctions are paused\");\n require(_isStarted(auction), \"no on-going auction\");\n require(_isStale(auction), \"you need to wait for more time for first bidder\");\n\n auction.status = AuctionStatus.ENDED;\n\n emit AuctionRestarted(comptroller, auction.startBlockOrTimestamp);\n _startAuction(comptroller);\n }\n\n /**\n * @notice Update next bidder block or timestamp limit which is used determine when an auction can be closed\n * @param nextBidderBlockOrTimestampLimit_ New next bidder slot (block or second) limit\n * @custom:event Emits NextBidderBlockLimitUpdated on success\n * @custom:access Restricted by ACM\n */\n function updateNextBidderBlockLimit(uint256 nextBidderBlockOrTimestampLimit_) external {\n _checkAccessAllowed(\"updateNextBidderBlockLimit(uint256)\");\n require(nextBidderBlockOrTimestampLimit_ != 0, \"nextBidderBlockOrTimestampLimit_ must not be 0\");\n\n emit NextBidderBlockLimitUpdated(nextBidderBlockLimit, nextBidderBlockOrTimestampLimit_);\n nextBidderBlockLimit = nextBidderBlockOrTimestampLimit_;\n }\n\n /**\n * @notice Updates the incentive BPS\n * @param incentiveBps_ New incentive BPS\n * @custom:event Emits IncentiveBpsUpdated on success\n * @custom:access Restricted by ACM\n */\n function updateIncentiveBps(uint256 incentiveBps_) external {\n _checkAccessAllowed(\"updateIncentiveBps(uint256)\");\n require(incentiveBps_ != 0, \"incentiveBps must not be 0\");\n uint256 oldIncentiveBps = incentiveBps;\n incentiveBps = incentiveBps_;\n emit IncentiveBpsUpdated(oldIncentiveBps, incentiveBps_);\n }\n\n /**\n * @notice Update minimum pool bad debt to start auction\n * @param minimumPoolBadDebt_ Minimum bad debt in the base asset for a pool to start auction\n * @custom:event Emits MinimumPoolBadDebtUpdated on success\n * @custom:access Restricted by ACM\n */\n function updateMinimumPoolBadDebt(uint256 minimumPoolBadDebt_) external {\n _checkAccessAllowed(\"updateMinimumPoolBadDebt(uint256)\");\n uint256 oldMinimumPoolBadDebt = minimumPoolBadDebt;\n minimumPoolBadDebt = minimumPoolBadDebt_;\n emit MinimumPoolBadDebtUpdated(oldMinimumPoolBadDebt, minimumPoolBadDebt_);\n }\n\n /**\n * @notice Update wait for first bidder block or timestamp count. If the first bid is not made within this limit, the auction is closed and needs to be restarted\n * @param waitForFirstBidder_ New wait for first bidder block or timestamp count\n * @custom:event Emits WaitForFirstBidderUpdated on success\n * @custom:access Restricted by ACM\n */\n function updateWaitForFirstBidder(uint256 waitForFirstBidder_) external {\n _checkAccessAllowed(\"updateWaitForFirstBidder(uint256)\");\n uint256 oldWaitForFirstBidder = waitForFirstBidder;\n waitForFirstBidder = waitForFirstBidder_;\n emit WaitForFirstBidderUpdated(oldWaitForFirstBidder, waitForFirstBidder_);\n }\n\n /**\n * @notice Update the pool registry this shortfall supports\n * @dev After Pool Registry is deployed we need to set the pool registry address\n * @param poolRegistry_ Address of pool registry contract\n * @custom:event Emits PoolRegistryUpdated on success\n * @custom:access Restricted to owner\n * @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n */\n function updatePoolRegistry(address poolRegistry_) external onlyOwner {\n ensureNonzeroAddress(poolRegistry_);\n address oldPoolRegistry = poolRegistry;\n poolRegistry = poolRegistry_;\n emit PoolRegistryUpdated(oldPoolRegistry, poolRegistry_);\n }\n\n /**\n * @notice Pause auctions. This disables starting new auctions but lets the current auction finishes\n * @custom:event Emits AuctionsPaused on success\n * @custom:error Errors is auctions are paused\n * @custom:access Restricted by ACM\n */\n function pauseAuctions() external {\n _checkAccessAllowed(\"pauseAuctions()\");\n require(!auctionsPaused, \"Auctions are already paused\");\n auctionsPaused = true;\n emit AuctionsPaused(msg.sender);\n }\n\n /**\n * @notice Resume paused auctions.\n * @custom:event Emits AuctionsResumed on success\n * @custom:error Errors is auctions are active\n * @custom:access Restricted by ACM\n */\n function resumeAuctions() external {\n _checkAccessAllowed(\"resumeAuctions()\");\n require(auctionsPaused, \"Auctions are not paused\");\n auctionsPaused = false;\n emit AuctionsResumed(msg.sender);\n }\n\n /**\n * @notice Start a auction when there is not currently one active\n * @param comptroller Comptroller address of the pool\n */\n function _startAuction(address comptroller) internal {\n PoolRegistryInterface.VenusPool memory pool = PoolRegistry(poolRegistry).getPoolByComptroller(comptroller);\n require(pool.comptroller == comptroller, \"comptroller doesn't exist pool registry\");\n\n Auction storage auction = auctions[comptroller];\n require(\n auction.status == AuctionStatus.NOT_STARTED || auction.status == AuctionStatus.ENDED,\n \"auction is on-going\"\n );\n\n auction.highestBidBps = 0;\n auction.highestBidBlockOrTimestamp = 0;\n\n uint256 marketsCount = auction.markets.length;\n for (uint256 i; i < marketsCount; ++i) {\n VToken vToken = auction.markets[i];\n auction.marketDebt[vToken] = 0;\n }\n\n delete auction.markets;\n\n VToken[] memory vTokens = _getAllMarkets(comptroller);\n marketsCount = vTokens.length;\n ResilientOracleInterface priceOracle = _getPriceOracle(comptroller);\n uint256 poolBadDebt;\n\n uint256[] memory marketsDebt = new uint256[](marketsCount);\n auction.markets = new VToken[](marketsCount);\n\n for (uint256 i; i < marketsCount; ++i) {\n uint256 marketBadDebt = vTokens[i].badDebt();\n\n priceOracle.updatePrice(address(vTokens[i]));\n uint256 usdValue = (priceOracle.getUnderlyingPrice(address(vTokens[i])) * marketBadDebt) / EXP_SCALE;\n\n poolBadDebt = poolBadDebt + usdValue;\n auction.markets[i] = vTokens[i];\n auction.marketDebt[vTokens[i]] = marketBadDebt;\n marketsDebt[i] = marketBadDebt;\n }\n\n require(poolBadDebt >= minimumPoolBadDebt, \"pool bad debt is too low\");\n\n priceOracle.updateAssetPrice(riskFund.convertibleBaseAsset());\n uint256 riskFundBalance = (priceOracle.getPrice(riskFund.convertibleBaseAsset()) *\n riskFund.getPoolsBaseAssetReserves(comptroller)) / EXP_SCALE;\n uint256 remainingRiskFundBalance = riskFundBalance;\n uint256 badDebtPlusIncentive = poolBadDebt + ((poolBadDebt * incentiveBps) / MAX_BPS);\n if (badDebtPlusIncentive >= riskFundBalance) {\n auction.startBidBps =\n (MAX_BPS * MAX_BPS * remainingRiskFundBalance) /\n (poolBadDebt * (MAX_BPS + incentiveBps));\n remainingRiskFundBalance = 0;\n auction.auctionType = AuctionType.LARGE_POOL_DEBT;\n } else {\n uint256 maxSeizeableRiskFundBalance = badDebtPlusIncentive;\n\n remainingRiskFundBalance = remainingRiskFundBalance - maxSeizeableRiskFundBalance;\n auction.auctionType = AuctionType.LARGE_RISK_FUND;\n auction.startBidBps = MAX_BPS;\n }\n\n auction.seizedRiskFund = riskFundBalance - remainingRiskFundBalance;\n auction.startBlockOrTimestamp = getBlockNumberOrTimestamp();\n auction.status = AuctionStatus.STARTED;\n auction.highestBidder = address(0);\n\n emit AuctionStarted(\n comptroller,\n auction.startBlockOrTimestamp,\n auction.auctionType,\n auction.markets,\n marketsDebt,\n auction.seizedRiskFund,\n auction.startBidBps\n );\n }\n\n /**\n * @dev Returns the price oracle of the pool\n * @param comptroller Address of the pool's comptroller\n * @return oracle The pool's price oracle\n */\n function _getPriceOracle(address comptroller) internal view returns (ResilientOracleInterface) {\n return ResilientOracleInterface(ComptrollerViewInterface(comptroller).oracle());\n }\n\n /**\n * @dev Returns all markets of the pool\n * @param comptroller Address of the pool's comptroller\n * @return markets The pool's markets as VToken array\n */\n function _getAllMarkets(address comptroller) internal view returns (VToken[] memory) {\n return ComptrollerInterface(comptroller).getAllMarkets();\n }\n\n /**\n * @dev Checks if the auction has started\n * @param auction The auction to query the status for\n * @return True if the auction has started\n */\n function _isStarted(Auction storage auction) internal view returns (bool) {\n return auction.status == AuctionStatus.STARTED;\n }\n\n /**\n * @dev Checks if the auction is stale, i.e. there's no bidder and the auction\n * was started more than waitForFirstBidder blocks or seconds ago.\n * @param auction The auction to query the status for\n * @return True if the auction is stale\n */\n function _isStale(Auction storage auction) internal view returns (bool) {\n bool noBidder = auction.highestBidder == address(0);\n return noBidder && (getBlockNumberOrTimestamp() > auction.startBlockOrTimestamp + waitForFirstBidder);\n }\n}\n" + }, + "contracts/Shortfall/ShortfallStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { VToken } from \"../VToken.sol\";\nimport { IRiskFund } from \"../Shortfall/IRiskFund.sol\";\n\n/**\n * @title ShortfallStorage\n * @author Venus\n * @dev Storage for Shortfall\n */\ncontract ShortfallStorage {\n /// @notice Type of auction\n enum AuctionType {\n LARGE_POOL_DEBT,\n LARGE_RISK_FUND\n }\n\n /// @notice Status of auction\n enum AuctionStatus {\n NOT_STARTED,\n STARTED,\n ENDED\n }\n\n /// @notice Auction metadata\n struct Auction {\n /// @notice It holds either the starting block number or timestamp\n uint256 startBlockOrTimestamp;\n AuctionType auctionType;\n AuctionStatus status;\n VToken[] markets;\n uint256 seizedRiskFund;\n address highestBidder;\n uint256 highestBidBps;\n /// @notice It holds either the highestBid block or timestamp\n uint256 highestBidBlockOrTimestamp;\n uint256 startBidBps;\n mapping(VToken => uint256) marketDebt;\n mapping(VToken => uint256) bidAmount;\n }\n\n /// @notice Pool registry address\n address public poolRegistry;\n\n /// @notice Risk fund address\n IRiskFund public riskFund;\n\n /// @notice Minimum USD debt in pool for shortfall to trigger\n uint256 public minimumPoolBadDebt;\n\n /// @notice Incentive to auction participants, initial value set to 1000 or 10%\n uint256 public incentiveBps;\n\n /// @notice Time to wait for next bidder. Initially waits for DEFAULT_NEXT_BIDDER_BLOCK_OR_TIMESTAMP_LIMIT\n uint256 public nextBidderBlockLimit;\n\n /// @notice Boolean of if auctions are paused\n bool public auctionsPaused;\n\n /// @notice Time to wait for first bidder. Initially waits for DEFAULT_WAIT_FOR_FIRST_BIDDER\n uint256 public waitForFirstBidder;\n\n /// @notice Auctions for each pool\n mapping(address => Auction) public auctions;\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[42] private __gap;\n}\n" + }, + "contracts/test/ComptrollerHarness.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { Comptroller } from \"../Comptroller.sol\";\n\ncontract ComptrollerHarness is Comptroller {\n uint256 public blockNumber;\n\n // solhint-disable-next-line no-empty-blocks\n constructor(address _poolRegistry) Comptroller(_poolRegistry) {}\n\n function harnessFastForward(uint256 blocks) public returns (uint256) {\n blockNumber += blocks;\n return blockNumber;\n }\n\n function setBlockNumber(uint256 number) public {\n blockNumber = number;\n }\n}\n\ncontract EchoTypesComptroller {\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(uint256[] memory u) public pure returns (uint256[] memory) {\n return u;\n }\n\n function reverty() public pure {\n require(false, \"gotcha sucka\");\n }\n}\n" + }, + "contracts/test/ComptrollerScenario.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { Comptroller } from \"../Comptroller.sol\";\nimport { VToken } from \"../VToken.sol\";\n\ncontract ComptrollerScenario is Comptroller {\n uint256 public blockNumber;\n\n // solhint-disable-next-line no-empty-blocks\n constructor(address _poolRegistry) Comptroller(_poolRegistry) {}\n\n function fastForward(uint256 blocks) public returns (uint256) {\n blockNumber += blocks;\n return blockNumber;\n }\n\n function setBlockNumber(uint256 number) public {\n blockNumber = number;\n }\n\n function unlist(VToken vToken) public {\n markets[address(vToken)].isListed = false;\n }\n\n function membershipLength(VToken vToken) public view returns (uint256) {\n return accountAssets[address(vToken)].length;\n }\n}\n" + }, + "contracts/test/Mocks/MockPriceOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { BinanceOracle } from \"@venusprotocol/oracle/contracts/oracles/BinanceOracle.sol\";\nimport { ChainlinkOracle } from \"@venusprotocol/oracle/contracts/oracles/ChainlinkOracle.sol\";\nimport { ProtocolShareReserve } from \"@venusprotocol/protocol-reserve/contracts/ProtocolReserve/ProtocolShareReserve.sol\";\nimport { VToken } from \"../../VToken.sol\";\n\ncontract MockPriceOracle is ResilientOracleInterface {\n struct TokenConfig {\n /// @notice asset address\n address asset;\n /// @notice `oracles` stores the oracles based on their role in the following order:\n /// [main, pivot, fallback],\n /// It can be indexed with the corresponding enum OracleRole value\n address[3] oracles;\n /// @notice `enableFlagsForOracles` stores the enabled state\n /// for each oracle in the same order as `oracles`\n bool[3] enableFlagsForOracles;\n }\n\n mapping(address => uint256) public assetPrices;\n\n //set price in 6 decimal precision\n // solhint-disable-next-line no-empty-blocks\n constructor() {}\n\n function setPrice(address asset, uint256 price) external {\n assetPrices[asset] = price;\n }\n\n // solhint-disable-next-line no-empty-blocks\n function updatePrice(address vToken) external override {}\n\n // solhint-disable-next-line no-empty-blocks\n function updateAssetPrice(address asset) external override {}\n\n function getPrice(address asset) external view returns (uint256) {\n return assetPrices[asset];\n }\n\n function getTokenConfig(address asset) external view returns (TokenConfig memory) {}\n\n function setTokenConfig(TokenConfig memory tokenConfig) public {}\n\n //https://compound.finance/docs/prices\n function getUnderlyingPrice(address vToken) public view override returns (uint256) {\n return assetPrices[VToken(vToken).underlying()];\n }\n}\n" + }, + "contracts/test/UpgradedVToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { AccessControlManager } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlManager.sol\";\n\nimport { VToken } from \"../VToken.sol\";\nimport { ComptrollerInterface } from \"../ComptrollerInterface.sol\";\nimport { InterestRateModel } from \"../InterestRateModel.sol\";\n\n/**\n * @title Venus's VToken Contract\n * @notice VTokens which wrap an EIP-20 underlying and are immutable\n * @author Venus\n */\ncontract UpgradedVToken is VToken {\n /**\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\n * @param blocksPerYear_ The number of blocks per year\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor(\n bool timeBased_,\n uint256 blocksPerYear_,\n uint256 maxBorrowRateMantissa_\n ) VToken(timeBased_, blocksPerYear_, maxBorrowRateMantissa_) {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\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_ ERC-20 name of this token\n * @param symbol_ ERC-20 symbol of this token\n * @param decimals_ ERC-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param riskManagement Addresses of risk fund contracts\n */\n\n /// @notice We added this new function to test contract upgrade\n function version() external pure returns (uint256) {\n return 2;\n }\n\n function initializeV2(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_,\n address accessControlManager_,\n RiskManagementInit memory riskManagement,\n uint256 reserveFactorMantissa_\n ) public reinitializer(2) {\n super._initialize(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_,\n accessControlManager_,\n riskManagement,\n reserveFactorMantissa_\n );\n }\n\n function getTokenUnderlying() public view returns (address) {\n return underlying;\n }\n}\n" + }, + "contracts/test/VTokenHarness.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.10;\n\nimport { AccessControlManager } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlManager.sol\";\n\nimport { VToken } from \"../VToken.sol\";\nimport { InterestRateModel } from \"../InterestRateModel.sol\";\n\ncontract VTokenHarness is VToken {\n uint256 public blockNumber;\n uint256 public harnessExchangeRate;\n bool public harnessExchangeRateStored;\n\n mapping(address => bool) public failTransferToAddresses;\n\n /**\n * @param timeBased_ A boolean indicating whether the contract is based on time or block.\n * @param blocksPerYear_ The number of blocks per year\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor(\n bool timeBased_,\n uint256 blocksPerYear_,\n uint256 maxBorrowRateMantissa_\n ) VToken(timeBased_, blocksPerYear_, maxBorrowRateMantissa_) {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n function harnessSetAccrualBlockNumber(uint256 accrualBlockNumber_) external {\n accrualBlockNumber = accrualBlockNumber_;\n }\n\n function harnessSetBlockNumber(uint256 newBlockNumber) external {\n blockNumber = newBlockNumber;\n }\n\n function harnessFastForward(uint256 blocks) external {\n blockNumber += blocks;\n }\n\n function harnessSetBalance(address account, uint256 amount) external {\n accountTokens[account] = amount;\n }\n\n function harnessSetTotalSupply(uint256 totalSupply_) external {\n totalSupply = totalSupply_;\n }\n\n function harnessSetTotalBorrows(uint256 totalBorrows_) external {\n totalBorrows = totalBorrows_;\n }\n\n function harnessSetTotalReserves(uint256 totalReserves_) external {\n totalReserves = totalReserves_;\n }\n\n function harnessSetInternalCash(uint256 cash_) external {\n internalCash = cash_;\n }\n\n function harnessExchangeRateDetails(uint256 totalSupply_, uint256 totalBorrows_, uint256 totalReserves_) external {\n totalSupply = totalSupply_;\n totalBorrows = totalBorrows_;\n totalReserves = totalReserves_;\n }\n\n function harnessSetExchangeRate(uint256 exchangeRate) external {\n harnessExchangeRate = exchangeRate;\n harnessExchangeRateStored = true;\n }\n\n function harnessSetFailTransferToAddress(address to_, bool fail_) external {\n failTransferToAddresses[to_] = fail_;\n }\n\n function harnessMintFresh(address account, uint256 mintAmount) external {\n super._mintFresh(account, account, mintAmount);\n }\n\n function harnessRedeemFresh(address payable account, uint256 vTokenAmount, uint256 underlyingAmount) external {\n super._redeemFresh(account, account, vTokenAmount, underlyingAmount);\n }\n\n function harnessSetAccountBorrows(address account, uint256 principal, uint256 interestIndex) external {\n accountBorrows[account] = BorrowSnapshot({ principal: principal, interestIndex: interestIndex });\n }\n\n function harnessSetBorrowIndex(uint256 borrowIndex_) external {\n borrowIndex = borrowIndex_;\n }\n\n function harnessBorrowFresh(address payable account, uint256 borrowAmount) external {\n _borrowFresh(account, account, borrowAmount);\n }\n\n function harnessRepayBorrowFresh(address payer, address account, uint256 repayAmount) external {\n _repayBorrowFresh(payer, account, repayAmount);\n }\n\n function harnessLiquidateBorrowFresh(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VToken vTokenCollateral,\n bool skipLiquidityCheck\n ) external {\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\n }\n\n function harnessReduceReservesFresh(uint256 spreadAmount) external {\n return _reduceReservesFresh(spreadAmount);\n }\n\n function harnessSetReserveFactorFresh(uint256 newReserveFactorMantissa) external {\n _setReserveFactorFresh(newReserveFactorMantissa);\n }\n\n function harnessSetInterestRateModelFresh(InterestRateModel newInterestRateModel) external {\n _setInterestRateModelFresh(newInterestRateModel);\n }\n\n function harnessAccountBorrows(address account) external view returns (uint256 principal, uint256 interestIndex) {\n BorrowSnapshot memory snapshot = accountBorrows[account];\n return (snapshot.principal, snapshot.interestIndex);\n }\n\n function getBorrowRateMaxMantissa() external view returns (uint256) {\n return MAX_BORROW_RATE_MANTISSA;\n }\n\n function harnessSetInterestRateModel(address newInterestRateModelAddress) public {\n interestRateModel = InterestRateModel(newInterestRateModelAddress);\n }\n\n function harnessCallPreBorrowHook(uint256 amount) public {\n comptroller.preBorrowHook(address(this), msg.sender, amount);\n }\n\n function getBlockNumberOrTimestamp() public view override returns (uint256) {\n return blockNumber;\n }\n\n function _doTransferOut(address to, uint256 amount) internal override {\n require(failTransferToAddresses[to] == false, \"HARNESS_TOKEN_TRANSFER_OUT_FAILED\");\n return super._doTransferOut(to, amount);\n }\n\n function _exchangeRateStored() internal view override returns (uint256) {\n if (harnessExchangeRateStored) {\n return harnessExchangeRate;\n }\n return super._exchangeRateStored();\n }\n}\n" + }, + "contracts/VToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\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 { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { IProtocolShareReserve } from \"@venusprotocol/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol\";\n\nimport { VTokenInterface } from \"./VTokenInterfaces.sol\";\nimport { ComptrollerInterface, ComptrollerViewInterface } from \"./ComptrollerInterface.sol\";\nimport { TokenErrorReporter } from \"./ErrorReporter.sol\";\nimport { InterestRateModel } from \"./InterestRateModel.sol\";\nimport { ExponentialNoError } from \"./ExponentialNoError.sol\";\nimport { TimeManagerV8 } from \"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\";\nimport { ensureNonzeroAddress } from \"./lib/validators.sol\";\n\n/**\n * @title VToken\n * @author Venus\n * @notice Each asset that is supported by a pool is integrated through an instance of the `VToken` contract. As outlined in the protocol overview,\n * each isolated pool creates its own `vToken` corresponding to an asset. Within a given pool, each included `vToken` is referred to as a market of\n * the pool. The main actions a user regularly interacts with in a market are:\n\n- mint/redeem of vTokens;\n- transfer of vTokens;\n- borrow/repay a loan on an underlying asset;\n- liquidate a borrow or liquidate/heal an account.\n\n * A user supplies the underlying asset to a pool by minting `vTokens`, where the corresponding `vToken` amount is determined by the `exchangeRate`.\n * The `exchangeRate` will change over time, dependent on a number of factors, some of which accrue interest. Additionally, once users have minted\n * `vToken` in a pool, they can borrow any asset in the isolated pool by using their `vToken` as collateral. In order to borrow an asset or use a `vToken`\n * as collateral, the user must be entered into each corresponding market (else, the `vToken` will not be considered collateral for a borrow). Note that\n * a user may borrow up to a portion of their collateral determined by the market’s collateral factor. However, if their borrowed amount exceeds an amount\n * calculated using the market’s corresponding liquidation threshold, the borrow is eligible for liquidation. When a user repays a borrow, they must also\n * pay off interest accrued on the borrow.\n * \n * The Venus protocol includes unique mechanisms for healing an account and liquidating an account. These actions are performed in the `Comptroller`\n * and consider all borrows and collateral for which a given account is entered within a market. These functions may only be called on an account with a\n * total collateral amount that is no larger than a universal `minLiquidatableCollateral` value, which is used for all markets within a `Comptroller`.\n * Both functions settle all of an account’s borrows, but `healAccount()` may add `badDebt` to a vToken. For more detail, see the description of\n * `healAccount()` and `liquidateAccount()` in the `Comptroller` summary section below.\n */\ncontract VToken is\n Ownable2StepUpgradeable,\n AccessControlledV8,\n VTokenInterface,\n ExponentialNoError,\n TokenErrorReporter,\n TimeManagerV8\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n uint256 internal constant DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA = 5e16; // 5%\n\n // Maximum fraction of interest that can be set aside for reserves\n uint256 internal constant MAX_RESERVE_FACTOR_MANTISSA = 1e18;\n\n // Maximum borrow rate that can ever be applied per slot(block or second)\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n uint256 internal immutable MAX_BORROW_RATE_MANTISSA;\n\n /**\n * Reentrancy Guard **\n */\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 * @param timeBased_ A boolean indicating whether the contract is based on time or block.\n * @param blocksPerYear_ The number of blocks per year\n * @param maxBorrowRateMantissa_ The maximum value of borrowing rate mantissa\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor(\n bool timeBased_,\n uint256 blocksPerYear_,\n uint256 maxBorrowRateMantissa_\n ) TimeManagerV8(timeBased_, blocksPerYear_) {\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n require(maxBorrowRateMantissa_ <= 1e18, \"Max borrow rate must be <= 1e18\");\n\n MAX_BORROW_RATE_MANTISSA = maxBorrowRateMantissa_;\n _disableInitializers();\n }\n\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_ ERC-20 name of this token\n * @param symbol_ ERC-20 symbol of this token\n * @param decimals_ ERC-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param accessControlManager_ AccessControlManager contract address\n * @param riskManagement Addresses of risk & income related contracts\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\n * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\n */\n function initialize(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address admin_,\n address accessControlManager_,\n RiskManagementInit memory riskManagement,\n uint256 reserveFactorMantissa_\n ) external initializer {\n ensureNonzeroAddress(admin_);\n\n // Initialize the market\n _initialize(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_,\n accessControlManager_,\n riskManagement,\n reserveFactorMantissa_\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 * @return success True if the transfer succeeded, reverts otherwise\n * @custom:event Emits Transfer event on success\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\n * @custom:access Not restricted\n */\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\n _transferTokens(msg.sender, msg.sender, dst, amount);\n return true;\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 success True if the transfer succeeded, reverts otherwise\n * @custom:event Emits Transfer event on success\n * @custom:error TransferNotAllowed is thrown if trying to transfer to self\n * @custom:access Not restricted\n */\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\n _transferTokens(msg.sender, src, dst, amount);\n return true;\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 (uint256.max means infinite)\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function approve(address spender, uint256 amount) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n transferAllowances[src][spender] = amount;\n emit Approval(src, spender, amount);\n return true;\n }\n\n /**\n * @notice Increase approval for `spender`\n * @param spender The address of the account which may transfer tokens\n * @param addedValue The number of additional tokens spender can transfer\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function increaseAllowance(address spender, uint256 addedValue) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n uint256 newAllowance = transferAllowances[src][spender];\n newAllowance += addedValue;\n transferAllowances[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n return true;\n }\n\n /**\n * @notice Decreases approval for `spender`\n * @param spender The address of the account which may transfer tokens\n * @param subtractedValue The number of tokens to remove from total approval\n * @return success Whether or not the approval succeeded\n * @custom:event Emits Approval event\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when spender address is zero\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) external override returns (bool) {\n ensureNonzeroAddress(spender);\n\n address src = msg.sender;\n uint256 currentAllowance = transferAllowances[src][spender];\n require(currentAllowance >= subtractedValue, \"decreased allowance below zero\");\n unchecked {\n currentAllowance -= subtractedValue;\n }\n\n transferAllowances[src][spender] = currentAllowance;\n\n emit Approval(src, spender, currentAllowance);\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 amount The amount of underlying owned by `owner`\n */\n function balanceOfUnderlying(address owner) external override returns (uint256) {\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\n return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\n }\n\n /**\n * @notice Returns the current total borrows plus accrued interest\n * @return totalBorrows The total borrows with interest\n */\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\n accrueInterest();\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 borrowBalance The calculated balance\n */\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\n accrueInterest();\n return _borrowBalanceStored(account);\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function mint(uint256 mintAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _mintFresh(msg.sender, msg.sender, mintAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender calls on-behalf of minter. minter supplies assets into the market and receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param minter User whom the supply will be attributed to\n * @param mintAmount The amount of the underlying asset to supply\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Mint and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n * @custom:error ZeroAddressNotAllowed is thrown when minter address is zero\n */\n function mintBehalf(address minter, uint256 mintAmount) external override nonReentrant returns (uint256) {\n ensureNonzeroAddress(minter);\n\n accrueInterest();\n\n _mintFresh(msg.sender, minter, mintAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\n * @custom:access Not restricted\n */\n function redeem(uint256 redeemTokens) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _redeemFresh(msg.sender, msg.sender, redeemTokens, 0);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\n * @custom:error RedeemTransferOutNotPossible is thrown when the protocol has insufficient cash\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function redeemBehalf(address redeemer, uint256 redeemTokens) external override nonReentrant returns (uint256) {\n _ensureSenderIsDelegateOf(redeemer);\n\n accrueInterest();\n\n _redeemFresh(redeemer, msg.sender, redeemTokens, 0);\n return NO_ERROR;\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 receive from redeeming vTokens\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n */\n function redeemUnderlying(uint256 redeemAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _redeemFresh(msg.sender, msg.sender, 0, redeemAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:error InsufficientRedeemApproval is thrown when sender is not approved by the redeemer for the given amount\n * @custom:event Emits Redeem and Transfer events; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function redeemUnderlyingBehalf(\n address redeemer,\n uint256 redeemAmount\n ) external override nonReentrant returns (uint256) {\n _ensureSenderIsDelegateOf(redeemer);\n\n accrueInterest();\n\n _redeemFresh(redeemer, msg.sender, 0, redeemAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits Borrow event; may emit AccrueInterest\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\n * @custom:access Not restricted\n */\n function borrow(uint256 borrowAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _borrowFresh(msg.sender, msg.sender, borrowAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:error DelegateNotApproved is thrown if caller is not approved delegate\n * @custom:error BorrowCashNotAvailable is thrown when the protocol has insufficient cash\n * @custom:event Emits Borrow event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function borrowBehalf(address borrower, uint256 borrowAmount) external override returns (uint256) {\n _ensureSenderIsDelegateOf(borrower);\n accrueInterest();\n\n _borrowFresh(borrower, msg.sender, borrowAmount);\n return NO_ERROR;\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay, or type(uint256).max for the full outstanding amount\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function repayBorrow(uint256 repayAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _repayBorrowFresh(msg.sender, msg.sender, repayAmount);\n return NO_ERROR;\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, or type(uint256).max for the full outstanding amount\n * @return error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits RepayBorrow event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override nonReentrant returns (uint256) {\n accrueInterest();\n\n _repayBorrowFresh(msg.sender, borrower, repayAmount);\n return NO_ERROR;\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 error Always NO_ERROR for compatibility with Venus core tooling\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\n * @custom:access Not restricted\n */\n function liquidateBorrow(\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) external override returns (uint256) {\n _liquidateBorrow(msg.sender, borrower, repayAmount, vTokenCollateral, false);\n return NO_ERROR;\n }\n\n /**\n * @notice sets protocol share accumulated from liquidations\n * @dev must be equal or less than liquidation incentive - 1\n * @param newProtocolSeizeShareMantissa_ new protocol share mantissa\n * @custom:event Emits NewProtocolSeizeShare event on success\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:error ProtocolSeizeShareTooBig is thrown when the new seize share is too high\n * @custom:access Controlled by AccessControlManager\n */\n function setProtocolSeizeShare(uint256 newProtocolSeizeShareMantissa_) external {\n _checkAccessAllowed(\"setProtocolSeizeShare(uint256)\");\n uint256 liquidationIncentive = ComptrollerViewInterface(address(comptroller)).liquidationIncentiveMantissa();\n if (newProtocolSeizeShareMantissa_ + MANTISSA_ONE > liquidationIncentive) {\n revert ProtocolSeizeShareTooBig();\n }\n\n uint256 oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\n protocolSeizeShareMantissa = newProtocolSeizeShareMantissa_;\n emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa_);\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 * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\n * @custom:event Emits NewReserveFactor event; may emit AccrueInterest\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:error SetReserveFactorBoundsCheck is thrown when the new reserve factor is too high\n * @custom:access Controlled by AccessControlManager\n */\n function setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant {\n _checkAccessAllowed(\"setReserveFactor(uint256)\");\n\n accrueInterest();\n _setReserveFactorFresh(newReserveFactorMantissa);\n }\n\n /**\n * @notice Accrues interest and reduces reserves by transferring to the protocol reserve contract\n * @dev Gracefully return if reserves already reduced in accrueInterest\n * @param reduceAmount Amount of reduction to reserves\n * @custom:event Emits ReservesReduced event; may emit AccrueInterest\n * @custom:error ReduceReservesCashNotAvailable is thrown when the vToken does not have sufficient cash\n * @custom:error ReduceReservesCashValidation is thrown when trying to withdraw more cash than the reserves have\n * @custom:access Not restricted\n */\n function reduceReserves(uint256 reduceAmount) external override nonReentrant {\n accrueInterest();\n if (reduceReservesBlockNumber == getBlockNumberOrTimestamp()) return;\n _reduceReservesFresh(reduceAmount);\n }\n\n /**\n * @notice The sender adds to reserves.\n * @param addAmount The amount of underlying token to add as reserves\n * @custom:event Emits ReservesAdded event; may emit AccrueInterest\n * @custom:access Not restricted\n */\n function addReserves(uint256 addAmount) external override nonReentrant {\n accrueInterest();\n _addReservesFresh(addAmount);\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 * @custom:event Emits NewMarketInterestRateModel event; may emit AccrueInterest\n * @custom:error Unauthorized error is thrown when the call is not authorized by AccessControlManager\n * @custom:access Controlled by AccessControlManager\n */\n function setInterestRateModel(InterestRateModel newInterestRateModel) external override {\n _checkAccessAllowed(\"setInterestRateModel(address)\");\n\n accrueInterest();\n _setInterestRateModelFresh(newInterestRateModel);\n }\n\n /**\n * @notice Repays a certain amount of debt, treats the rest of the borrow as bad debt, essentially\n * \"forgiving\" the borrower. Healing is a situation that should rarely happen. However, some pools\n * may list risky assets or be configured improperly – we want to still handle such cases gracefully.\n * We assume that Comptroller does the seizing, so this function is only available to Comptroller.\n * @dev This function does not call any Comptroller hooks (like \"healAllowed\"), because we assume\n * the Comptroller does all the necessary checks before calling this function.\n * @param payer account who repays the debt\n * @param borrower account to heal\n * @param repayAmount amount to repay\n * @custom:event Emits RepayBorrow, BadDebtIncreased events; may emit AccrueInterest\n * @custom:error HealBorrowUnauthorized is thrown when the request does not come from Comptroller\n * @custom:access Only Comptroller\n */\n function healBorrow(address payer, address borrower, uint256 repayAmount) external override nonReentrant {\n if (repayAmount != 0) {\n comptroller.preRepayHook(address(this), borrower);\n }\n\n if (msg.sender != address(comptroller)) {\n revert HealBorrowUnauthorized();\n }\n\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n uint256 totalBorrowsNew = totalBorrows;\n\n uint256 actualRepayAmount;\n if (repayAmount != 0) {\n // _doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\n // We violate checks-effects-interactions here to account for tokens that take transfer fees\n actualRepayAmount = _doTransferIn(payer, repayAmount);\n totalBorrowsNew = totalBorrowsNew - actualRepayAmount;\n emit RepayBorrow(\n payer,\n borrower,\n actualRepayAmount,\n accountBorrowsPrev - actualRepayAmount,\n totalBorrowsNew\n );\n }\n\n // The transaction will fail if trying to repay too much\n uint256 badDebtDelta = accountBorrowsPrev - actualRepayAmount;\n if (badDebtDelta != 0) {\n uint256 badDebtOld = badDebt;\n uint256 badDebtNew = badDebtOld + badDebtDelta;\n totalBorrowsNew = totalBorrowsNew - badDebtDelta;\n badDebt = badDebtNew;\n\n // We treat healing as \"repayment\", where vToken is the payer\n emit RepayBorrow(address(this), borrower, badDebtDelta, 0, totalBorrowsNew);\n emit BadDebtIncreased(borrower, badDebtDelta, badDebtOld, badDebtNew);\n }\n\n accountBorrows[borrower].principal = 0;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n emit HealBorrow(payer, borrower, repayAmount);\n }\n\n /**\n * @notice The extended version of liquidations, callable only by Comptroller. May skip\n * the close factor check. The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n * @custom:event Emits LiquidateBorrow event; may emit AccrueInterest\n * @custom:error ForceLiquidateBorrowUnauthorized is thrown when the request does not come from Comptroller\n * @custom:error LiquidateAccrueCollateralInterestFailed is thrown when it is not possible to accrue interest on the collateral vToken\n * @custom:error LiquidateCollateralFreshnessCheck is thrown when interest has not been accrued on the collateral vToken\n * @custom:error LiquidateLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:error LiquidateCloseAmountIsZero is thrown when repayment amount is zero\n * @custom:error LiquidateCloseAmountIsUintMax is thrown when repayment amount is UINT_MAX\n * @custom:access Only Comptroller\n */\n function forceLiquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) external override {\n if (msg.sender != address(comptroller)) {\n revert ForceLiquidateBorrowUnauthorized();\n }\n _liquidateBorrow(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\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 * @custom:event Emits Transfer, ReservesAdded events\n * @custom:error LiquidateSeizeLiquidatorIsBorrower is thrown when trying to liquidate self\n * @custom:access Not restricted\n */\n function seize(address liquidator, address borrower, uint256 seizeTokens) external override nonReentrant {\n _seize(msg.sender, liquidator, borrower, seizeTokens);\n }\n\n /**\n * @notice Updates bad debt\n * @dev Called only when bad debt is recovered from auction. Updates internal cash balance.\n * @param recoveredAmount_ The amount of bad debt recovered\n * @custom:event Emits BadDebtRecovered event\n * @custom:access Only Shortfall contract\n */\n function badDebtRecovered(uint256 recoveredAmount_) external {\n require(msg.sender == shortfall, \"only shortfall contract can update bad debt\");\n require(recoveredAmount_ <= badDebt, \"more than bad debt recovered from auction\");\n\n uint256 badDebtOld = badDebt;\n uint256 badDebtNew = badDebtOld - recoveredAmount_;\n badDebt = badDebtNew;\n internalCash += recoveredAmount_;\n\n emit BadDebtRecovered(badDebtOld, badDebtNew);\n }\n\n /**\n * @notice Sets protocol share reserve contract address\n * @param protocolShareReserve_ The address of the protocol share reserve contract\n * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero\n * @custom:access Only Governance\n */\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\n _setProtocolShareReserve(protocolShareReserve_);\n }\n\n /**\n * @notice Sets shortfall contract address\n * @param shortfall_ The address of the shortfall contract\n * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero\n * @custom:access Only Governance\n */\n function setShortfallContract(address shortfall_) external onlyOwner {\n _setShortfallContract(shortfall_);\n }\n\n /**\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\n * @param token The address of the ERC-20 token to sweep\n * @custom:access Only Governance\n */\n function sweepToken(IERC20Upgradeable token) external override {\n require(msg.sender == owner(), \"VToken::sweepToken: only admin can sweep tokens\");\n require(address(token) != underlying, \"VToken::sweepToken: can not sweep underlying token\");\n uint256 balance = token.balanceOf(address(this));\n token.safeTransfer(owner(), balance);\n\n emit SweepToken(address(token));\n }\n\n /**\n * @notice Sync internalCash with the actual underlying token balance\n * @dev Used for one-time migration after upgrade to initialize internalCash\n * @custom:event Emits CashSynced\n * @custom:access Controlled by AccessControlManager\n */\n function syncCash() external override nonReentrant {\n _checkAccessAllowed(\"syncCash()\");\n uint256 oldInternalCash = internalCash;\n uint256 actualCash = IERC20Upgradeable(underlying).balanceOf(address(this));\n internalCash = actualCash;\n emit CashSynced(oldInternalCash, actualCash);\n }\n\n /**\n * @notice A public function to set new threshold of slot(block or second) difference after which funds will be sent to the protocol share reserve\n * @param _newReduceReservesBlockOrTimestampDelta slot(block or second) difference value\n * @custom:access Only Governance\n */\n function setReduceReservesBlockDelta(uint256 _newReduceReservesBlockOrTimestampDelta) external {\n _checkAccessAllowed(\"setReduceReservesBlockDelta(uint256)\");\n require(_newReduceReservesBlockOrTimestampDelta > 0, \"Invalid Input\");\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, _newReduceReservesBlockOrTimestampDelta);\n reduceReservesBlockDelta = _newReduceReservesBlockOrTimestampDelta;\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 amount 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 amount 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 error Always NO_ERROR for compatibility with Venus core tooling\n * @return vTokenBalance User's balance of vTokens\n * @return borrowBalance Amount owed in terms of underlying\n * @return exchangeRate Stored exchange rate\n */\n function getAccountSnapshot(\n address account\n )\n external\n view\n override\n returns (uint256 error, uint256 vTokenBalance, uint256 borrowBalance, uint256 exchangeRate)\n {\n return (NO_ERROR, accountTokens[account], _borrowBalanceStored(account), _exchangeRateStored());\n }\n\n /**\n * @notice Get the internally tracked cash balance of this vToken in the underlying asset\n * @return cash The quantity of underlying asset tracked internally by this contract\n */\n function getCash() external view override returns (uint256) {\n return _getCashPrior();\n }\n\n /**\n * @notice Returns the current per slot(block or second) borrow interest rate for this vToken\n * @return rate The borrow interest rate per slot(block or second), scaled by 1e18\n */\n function borrowRatePerBlock() external view override returns (uint256) {\n return interestRateModel.getBorrowRate(_getCashPrior(), totalBorrows, totalReserves, badDebt);\n }\n\n /**\n * @notice Returns the current per-slot(block or second) supply interest rate for this v\n * @return rate The supply interest rate per slot(block or second), scaled by 1e18\n */\n function supplyRatePerBlock() external view override returns (uint256) {\n return\n interestRateModel.getSupplyRate(\n _getCashPrior(),\n totalBorrows,\n totalReserves,\n reserveFactorMantissa,\n badDebt\n );\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 borrowBalance The calculated balance\n */\n function borrowBalanceStored(address account) external view override returns (uint256) {\n return _borrowBalanceStored(account);\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 exchangeRate Calculated exchange rate scaled by 1e18\n */\n function exchangeRateStored() external view override returns (uint256) {\n return _exchangeRateStored();\n }\n\n /**\n * @notice Accrue interest then return the up-to-date exchange rate\n * @return exchangeRate Calculated exchange rate scaled by 1e18\n */\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\n accrueInterest();\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 slot(block or second)\n * up to the current slot(block or second) and writes new checkpoint to storage and\n * reduce spread reserves to protocol share reserve\n * if currentSlot - reduceReservesBlockNumber >= slotDelta\n * @return Always NO_ERROR\n * @custom:event Emits AccrueInterest event on success\n * @custom:access Not restricted\n */\n function accrueInterest() public virtual override returns (uint256) {\n /* Remember the initial block number or timestamp */\n uint256 currentSlotNumber = getBlockNumberOrTimestamp();\n uint256 accrualSlotNumberPrior = accrualBlockNumber;\n\n /* Short-circuit accumulating 0 interest */\n if (accrualSlotNumberPrior == currentSlotNumber) {\n return NO_ERROR;\n }\n\n /* Read the previous values out of storage */\n uint256 cashPrior = _getCashPrior();\n uint256 borrowsPrior = totalBorrows;\n uint256 reservesPrior = totalReserves;\n uint256 borrowIndexPrior = borrowIndex;\n\n /* Calculate the current borrow interest rate */\n uint256 borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior, badDebt);\n require(borrowRateMantissa <= MAX_BORROW_RATE_MANTISSA, \"borrow rate is absurdly high\");\n\n /* Calculate the number of slots elapsed since the last accrual */\n uint256 slotDelta = currentSlotNumber - accrualSlotNumberPrior;\n\n /*\n * Calculate the interest accumulated into borrows and reserves and the new index:\n * simpleInterestFactor = borrowRate * slotDelta\n * interestAccumulated = simpleInterestFactor * totalBorrows\n * totalBorrowsNew = interestAccumulated + totalBorrows\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\n */\n\n Exp memory simpleInterestFactor = mul_(Exp({ mantissa: borrowRateMantissa }), slotDelta);\n uint256 interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\n uint256 totalBorrowsNew = interestAccumulated + borrowsPrior;\n uint256 totalReservesNew = mul_ScalarTruncateAddUInt(\n Exp({ mantissa: reserveFactorMantissa }),\n interestAccumulated,\n reservesPrior\n );\n uint256 borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the previously calculated values into storage */\n accrualBlockNumber = currentSlotNumber;\n borrowIndex = borrowIndexNew;\n totalBorrows = totalBorrowsNew;\n totalReserves = totalReservesNew;\n\n if (currentSlotNumber - reduceReservesBlockNumber >= reduceReservesBlockDelta) {\n reduceReservesBlockNumber = currentSlotNumber;\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 NO_ERROR;\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 or timestamp\n * @param payer The address of the account which is sending the assets for supply\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 */\n function _mintFresh(address payer, address minter, uint256 mintAmount) internal {\n /* Fail if mint not allowed */\n comptroller.preMintHook(address(this), minter, mintAmount);\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert MintFreshnessCheck();\n }\n\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\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 * `_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 uint256 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 uint256 mintTokens = div_(actualMintAmount, exchangeRate);\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 * And write them into storage\n */\n totalSupply = totalSupply + mintTokens;\n uint256 balanceAfter = accountTokens[minter] + mintTokens;\n accountTokens[minter] = balanceAfter;\n\n /* We emit a Mint event, and a Transfer event */\n emit Mint(minter, actualMintAmount, mintTokens, balanceAfter);\n emit Transfer(address(0), minter, mintTokens);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.mintVerify(address(this), minter, actualMintAmount, mintTokens);\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 Comptroller.updateDelegate)\n * @dev Assumes interest has already been accrued up to the current slot(block or second)\n * @param redeemer The address of the account which is redeeming the tokens\n * @param receiver The receiver of the underlying 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 */\n function _redeemFresh(address redeemer, address receiver, uint256 redeemTokensIn, uint256 redeemAmountIn) internal {\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \"one of redeemTokensIn or redeemAmountIn must be zero\");\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert RedeemFreshnessCheck();\n }\n\n /* exchangeRate = invoke Exchange Rate Stored() */\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\n\n uint256 redeemTokens;\n uint256 redeemAmount;\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 */\n redeemTokens = redeemTokensIn;\n } else {\n /*\n * We get the current exchange rate and calculate the amount to be redeemed:\n * redeemTokens = redeemAmountIn / exchangeRate\n */\n redeemTokens = div_(redeemAmountIn, exchangeRate);\n\n uint256 _redeemAmount = mul_(redeemTokens, exchangeRate);\n if (_redeemAmount != 0 && _redeemAmount != redeemAmountIn) redeemTokens++; // round up\n }\n\n // redeemAmount = exchangeRate * redeemTokens\n redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokens);\n\n // Revert if amount is zero\n if (redeemAmount == 0) {\n revert(\"redeemAmount is zero\");\n }\n\n /* Fail if redeem not allowed */\n comptroller.preRedeemHook(address(this), redeemer, redeemTokens);\n\n /* Fail gracefully if protocol has insufficient cash */\n if (_getCashPrior() - totalReserves < redeemAmount) {\n revert RedeemTransferOutNotPossible();\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We write the previously calculated values into storage.\n * Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\n */\n totalSupply = totalSupply - redeemTokens;\n uint256 balanceAfter = accountTokens[redeemer] - redeemTokens;\n accountTokens[redeemer] = balanceAfter;\n\n /*\n * We invoke _doTransferOut for the receiver and the redeemAmount.\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 _doTransferOut(receiver, redeemAmount);\n\n /* We emit a Transfer event, and a Redeem event */\n emit Transfer(redeemer, address(this), redeemTokens);\n emit Redeem(redeemer, redeemAmount, redeemTokens, balanceAfter);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.redeemVerify(address(this), redeemer, redeemAmount, redeemTokens);\n }\n\n /**\n * @notice Users or their delegates borrow assets from the protocol\n * @param borrower User who borrows the assets\n * @param receiver The receiver of the tokens, if called by a delegate\n * @param borrowAmount The amount of the underlying asset to borrow\n */\n function _borrowFresh(address borrower, address receiver, uint256 borrowAmount) internal {\n /* Fail if borrow not allowed */\n comptroller.preBorrowHook(address(this), borrower, borrowAmount);\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert BorrowFreshnessCheck();\n }\n\n /* Fail gracefully if protocol has insufficient underlying cash */\n if (_getCashPrior() - totalReserves < borrowAmount) {\n revert BorrowCashNotAvailable();\n }\n\n /*\n * We calculate the new borrower and total borrow balances, failing on overflow:\n * accountBorrowNew = accountBorrow + borrowAmount\n * totalBorrowsNew = totalBorrows + borrowAmount\n */\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n uint256 accountBorrowsNew = accountBorrowsPrev + borrowAmount;\n uint256 totalBorrowsNew = totalBorrows + borrowAmount;\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We write the previously calculated values into storage.\n * Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\n `*/\n accountBorrows[borrower].principal = accountBorrowsNew;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n /*\n * We invoke _doTransferOut for the receiver and the borrowAmount.\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, accountBorrowsNew, totalBorrowsNew);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\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 underlying tokens being returned, or type(uint256).max for the full outstanding amount\n * @return (uint) the actual repayment amount.\n */\n function _repayBorrowFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256) {\n /* Fail if repayBorrow not allowed */\n comptroller.preRepayHook(address(this), borrower);\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert RepayBorrowFreshnessCheck();\n }\n\n /* We fetch the amount the borrower owes, with accumulated interest */\n uint256 accountBorrowsPrev = _borrowBalanceStored(borrower);\n\n uint256 repayAmountFinal = repayAmount >= accountBorrowsPrev ? accountBorrowsPrev : 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 * 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 uint256 actualRepayAmount = _doTransferIn(payer, repayAmountFinal);\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 uint256 accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\n uint256 totalBorrowsNew = totalBorrows - actualRepayAmount;\n\n /* We write the previously calculated values into storage */\n accountBorrows[borrower].principal = accountBorrowsNew;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = totalBorrowsNew;\n\n /* We emit a RepayBorrow event */\n emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.repayBorrowVerify(address(this), payer, borrower, actualRepayAmount, borrowIndex);\n\n return actualRepayAmount;\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n */\n function _liquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) internal nonReentrant {\n accrueInterest();\n\n uint256 error = vTokenCollateral.accrueInterest();\n if (error != NO_ERROR) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\n revert LiquidateAccrueCollateralInterestFailed(error);\n }\n\n _liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral, skipLiquidityCheck);\n }\n\n /**\n * @notice The liquidator liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the borrow and seizing collateral\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 * @param skipLiquidityCheck If set to true, allows to liquidate up to 100% of the borrow\n * regardless of the account liquidity\n */\n function _liquidateBorrowFresh(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipLiquidityCheck\n ) internal {\n /* Fail if liquidate not allowed */\n comptroller.preLiquidateHook(\n address(this),\n address(vTokenCollateral),\n borrower,\n repayAmount,\n skipLiquidityCheck\n );\n\n /* Verify market's slot(block or second) number equals current slot(block or second) number */\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert LiquidateFreshnessCheck();\n }\n\n /* Verify vTokenCollateral market's slot(block or second) number equals current slot(block or second) number */\n if (vTokenCollateral.accrualBlockNumber() != getBlockNumberOrTimestamp()) {\n revert LiquidateCollateralFreshnessCheck();\n }\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n revert LiquidateLiquidatorIsBorrower();\n }\n\n /* Fail if repayAmount = 0 */\n if (repayAmount == 0) {\n revert LiquidateCloseAmountIsZero();\n }\n\n /* Fail if repayAmount = type(uint256).max */\n if (repayAmount == type(uint256).max) {\n revert LiquidateCloseAmountIsUintMax();\n }\n\n /* Fail if repayBorrow fails */\n uint256 actualRepayAmount = _repayBorrowFresh(liquidator, borrower, repayAmount);\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.liquidateCalculateSeizeTokens(\n address(this),\n address(vTokenCollateral),\n actualRepayAmount\n );\n require(amountSeizeError == 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, call _seize internally to avoid re-entrancy, otherwise make an external call\n if (address(vTokenCollateral) == address(this)) {\n _seize(address(this), liquidator, borrower, seizeTokens);\n } else {\n vTokenCollateral.seize(liquidator, borrower, seizeTokens);\n }\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\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 * It's absolutely critical to use msg.sender as the seizer vToken and not a parameter.\n * @param seizerContract The contract seizing the collateral (either borrowed vToken or Comptroller)\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 */\n function _seize(address seizerContract, address liquidator, address borrower, uint256 seizeTokens) internal {\n /* Fail if seize not allowed */\n comptroller.preSeizeHook(address(this), seizerContract, liquidator, borrower);\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n revert LiquidateSeizeLiquidatorIsBorrower();\n }\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 uint256 liquidationIncentiveMantissa = ComptrollerViewInterface(address(comptroller))\n .liquidationIncentiveMantissa();\n uint256 numerator = mul_(seizeTokens, Exp({ mantissa: protocolSeizeShareMantissa }));\n uint256 protocolSeizeTokens = div_(numerator, Exp({ mantissa: liquidationIncentiveMantissa }));\n uint256 liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\n Exp memory exchangeRate = Exp({ mantissa: _exchangeRateStored() });\n uint256 protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the calculated values into storage */\n totalSupply = totalSupply - protocolSeizeTokens;\n accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\n accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\n\n // _doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\n _doTransferOut(protocolShareReserve, protocolSeizeAmount);\n\n // Update the pool asset's state in the protocol share reserve for the above transfer.\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\n address(comptroller),\n underlying,\n IProtocolShareReserve.IncomeType.LIQUIDATION\n );\n\n /* Emit a Transfer event */\n emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\n emit ProtocolSeize(borrower, protocolShareReserve, protocolSeizeAmount);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.seizeVerify(address(this), seizerContract, liquidator, borrower, seizeTokens);\n }\n\n function _setComptroller(ComptrollerInterface newComptroller) internal {\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\n /**\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\n * @dev Admin function to set a new reserve factor\n * @param newReserveFactorMantissa New reserve factor (from 0 to 1e18)\n */\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal {\n // Verify market's slot(block or second) number equals current slot(block or second) number\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert SetReserveFactorFreshCheck();\n }\n\n // Check newReserveFactor ≤ maxReserveFactor\n if (newReserveFactorMantissa > MAX_RESERVE_FACTOR_MANTISSA) {\n revert SetReserveFactorBoundsCheck();\n }\n\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\n reserveFactorMantissa = newReserveFactorMantissa;\n\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\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 actualAddAmount The actual amount added, excluding the potential token fees\n */\n function _addReservesFresh(uint256 addAmount) internal returns (uint256) {\n // totalReserves + actualAddAmount\n uint256 totalReservesNew;\n uint256 actualAddAmount;\n\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert AddReservesFactorFreshCheck(actualAddAmount);\n }\n\n actualAddAmount = _doTransferIn(msg.sender, addAmount);\n totalReservesNew = totalReserves + actualAddAmount;\n totalReserves = totalReservesNew;\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\n\n return actualAddAmount;\n }\n\n /**\n * @notice Reduces reserves by transferring to the protocol reserve contract\n * @dev Requires fresh interest accrual\n * @param reduceAmount Amount of reduction to reserves\n */\n function _reduceReservesFresh(uint256 reduceAmount) internal {\n if (reduceAmount == 0) {\n return;\n }\n // totalReserves - reduceAmount\n uint256 totalReservesNew;\n\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert ReduceReservesFreshCheck();\n }\n\n // Fail gracefully if protocol has insufficient underlying cash\n if (_getCashPrior() < reduceAmount) {\n revert ReduceReservesCashNotAvailable();\n }\n\n // Check reduceAmount ≤ reserves[n] (totalReserves)\n if (reduceAmount > totalReserves) {\n revert ReduceReservesCashValidation();\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 // Transferring an underlying asset to the protocolShareReserve contract to channel the funds for different use.\n _doTransferOut(protocolShareReserve, reduceAmount);\n\n // Update the pool asset's state in the protocol share reserve for the above transfer.\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\n address(comptroller),\n underlying,\n IProtocolShareReserve.IncomeType.SPREAD\n );\n\n emit SpreadReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\n }\n\n /**\n * @notice updates the interest rate model (*requires fresh interest accrual)\n * @dev Admin function to update the interest rate model\n * @param newInterestRateModel the new interest rate model to use\n */\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal {\n // Used to store old model for use in the event that is emitted on success\n InterestRateModel oldInterestRateModel;\n\n // We fail gracefully unless market's slot(block or second) number equals current slot(block or second) number\n if (accrualBlockNumber != getBlockNumberOrTimestamp()) {\n revert SetInterestRateModelFreshCheck();\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\n /**\n * Safe Token **\n */\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 returns (uint256) {\n IERC20Upgradeable token = IERC20Upgradeable(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 * @param to Receiver of the underlying tokens\n * @param amount Amount of underlying to transfer\n */\n function _doTransferOut(address to, uint256 amount) internal virtual {\n IERC20Upgradeable token = IERC20Upgradeable(underlying);\n internalCash -= amount;\n token.safeTransfer(to, amount);\n }\n\n /**\n * @notice Transfer `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 */\n function _transferTokens(address spender, address src, address dst, uint256 tokens) internal {\n /* Fail if transfer not allowed */\n comptroller.preTransferHook(address(this), src, dst, tokens);\n\n /* Do not allow self-transfers */\n if (src == dst) {\n revert TransferNotAllowed();\n }\n\n /* Get the allowance, infinite for the account owner */\n uint256 startingAllowance;\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 uint256 allowanceNew = startingAllowance - tokens;\n uint256 srcTokensNew = accountTokens[src] - tokens;\n uint256 dstTokensNew = accountTokens[dst] + tokens;\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n\n accountTokens[src] = srcTokensNew;\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\n /**\n * @notice Initialize the 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_ ERC-20 name of this token\n * @param symbol_ ERC-20 symbol of this token\n * @param decimals_ ERC-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param accessControlManager_ AccessControlManager contract address\n * @param riskManagement Addresses of risk & income related contracts\n * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18)\n */\n function _initialize(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address admin_,\n address accessControlManager_,\n RiskManagementInit memory riskManagement,\n uint256 reserveFactorMantissa_\n ) internal onlyInitializing {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\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 _setComptroller(comptroller_);\n\n // Initialize slot(block or second) number and borrow index (slot(block or second) number mocks depend on comptroller being set)\n accrualBlockNumber = getBlockNumberOrTimestamp();\n borrowIndex = MANTISSA_ONE;\n\n // Set the interest rate model (depends on slot(block or second) number / borrow index)\n _setInterestRateModelFresh(interestRateModel_);\n\n _setReserveFactorFresh(reserveFactorMantissa_);\n\n name = name_;\n symbol = symbol_;\n decimals = decimals_;\n _setShortfallContract(riskManagement.shortfall);\n _setProtocolShareReserve(riskManagement.protocolShareReserve);\n protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA;\n\n // Set underlying and sanity check it\n underlying = underlying_;\n IERC20Upgradeable(underlying).totalSupply();\n\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\n _notEntered = true;\n _transferOwnership(admin_);\n }\n\n function _setShortfallContract(address shortfall_) internal {\n ensureNonzeroAddress(shortfall_);\n address oldShortfall = shortfall;\n shortfall = shortfall_;\n emit NewShortfallContract(oldShortfall, shortfall_);\n }\n\n function _setProtocolShareReserve(address payable protocolShareReserve_) internal {\n ensureNonzeroAddress(protocolShareReserve_);\n address oldProtocolShareReserve = address(protocolShareReserve);\n protocolShareReserve = protocolShareReserve_;\n emit NewProtocolShareReserve(oldProtocolShareReserve, address(protocolShareReserve_));\n }\n\n function _ensureSenderIsDelegateOf(address user) internal view {\n if (!ComptrollerViewInterface(address(comptroller)).approvedDelegates(user, msg.sender)) {\n revert DelegateNotApproved();\n }\n }\n\n /**\n * @notice Gets the internally tracked cash balance of this market\n * @dev Returns the internalCash state variable, which is updated on transfers in/out\n * @return The quantity of underlying tokens tracked internally by this contract\n */\n function _getCashPrior() internal view virtual returns (uint256) {\n return internalCash;\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 borrowBalance the calculated balance\n */\n function _borrowBalanceStored(address account) internal view returns (uint256) {\n /* Get borrowBalance and borrowIndex */\n BorrowSnapshot memory 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 0;\n }\n\n /* Calculate new borrow balance using the interest index:\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\n */\n uint256 principalTimesIndex = borrowSnapshot.principal * borrowIndex;\n\n return principalTimesIndex / borrowSnapshot.interestIndex;\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 exchangeRate Calculated exchange rate scaled by 1e18\n */\n function _exchangeRateStored() internal view virtual returns (uint256) {\n uint256 _totalSupply = totalSupply;\n if (_totalSupply == 0) {\n /*\n * If there are no tokens minted:\n * exchangeRate = initialExchangeRate\n */\n return initialExchangeRateMantissa;\n }\n /*\n * Otherwise:\n * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply\n */\n uint256 totalCash = _getCashPrior();\n uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves;\n uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply;\n\n return exchangeRate;\n }\n}\n" + }, + "contracts/VTokenInterfaces.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\nimport { ComptrollerInterface } from \"./ComptrollerInterface.sol\";\nimport { InterestRateModel } from \"./InterestRateModel.sol\";\n\n/**\n * @title VTokenStorage\n * @author Venus\n * @notice Storage layout used by the `VToken` contract\n */\n// solhint-disable-next-line max-states-count\ncontract VTokenStorage {\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 uint256 principal;\n uint256 interestIndex;\n }\n\n /**\n * @dev Guard variable for re-entrancy checks\n */\n bool internal _notEntered;\n\n /**\n * @notice Underlying asset for this VToken\n */\n address public underlying;\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 Protocol share Reserve contract address\n */\n address payable public protocolShareReserve;\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 InterestRateModel public interestRateModel;\n\n // Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\n uint256 internal initialExchangeRateMantissa;\n\n /**\n * @notice Fraction of interest currently set aside for reserves\n */\n uint256 public reserveFactorMantissa;\n\n /**\n * @notice Slot(block or second) number that interest was last accrued at\n */\n uint256 public accrualBlockNumber;\n\n /**\n * @notice Accumulator of the total earned interest rate since the opening of the market\n */\n uint256 public borrowIndex;\n\n /**\n * @notice Total amount of outstanding borrows of the underlying in this market\n */\n uint256 public totalBorrows;\n\n /**\n * @notice Total amount of reserves of the underlying held in this market\n */\n uint256 public totalReserves;\n\n /**\n * @notice Total number of tokens in circulation\n */\n uint256 public totalSupply;\n\n /**\n * @notice Total bad debt of the market\n */\n uint256 public badDebt;\n\n // Official record of token balances for each account\n mapping(address => uint256) internal accountTokens;\n\n // Approved token transfer amounts on behalf of others\n mapping(address => mapping(address => uint256)) internal transferAllowances;\n\n // Mapping of account addresses to outstanding borrow balances\n mapping(address => BorrowSnapshot) internal accountBorrows;\n\n /**\n * @notice Share of seized collateral that is added to reserves\n */\n uint256 public protocolSeizeShareMantissa;\n\n /**\n * @notice Storage of Shortfall contract address\n */\n address public shortfall;\n\n /**\n * @notice delta slot (block or second) after which reserves will be reduced\n */\n uint256 public reduceReservesBlockDelta;\n\n /**\n * @notice last slot (block or second) number at which reserves were reduced\n */\n uint256 public reduceReservesBlockNumber;\n\n /**\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\n * @dev Updated via _doTransferIn(), _doTransferOut(), syncCash(), and badDebtRecovered(). Must be initialized via syncCash() 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[47] private __gap;\n}\n\n/**\n * @title VTokenInterface\n * @author Venus\n * @notice Interface implemented by the `VToken` contract\n */\nabstract contract VTokenInterface is VTokenStorage {\n struct RiskManagementInit {\n address shortfall;\n address payable protocolShareReserve;\n }\n\n /*** Market Events ***/\n\n /**\n * @notice Event emitted when interest is accrued\n */\n event AccrueInterest(uint256 cashPrior, uint256 interestAccumulated, uint256 borrowIndex, uint256 totalBorrows);\n\n /**\n * @notice Event emitted when tokens are minted\n */\n event Mint(address indexed minter, uint256 mintAmount, uint256 mintTokens, uint256 accountBalance);\n\n /**\n * @notice Event emitted when tokens are redeemed\n */\n event Redeem(address indexed redeemer, uint256 redeemAmount, uint256 redeemTokens, uint256 accountBalance);\n\n /**\n * @notice Event emitted when underlying is borrowed\n */\n event Borrow(address indexed borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\n\n /**\n * @notice Event emitted when a borrow is repaid\n */\n event RepayBorrow(\n address indexed payer,\n address indexed borrower,\n uint256 repayAmount,\n uint256 accountBorrows,\n uint256 totalBorrows\n );\n\n /**\n * @notice Event emitted when bad debt is accumulated on a market\n * @param borrower borrower to \"forgive\"\n * @param badDebtDelta amount of new bad debt recorded\n * @param badDebtOld previous bad debt value\n * @param badDebtNew new bad debt value\n */\n event BadDebtIncreased(address indexed borrower, uint256 badDebtDelta, uint256 badDebtOld, uint256 badDebtNew);\n\n /**\n * @notice Event emitted when bad debt is recovered via an auction\n * @param badDebtOld previous bad debt value\n * @param badDebtNew new bad debt value\n */\n event BadDebtRecovered(uint256 badDebtOld, uint256 badDebtNew);\n\n /**\n * @notice Event emitted when a borrow is liquidated\n */\n event LiquidateBorrow(\n address indexed liquidator,\n address indexed borrower,\n uint256 repayAmount,\n address indexed vTokenCollateral,\n uint256 seizeTokens\n );\n\n /*** Admin Events ***/\n\n /**\n * @notice Event emitted when comptroller is changed\n */\n event NewComptroller(ComptrollerInterface indexed oldComptroller, ComptrollerInterface indexed newComptroller);\n\n /**\n * @notice Event emitted when shortfall contract address is changed\n */\n event NewShortfallContract(address indexed oldShortfall, address indexed newShortfall);\n\n /**\n * @notice Event emitted when protocol share reserve contract address is changed\n */\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\n\n /**\n * @notice Event emitted when interestRateModel is changed\n */\n event NewMarketInterestRateModel(\n InterestRateModel indexed oldInterestRateModel,\n InterestRateModel indexed newInterestRateModel\n );\n\n /**\n * @notice Event emitted when protocol seize share is changed\n */\n event NewProtocolSeizeShare(uint256 oldProtocolSeizeShareMantissa, uint256 newProtocolSeizeShareMantissa);\n\n /**\n * @notice Event emitted when the reserve factor is changed\n */\n event NewReserveFactor(uint256 oldReserveFactorMantissa, uint256 newReserveFactorMantissa);\n\n /**\n * @notice Event emitted when the reserves are added\n */\n event ReservesAdded(address indexed benefactor, uint256 addAmount, uint256 newTotalReserves);\n\n /**\n * @notice Event emitted when the spread reserves are reduced\n */\n event SpreadReservesReduced(address indexed protocolShareReserve, uint256 reduceAmount, uint256 newTotalReserves);\n\n /**\n * @notice EIP20 Transfer event\n */\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n /**\n * @notice EIP20 Approval event\n */\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /**\n * @notice Event emitted when healing the borrow\n */\n event HealBorrow(address indexed payer, address indexed borrower, uint256 repayAmount);\n\n /**\n * @notice Event emitted when tokens are swept\n */\n event SweepToken(address indexed token);\n\n /**\n * @notice Event emitted when reduce reserves slot (block or second) delta is changed\n */\n event NewReduceReservesBlockDelta(\n uint256 oldReduceReservesBlockOrTimestampDelta,\n uint256 newReduceReservesBlockOrTimestampDelta\n );\n\n /**\n * @notice Event emitted when liquidation reserves are reduced\n */\n event ProtocolSeize(address indexed from, address indexed to, uint256 amount);\n\n /**\n * @notice Event emitted when internalCash is synced with actual token balance\n */\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\n\n /*** User Interface ***/\n\n function mint(uint256 mintAmount) external virtual returns (uint256);\n\n function mintBehalf(address minter, uint256 mintAllowed) external virtual returns (uint256);\n\n function redeem(uint256 redeemTokens) external virtual returns (uint256);\n\n function redeemBehalf(address redeemer, uint256 redeemTokens) external virtual returns (uint256);\n\n function redeemUnderlying(uint256 redeemAmount) external virtual returns (uint256);\n\n function redeemUnderlyingBehalf(address redeemer, uint256 redeemAmount) external virtual returns (uint256);\n\n function borrow(uint256 borrowAmount) external virtual returns (uint256);\n\n function borrowBehalf(address borrwwer, uint256 borrowAmount) external virtual returns (uint256);\n\n function repayBorrow(uint256 repayAmount) external virtual returns (uint256);\n\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external virtual returns (uint256);\n\n function liquidateBorrow(\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) external virtual returns (uint256);\n\n function healBorrow(address payer, address borrower, uint256 repayAmount) external virtual;\n\n function forceLiquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral,\n bool skipCloseFactorCheck\n ) external virtual;\n\n function seize(address liquidator, address borrower, uint256 seizeTokens) external virtual;\n\n function transfer(address dst, uint256 amount) external virtual returns (bool);\n\n function transferFrom(address src, address dst, uint256 amount) external virtual returns (bool);\n\n function accrueInterest() external virtual returns (uint256);\n\n function sweepToken(IERC20Upgradeable token) external virtual;\n\n /*** Admin Functions ***/\n\n function setReserveFactor(uint256 newReserveFactorMantissa) external virtual;\n\n function reduceReserves(uint256 reduceAmount) external virtual;\n\n function exchangeRateCurrent() external virtual returns (uint256);\n\n function borrowBalanceCurrent(address account) external virtual returns (uint256);\n\n function setInterestRateModel(InterestRateModel newInterestRateModel) external virtual;\n\n function addReserves(uint256 addAmount) external virtual;\n\n function syncCash() external virtual;\n\n function totalBorrowsCurrent() external virtual returns (uint256);\n\n function balanceOfUnderlying(address owner) external virtual returns (uint256);\n\n function approve(address spender, uint256 amount) external virtual returns (bool);\n\n function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool);\n\n function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool);\n\n function allowance(address owner, address spender) external view virtual returns (uint256);\n\n function balanceOf(address owner) external view virtual returns (uint256);\n\n function getAccountSnapshot(address account) external view virtual returns (uint256, uint256, uint256, uint256);\n\n function borrowRatePerBlock() external view virtual returns (uint256);\n\n function supplyRatePerBlock() external view virtual returns (uint256);\n\n function borrowBalanceStored(address account) external view virtual returns (uint256);\n\n function exchangeRateStored() external view virtual returns (uint256);\n\n function getCash() external view virtual returns (uint256);\n\n /**\n * @notice Indicator that this is a VToken contract (for inspection)\n * @return Always true\n */\n function isVToken() external pure virtual returns (bool) {\n return true;\n }\n}\n" + }, + "contracts/WUSDMLiquidator.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 { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\n\nimport { ApproveOrRevert } from \"./lib/ApproveOrRevert.sol\";\nimport { Comptroller } from \"./Comptroller.sol\";\nimport { Action } from \"./ComptrollerInterface.sol\";\nimport { VToken } from \"./VToken.sol\";\n\ncontract WUSDMLiquidator is Ownable2StepUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n using ApproveOrRevert for IERC20Upgradeable;\n\n struct OriginalConfig {\n uint256 minLiquidatableCollateral;\n uint256 closeFactor;\n uint256 wUSDMCollateralFactor;\n uint256 wUSDMLiquidationThreshold;\n uint256 vWUSDMProtocolSeizeShare;\n uint256 vWETHProtocolSeizeShare;\n uint256 vUSDCEProtocolSeizeShare;\n uint256 vUSDTProtocolSeizeShare;\n }\n\n OriginalConfig private _originalConfig;\n\n ResilientOracleInterface public constant ORACLE =\n ResilientOracleInterface(0xDe564a4C887d5ad315a19a96DC81991c98b12182);\n Comptroller public constant COMPTROLLER = Comptroller(0xddE4D098D9995B659724ae6d5E3FB9681Ac941B1);\n VToken public constant VWUSDM = VToken(0x183dE3C349fCf546aAe925E1c7F364EA6FB4033c);\n VToken public constant VWETH = VToken(0x1Fa916C27c7C2c4602124A14C77Dbb40a5FF1BE8);\n VToken public constant VUSDCE = VToken(0x1aF23bD57c62A99C59aD48236553D0Dd11e49D2D);\n VToken public constant VUSDT = VToken(0x69cDA960E3b20DFD480866fFfd377Ebe40bd0A46);\n\n uint256 public constant LIQUIDATION_INCENTIVE = 1.1e18;\n\n address public constant A2 = 0x4C0e4B3e6c5756fb31886a0A01079701ffEC0561;\n address public constant A3 = 0x924EDEd3D010b3F20009b872183eec48D0111265;\n address public constant A4 = 0x2B379d8c90e02016658aD00ba2566F55E814C369;\n address public constant A5 = 0xfffAB9120d9Df39EEa07063F6465a0aA45a80C52;\n\n IERC20Upgradeable public immutable WUSDM;\n IERC20Upgradeable public immutable WETH;\n IERC20Upgradeable public immutable USDCE;\n IERC20Upgradeable public immutable USDT;\n\n /// @notice Emitted when token is swept from the contract\n event SweepToken(address indexed token, address indexed receiver, uint256 amount);\n\n /**\n * @notice Constructor to initialize immutable token references and disable initializers\n */\n constructor() {\n WUSDM = IERC20Upgradeable(VWUSDM.underlying());\n WETH = IERC20Upgradeable(VWETH.underlying());\n USDCE = IERC20Upgradeable(VUSDCE.underlying());\n USDT = IERC20Upgradeable(VUSDT.underlying());\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the contract and sets up ownership\n * @dev This function can only be called once\n */\n function initialize() external initializer {\n __Ownable2Step_init();\n }\n\n /**\n * @notice Executes the liquidation and repayment process\n * @dev This function performs the following steps:\n * 1. Configures the markets by setting collateral factors, close factors, and enabling actions.\n * 2. Supplies WUSDM as collateral.\n * 3. Borrows WETH and liquidates borrowers with WETH debt.\n * 4. Borrows USDCE and liquidates borrowers with USDCE debt.\n * 5. Borrows USDT and liquidates borrowers with USDT debt.\n * 6. Restores the original market configuration.\n */\n function run() external onlyOwner {\n uint256 wusdmPrice = ORACLE.getPrice(address(WUSDM));\n uint256 vwUSDMExchangeRate = VWUSDM.exchangeRateCurrent();\n\n _configureMarkets();\n _supplyCollateral();\n _borrowWETHAndLiquidateBorrowers(wusdmPrice, vwUSDMExchangeRate);\n _borrowUSDCeAndLiquidateBorrowers(wusdmPrice, vwUSDMExchangeRate);\n _borrowUSDTAndLiquidateBorrowers(wusdmPrice, vwUSDMExchangeRate);\n _restoreOriginalConfiguration();\n }\n\n /**\n * @notice Sweeps the input token address tokens from the contract and sends them to the owner\n * @param token Address of the token\n * @custom:event SweepToken emits on success\n * @custom:access Controlled by Governance\n */\n function sweepToken(IERC20Upgradeable token) external onlyOwner {\n uint256 balance = token.balanceOf(address(this));\n\n if (balance > 0) {\n address owner_ = owner();\n token.safeTransfer(owner_, balance);\n emit SweepToken(address(token), owner_, balance);\n }\n }\n\n function _configureMarkets() internal {\n (, uint256 wUSDMCollateralFactor, uint256 wUSDMLiquidationThreshold) = COMPTROLLER.markets(address(VWUSDM));\n _originalConfig = OriginalConfig({\n minLiquidatableCollateral: COMPTROLLER.minLiquidatableCollateral(),\n closeFactor: COMPTROLLER.closeFactorMantissa(),\n wUSDMCollateralFactor: wUSDMCollateralFactor,\n wUSDMLiquidationThreshold: wUSDMLiquidationThreshold,\n vWUSDMProtocolSeizeShare: VWUSDM.protocolSeizeShareMantissa(),\n vWETHProtocolSeizeShare: VWETH.protocolSeizeShareMantissa(),\n vUSDCEProtocolSeizeShare: VUSDCE.protocolSeizeShareMantissa(),\n vUSDTProtocolSeizeShare: VUSDT.protocolSeizeShareMantissa()\n });\n COMPTROLLER.setMinLiquidatableCollateral(0);\n COMPTROLLER.setCloseFactor(1e18);\n COMPTROLLER.setCollateralFactor(VWUSDM, 0.78e18, 0.78e18);\n VToken[] memory markets = new VToken[](1);\n Action[] memory actions = new Action[](2);\n markets[0] = VWUSDM;\n actions[0] = Action.MINT;\n actions[1] = Action.ENTER_MARKET;\n COMPTROLLER.setActionsPaused(markets, actions, false);\n VWUSDM.setProtocolSeizeShare(0);\n VWETH.setProtocolSeizeShare(0);\n VUSDCE.setProtocolSeizeShare(0);\n VUSDT.setProtocolSeizeShare(0);\n }\n\n function _restoreOriginalConfiguration() internal {\n COMPTROLLER.setMinLiquidatableCollateral(_originalConfig.minLiquidatableCollateral);\n COMPTROLLER.setCloseFactor(_originalConfig.closeFactor);\n COMPTROLLER.setCollateralFactor(\n VWUSDM,\n _originalConfig.wUSDMCollateralFactor,\n _originalConfig.wUSDMLiquidationThreshold\n );\n VToken[] memory markets = new VToken[](1);\n Action[] memory actions = new Action[](2);\n markets[0] = VWUSDM;\n actions[0] = Action.MINT;\n actions[1] = Action.ENTER_MARKET;\n COMPTROLLER.setActionsPaused(markets, actions, true);\n VWUSDM.setProtocolSeizeShare(_originalConfig.vWUSDMProtocolSeizeShare);\n VWETH.setProtocolSeizeShare(_originalConfig.vWETHProtocolSeizeShare);\n VUSDCE.setProtocolSeizeShare(_originalConfig.vUSDCEProtocolSeizeShare);\n VUSDT.setProtocolSeizeShare(_originalConfig.vUSDTProtocolSeizeShare);\n // Get some gas refunds for zeroing out storage\n _originalConfig = OriginalConfig(0, 0, 0, 0, 0, 0, 0, 0);\n }\n\n function _supplyCollateral() internal {\n uint256 amount = WUSDM.balanceOf(address(this));\n WUSDM.approveOrRevert(address(VWUSDM), amount);\n VWUSDM.mint(amount);\n WUSDM.approveOrRevert(address(VWUSDM), 0);\n address[] memory markets = new address[](1);\n markets[0] = address(VWUSDM);\n COMPTROLLER.enterMarkets(markets);\n }\n\n function _borrowWETHAndLiquidateBorrowers(uint256 wusdmPrice, uint256 vwUSDMExchangeRate) internal {\n uint256 a2Debt = _getDebt(VWETH, A2);\n uint256 ratio = _getBorrowedTokensToCollateralVTokensRatio(VWETH, wusdmPrice, vwUSDMExchangeRate);\n uint256 amountToRepay = _getAmountToRepayDuringLiquidation(A2, a2Debt, VWUSDM, ratio);\n if (amountToRepay > 0) {\n _borrow(VWETH, amountToRepay);\n WETH.approveOrRevert(address(VWETH), amountToRepay);\n VWETH.liquidateBorrow(A2, amountToRepay, VWUSDM);\n WETH.approveOrRevert(address(VWETH), 0);\n }\n }\n\n function _borrowUSDCeAndLiquidateBorrowers(uint256 wusdmPrice, uint256 vwUSDMExchangeRate) internal {\n uint256 a3Debt = _getDebt(VUSDCE, A3);\n uint256 a4Debt = _getDebt(VUSDCE, A4);\n uint256 a5Debt = _getDebt(VUSDCE, A5);\n uint256 totalRepayment = a3Debt + a4Debt + a5Debt;\n\n _borrow(VUSDCE, totalRepayment);\n USDCE.approveOrRevert(address(VUSDCE), totalRepayment);\n uint256 ratio = _getBorrowedTokensToCollateralVTokensRatio(VUSDCE, wusdmPrice, vwUSDMExchangeRate);\n a3Debt = _liquidateAsMuchAsPossible(A3, a3Debt, VUSDCE, VWUSDM, ratio);\n a4Debt = _liquidateAsMuchAsPossible(A4, a4Debt, VUSDCE, VWUSDM, ratio);\n a5Debt = _liquidateAsMuchAsPossible(A5, a5Debt, VUSDCE, VWUSDM, ratio);\n _repay(A3, VUSDCE, a3Debt > 1 ? a3Debt - 1 : 0);\n _repay(A4, VUSDCE, a4Debt > 1 ? a4Debt - 1 : 0);\n _repay(A5, VUSDCE, a5Debt > 1 ? a5Debt - 1 : 0);\n USDCE.approveOrRevert(address(VUSDCE), 0);\n }\n\n function _borrowUSDTAndLiquidateBorrowers(uint256 wusdmPrice, uint256 vwUSDMExchangeRate) internal {\n uint256 a3Debt = _getDebt(VUSDT, A3);\n uint256 a4Debt = _getDebt(VUSDT, A4);\n uint256 a5Debt = _getDebt(VUSDT, A5);\n uint256 totalRepayment = a3Debt + a4Debt + a5Debt;\n\n _borrow(VUSDT, totalRepayment);\n USDT.approveOrRevert(address(VUSDT), totalRepayment);\n uint256 ratio = _getBorrowedTokensToCollateralVTokensRatio(VUSDT, wusdmPrice, vwUSDMExchangeRate);\n a3Debt = _liquidateAsMuchAsPossible(A3, a3Debt, VUSDT, VWUSDM, ratio);\n a4Debt = _liquidateAsMuchAsPossible(A4, a4Debt, VUSDT, VWUSDM, ratio);\n a5Debt = _liquidateAsMuchAsPossible(A5, a5Debt, VUSDT, VWUSDM, ratio);\n _repay(A3, VUSDT, a3Debt > 1 ? a3Debt - 1 : 0);\n _repay(A4, VUSDT, a4Debt > 1 ? a4Debt - 1 : 0);\n _repay(A5, VUSDT, a5Debt > 1 ? a5Debt - 1 : 0);\n USDT.approveOrRevert(address(VUSDT), 0);\n }\n\n function _getDebt(VToken market, address account) internal returns (uint256) {\n if (!_isUnderwater(account)) {\n return 0; // no debt if not underwater\n }\n return market.borrowBalanceCurrent(account);\n }\n\n function _borrow(VToken market, uint256 amount) internal {\n market.borrow(amount);\n }\n\n function _repay(address account, VToken market, uint256 amount) internal {\n if (amount == 0) {\n return;\n }\n market.repayBorrowBehalf(account, amount);\n }\n\n function _liquidateAsMuchAsPossible(\n address account,\n uint256 debt,\n VToken market,\n VToken collateral,\n uint256 ratio\n ) internal returns (uint256) {\n if (debt == 0) {\n return 0;\n }\n uint256 amountToRepay = _getAmountToRepayDuringLiquidation(account, debt, collateral, ratio);\n if (amountToRepay > 1) {\n market.liquidateBorrow(account, amountToRepay, collateral);\n }\n return debt - amountToRepay;\n }\n\n function _getAmountToRepayDuringLiquidation(\n address account,\n uint256 debt,\n VToken collateral,\n uint256 ratio\n ) internal view returns (uint256) {\n if (debt == 0) {\n return 0;\n }\n uint256 seizeableVTokens = collateral.balanceOf(account);\n if (seizeableVTokens <= 1) {\n return debt;\n }\n // Ideally, we should round up here so that we repay as much as possible during the liquidation,\n // leaving no vTokens supplied, but due to anvil-zksync issues, we want to keep at least 1 wei\n // of vTokens supplied so that we're able to test it later\n uint256 amountToRepayForEntireCollateral = ((seizeableVTokens - 1) * 1e18) / ratio;\n // Keeping 1 wei of debt, for the same purpose\n return debt > amountToRepayForEntireCollateral ? amountToRepayForEntireCollateral : (debt - 1);\n }\n\n function _getBorrowedTokensToCollateralVTokensRatio(\n VToken borrowed,\n uint256 collateralPrice,\n uint256 collateralExchangeRate\n ) internal view returns (uint256) {\n uint256 borrowedPrice = ORACLE.getUnderlyingPrice(address(borrowed));\n return (borrowedPrice * LIQUIDATION_INCENTIVE * 1e18) / (collateralPrice * collateralExchangeRate);\n }\n\n function _isUnderwater(address account) internal view returns (bool) {\n (, uint256 liquidity, uint256 shortfall) = COMPTROLLER.getAccountLiquidity(account);\n return liquidity == 0 && shortfall > 0;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "mode": "3" + }, + "evmVersion": "paris", + "outputSelection": { + "*": { + "*": ["storageLayout", "abi", "evm.methodIdentifiers", "metadata", "devdoc", "userdoc"], + "": ["ast"] + } + }, + "detectMissingLibraries": false, + "forceEVMLA": false, + "enableEraVMExtensions": false, + "libraries": {} + } +} diff --git a/deployments/zksyncmainnet_addresses.json b/deployments/zksyncmainnet_addresses.json index fccb461e8..c710ebc95 100644 --- a/deployments/zksyncmainnet_addresses.json +++ b/deployments/zksyncmainnet_addresses.json @@ -13,7 +13,7 @@ "JumpRateModelV2_base0bps_slope900bps_jump30000bps_kink4500bps_timeBased": "0x42053cb8Ee2cBbfCEDF423C79A50CF56c9C9424f", "JumpRateModelV2_base200bps_slope2000bps_jump30000bps_kink4500bps_timeBased": "0xab2A687A02F5EE7A5b3B52E929705cCA470A0844", "NativeTokenGateway_vWETH_Core": "0xeEDE4e1BDaC489BD851970bE3952B729C4238A68", - "PoolLens": "0x69FC4232959131B4992597B739cEC97Ee898aA68", + "PoolLens": "0x437afd23d8929c382e0CBED30bf7a0A4310C8071", "PoolRegistry": "0xFD96B926298034aed9bBe0Cca4b651E41eB87Bc4", "PoolRegistry_Implementation": "0x204Dfdbb0F066dAfaD8C7fc07B04751A973ADCFb", "PoolRegistry_Proxy": "0xFD96B926298034aed9bBe0Cca4b651E41eB87Bc4", diff --git a/tests/hardhat/Fork/PoolLensForkTest.ts b/tests/hardhat/Fork/PoolLensForkTest.ts new file mode 100644 index 000000000..768807263 --- /dev/null +++ b/tests/hardhat/Fork/PoolLensForkTest.ts @@ -0,0 +1,164 @@ +import chai from "chai"; +import { ethers } from "hardhat"; + +import { + Comptroller, + Comptroller__factory, + PoolLens, + PoolLens__factory, + PoolRegistry__factory, +} from "../../../typechain"; +import { getContractAddresses, setForkBlock } from "./utils"; + +const { expect } = chai; + +const FORK = process.env.FORK === "true"; +const FORKED_NETWORK = process.env.FORKED_NETWORK || "bscmainnet"; + +const { POOL_REGISTRY, COMPTROLLER, CORE_COMPTROLLER, ACC1, BLOCK_NUMBER } = getContractAddresses( + FORKED_NETWORK as string, +); + +// BSC uses block-based, Arbitrum/Optimism/Base/zkSync use time-based +const TIME_BASED_NETWORKS = [ + "arbitrumone", + "arbitrumsepolia", + "zksyncmainnet", + "zksyncsepolia", + "opmainnet", + "opsepolia", + "basemainnet", + "basesepolia", + "unichainmainnet", + "unichainsepolia", +]; + +const isTimeBased = TIME_BASED_NETWORKS.includes(FORKED_NETWORK); +const BSC_BLOCKS_PER_YEAR = 70_080_000; +const ETH_BLOCKS_PER_YEAR = 2_628_000; +const OPBNB_BLOCKS_PER_YEAR = 126_144_000; + +function getBlocksPerYear(network: string): number { + if (TIME_BASED_NETWORKS.includes(network)) return 0; + if (network.includes("opbnb")) return OPBNB_BLOCKS_PER_YEAR; + if (network === "ethereum" || network === "sepolia") return ETH_BLOCKS_PER_YEAR; + return BSC_BLOCKS_PER_YEAR; +} + +if (FORK) { + describe(`PoolLens Fork Test (${FORKED_NETWORK})`, function () { + this.timeout(120_000); // fork tests need more time due to RPC calls + let poolLens: PoolLens; + let comptroller: Comptroller; + + before(async () => { + await setForkBlock(BLOCK_NUMBER); + + const poolLensFactory = (await ethers.getContractFactory("PoolLens")) as PoolLens__factory; + poolLens = await poolLensFactory.deploy( + isTimeBased, + getBlocksPerYear(FORKED_NETWORK), + CORE_COMPTROLLER || ethers.constants.AddressZero, + ); + await poolLens.deployed(); + + comptroller = Comptroller__factory.connect(CORE_COMPTROLLER, ethers.provider); + }); + + describe("getAllPools", () => { + it("should not revert", async () => { + const pools = await poolLens.getAllPools(POOL_REGISTRY); + expect(pools.length).to.be.greaterThan(0); + + for (const pool of pools) { + expect(pool.comptroller).to.not.equal(ethers.constants.AddressZero); + } + }); + }); + + describe("getPoolByComptroller", () => { + it("should not revert and return all markets for core pool", async () => { + const pool = await poolLens.getPoolByComptroller(POOL_REGISTRY, CORE_COMPTROLLER); + expect(pool.comptroller).to.equal(CORE_COMPTROLLER); + expect(pool.vTokens.length).to.be.greaterThan(0); + for (const vToken of pool.vTokens) { + expect(vToken.isListed).to.equal(true); + } + }); + }); + + describe("getPendingRewards", () => { + it("should not revert", async () => { + const account = ACC1 || ethers.constants.AddressZero; + const rewards = await poolLens.getPendingRewards(account, CORE_COMPTROLLER); + expect(rewards).to.be.an("array"); + }); + }); + + describe("getPoolBadDebt", () => { + it("should not revert", async () => { + const badDebtSummary = await poolLens.getPoolBadDebt(CORE_COMPTROLLER); + expect(badDebtSummary.comptroller).to.equal(CORE_COMPTROLLER); + expect(badDebtSummary.badDebts).to.be.an("array"); + for (const badDebt of badDebtSummary.badDebts) { + expect(badDebt.vTokenAddress).to.not.equal(ethers.constants.AddressZero); + } + }); + }); + + describe("vTokenMetadataAll", () => { + it("should not revert for markets in pool", async () => { + const allMarkets = await comptroller.getAllMarkets(); + + if (allMarkets.length > 0) { + const metadata = await poolLens.vTokenMetadataAll(allMarkets); + expect(metadata.length).to.equal(allMarkets.length); + } + }); + }); + + describe("getPoolDataFromVenusPool", () => { + it("should not revert", async () => { + const poolRegistry = PoolRegistry__factory.connect(POOL_REGISTRY, ethers.provider); + const venusPool = await poolRegistry.getPoolByComptroller(CORE_COMPTROLLER); + const poolData = await poolLens.getPoolDataFromVenusPool(POOL_REGISTRY, venusPool); + expect(poolData.comptroller).to.equal(CORE_COMPTROLLER); + }); + }); + + describe("non-core pool filters out vTokens with internalCash == 0", () => { + it("should not include vTokens with zero internalCash for non-core pools", async () => { + if (COMPTROLLER === CORE_COMPTROLLER) { + return; + } + + const pools = await poolLens.getAllPools(POOL_REGISTRY); + for (const pool of pools) { + if (pool.comptroller === CORE_COMPTROLLER) continue; + + for (const vToken of pool.vTokens) { + expect(vToken.totalCash).to.be.gt(0, `vToken ${vToken.vToken} in pool ${pool.comptroller} has zero cash`); + } + } + }); + }); + + describe("core pool includes all markets", () => { + it("should include all markets for core pool", async () => { + if (!CORE_COMPTROLLER || CORE_COMPTROLLER === ethers.constants.AddressZero) { + return; + } + + const coreComptroller = Comptroller__factory.connect(CORE_COMPTROLLER, ethers.provider); + const allMarkets = await coreComptroller.getAllMarkets(); + const pool = await poolLens.getPoolByComptroller(POOL_REGISTRY, CORE_COMPTROLLER); + const returnedAddresses = pool.vTokens.map(v => v.vToken.toLowerCase()); + + expect(returnedAddresses.length).to.equal(allMarkets.length); + for (const market of allMarkets) { + expect(returnedAddresses).to.include(market.toLowerCase()); + } + }); + }); + }); +} diff --git a/tests/hardhat/Fork/constants.ts b/tests/hardhat/Fork/constants.ts index fd670589a..3309b6b8c 100644 --- a/tests/hardhat/Fork/constants.ts +++ b/tests/hardhat/Fork/constants.ts @@ -40,6 +40,7 @@ export const contractAddresses = { VTOKEN1: SepoliaContracts.VToken_vcrvUSD_Core.address, VTOKEN2: SepoliaContracts.VToken_vCRV_Core.address, COMPTROLLER: SepoliaContracts.Comptroller_Core.address, + CORE_COMPTROLLER: "0x7Aa39ab4BcA897F403425C9C6FDbd0f882Be0D70", PSR: PsrSepTestnet.contracts.ProtocolShareReserve.address, REWARD_DISTRIBUTOR1: SepoliaContracts.RewardsDistributor_Core_1.address, POOL_REGISTRY: SepoliaContracts.PoolRegistry.address, @@ -60,6 +61,7 @@ export const contractAddresses = { VTOKEN1: EthereumContracts.VToken_vcrvUSD_Curve.address, VTOKEN2: EthereumContracts.VToken_vCRV_Curve.address, COMPTROLLER: EthereumContracts.Comptroller_Curve.address, + CORE_COMPTROLLER: "0x687a01ecF6d3907658f7A7c714749fAC32336D1B", PSR: PsrEthereum.contracts.ProtocolShareReserve.address, REWARD_DISTRIBUTOR1: EthereumContracts.RewardsDistributor_Curve_0.address, POOL_REGISTRY: EthereumContracts.PoolRegistry.address, @@ -70,7 +72,7 @@ export const contractAddresses = { ACC1: "0x95222290DD7278Aa3Ddd389Cc1E1d165CC4BAfe5", ACC2: "0x29182006a4967e9a50C0A66076dA514993D3B4D4", ACC3: "0xa27CEF8aF2B6575903b676e5644657FAe96F491F", - BLOCK_NUMBER: 19781700, + BLOCK_NUMBER: 24777279, }, bsctestnet: { ADMIN: GovernanceBscTestnet.contracts.NormalTimelock.address, @@ -80,6 +82,7 @@ export const contractAddresses = { VTOKEN1: TestnetContracts.VToken_vUSDD_Stablecoins.address, VTOKEN2: TestnetContracts.VToken_vlisUSD_Stablecoins.address, COMPTROLLER: TestnetContracts.Comptroller_Stablecoins.address, + CORE_COMPTROLLER: "0x0000000000000000000000000000000000000000", PSR: PsrBscTestnet.contracts.ProtocolShareReserve.address, SHORTFALL: TestnetContracts.Shortfall.address, RISKFUND: PsrBscTestnet.contracts.RiskFundV2.address, @@ -104,6 +107,7 @@ export const contractAddresses = { VTOKEN1: MainnetContracts.VToken_vUSDD_Stablecoins.address, VTOKEN2: MainnetContracts.VToken_vlisUSD_Stablecoins.address, COMPTROLLER: MainnetContracts.Comptroller_Stablecoins.address, + CORE_COMPTROLLER: "0x0000000000000000000000000000000000000000", PSR: PsrBscMainnet.contracts.ProtocolShareReserve.address, SHORTFALL: MainnetContracts.Shortfall.address, RISKFUND: PsrBscMainnet.contracts.RiskFundV2.address, @@ -130,6 +134,7 @@ export const contractAddresses = { VTOKEN1: OpBnbTestnetContracts.VToken_vBTCB_Core.address, VTOKEN2: OpBnbTestnetContracts.VToken_vETH_Core.address, COMPTROLLER: OpBnbTestnetContracts.Comptroller_Core.address, + CORE_COMPTROLLER: "0x2FCABb31E57F010D623D8d68e1E18Aed11d5A388", PSR: PsrOpBnbTestnet.address, POOL_REGISTRY: OpBnbTestnetContracts.PoolRegistry.address, RESILIENT_ORACLE: OracleOpBnbTestnet.contracts.ResilientOracle.address, @@ -150,6 +155,7 @@ export const contractAddresses = { VTOKEN1: OpBnbMainnetContracts.VToken_vUSDT_Core.address, VTOKEN2: OpBnbMainnetContracts.VToken_vFDUSD_Core.address, COMPTROLLER: OpBnbMainnetContracts.Comptroller_Core.address, + CORE_COMPTROLLER: "0xD6e3E2A1d8d95caE355D15b3b9f8E5c2511874dd", PSR: "0xDDc9017F3073aa53a4A8535163b0bf7311F72C52", POOL_REGISTRY: OpBnbMainnetContracts.PoolRegistry.address, RESILIENT_ORACLE: OracleOpBnbMainnet.contracts.ResilientOracle.address, @@ -161,7 +167,7 @@ export const contractAddresses = { ACC1: "0x3Ac99C7853b58f4AA38b309D372562a5A88bB9C1", ACC2: "0xA4a04C2D661bB514bB8B478CaCB61145894563ef", ACC3: "0x394d1d517e8269596a7E4Cd1DdaC1C928B3bD8b3", - BLOCK_NUMBER: 17881611, + BLOCK_NUMBER: 127330000, }, arbitrumsepolia: { ADMIN: "0x1426A5Ae009c4443188DA8793751024E358A61C2", @@ -169,6 +175,7 @@ export const contractAddresses = { VTOKEN1: ArbSepContracts.VToken_vWETH_Core.address, VTOKEN2: ArbSepContracts.VToken_vARB_Core.address, COMPTROLLER: ArbSepContracts.Comptroller_Core.address, + CORE_COMPTROLLER: "0x006D44b6f5927b3eD83bD0c1C36Fb1A3BaCaC208", PSR: PsrArbSep.contracts.ProtocolShareReserve.address, REWARD_DISTRIBUTOR1: ArbSepContracts.RewardsDistributor_Core_0.address, POOL_REGISTRY: ArbSepContracts.PoolRegistry.address, @@ -189,6 +196,7 @@ export const contractAddresses = { VTOKEN1: ArbOneContracts.VToken_vWETH_Core.address, VTOKEN2: ArbOneContracts.VToken_vARB_Core.address, COMPTROLLER: ArbOneContracts.Comptroller_Core.address, + CORE_COMPTROLLER: "0x317c1A5739F39046E20b08ac9BeEa3f10fD43326", PSR: PsrArbOne.contracts.ProtocolShareReserve.address, REWARD_DISTRIBUTOR1: ArbOneContracts.RewardsDistributor_Core_0.address, POOL_REGISTRY: ArbOneContracts.PoolRegistry.address, @@ -201,6 +209,24 @@ export const contractAddresses = { ACC1: "0x32B701d3957fee432664cFA57FB44b0fE8496659", ACC2: "0xB09F16F625B363875e39ADa56C03682088471523", ACC3: "0x4A2339eE9c4fD4c99DE1d3AeB513B53ab42Db5ca", - BLOCK_NUMBER: 224198807, + BLOCK_NUMBER: 447530000, + }, + basemainnet: { + CORE_COMPTROLLER: "0x0C7973F9598AA62f9e03B94E92C967fD5437426C", + POOL_REGISTRY: "0xeef902918DdeCD773D4B422aa1C6e1673EB9136F", + ACC1: "0xcdac0d6c6c59727a65f871236188350531885c43", + BLOCK_NUMBER: 44070000, + }, + opmainnet: { + CORE_COMPTROLLER: "0x5593FF68bE84C966821eEf5F0a988C285D5B7CeC", + POOL_REGISTRY: "0x147780799840d541C1d7c998F0cbA996d11D62bb", + ACC1: "0xacD03D601e5bB1B275Bb94076fF46ED9D753435A", + BLOCK_NUMBER: 149670000, + }, + unichainmainnet: { + CORE_COMPTROLLER: "0xe22af1e6b78318e1Fe1053Edbd7209b8Fc62c4Fe", + POOL_REGISTRY: "0x0C52403E16BcB8007C1e54887E1dFC1eC9765D7C", + ACC1: "0x0000000000000000000000000000000000000001", + BLOCK_NUMBER: 44190000, }, }; diff --git a/tests/hardhat/Lens/PoolLens.ts b/tests/hardhat/Lens/PoolLens.ts index 00a0e7675..ad3b1f4fb 100644 --- a/tests/hardhat/Lens/PoolLens.ts +++ b/tests/hardhat/Lens/PoolLens.ts @@ -239,7 +239,7 @@ for (const isTimeBased of [false, true]) { .setActionsPaused([vWBTC.address], [ACTION_LIQUIDATE, ACTION_EXIT_MARKET], true); const PoolLens = await ethers.getContractFactory("PoolLens"); - poolLens = await PoolLens.deploy(isTimeBased, slotsPerYear); + poolLens = await PoolLens.deploy(isTimeBased, slotsPerYear, ethers.constants.AddressZero); }); describe(`${description}PoolView Tests`, () => { diff --git a/tests/hardhat/Lens/RewardsSummary.ts b/tests/hardhat/Lens/RewardsSummary.ts index cd3e2084d..dbf09aba4 100644 --- a/tests/hardhat/Lens/RewardsSummary.ts +++ b/tests/hardhat/Lens/RewardsSummary.ts @@ -55,7 +55,7 @@ const rewardsFixture = async (): Promise => { rewardToken2 = await smock.fake("MockToken"); rewardToken3 = await smock.fake("MockToken"); const poolLensFactory = await smock.mock("PoolLens"); - poolLens = await poolLensFactory.deploy(isTimeBased, blocksPerYear); + poolLens = await poolLensFactory.deploy(isTimeBased, blocksPerYear, comptroller.address); const startBlock = await ethers.provider.getBlockNumber(); @@ -168,7 +168,7 @@ const timeBasedRewardsFixture = async (): Promise => { isTimeBased = true; blocksPerYear = 0; - poolLens = await poolLensFactory.deploy(isTimeBased, blocksPerYear); + poolLens = await poolLensFactory.deploy(isTimeBased, blocksPerYear, comptroller.address); const startBlock = (await ethers.provider.getBlock("latest")).number; const startBlockTimestamp = (await ethers.provider.getBlock("latest")).timestamp;