{ "settings": { "evmVersion": "paris", "libraries": { "": {} }, "metadata": { "bytecodeHash": "ipfs" }, "optimizer": { "enabled": true, "runs": 200 }, "remappings": [], "viaIR": true, "outputSelection": { "*": { "*": [ "evm.bytecode.object", "evm.deployedBytecode.object", "evm.deployedBytecode.immutableReferences", "metadata" ] } } }, "sources": { "contracts/Exponential/ExponentialNoError.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\nstruct Exp {\n uint256 mantissa;\n}\n\nstruct Double {\n uint256 mantissa;\n}\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 */\nlibrary ExponentialNoError {\n uint256 constant expScale = 1e18;\n uint256 constant doubleScale = 1e36;\n uint256 constant halfExpScale = expScale / 2;\n uint256 constant mantissaOne = expScale;\n\n /**\n * @dev Truncates the given exp to a whole number value.\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\n */\n function truncate(Exp memory exp) internal pure returns (uint256) {\n // Note: We are not using careful math here as we're performing a division that cannot fail\n return exp.mantissa / expScale;\n }\n\n /**\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\n */\n function mul_ScalarTruncate(Exp memory a, 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 function mul_ScalarTruncateAddUInt(\n Exp memory a,\n uint256 scalar,\n uint256 addend\n ) internal pure returns (uint256) {\n Exp memory product = mul_(a, scalar);\n return add_(truncate(product), addend);\n }\n\n function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\n require(n < 2**224, errorMessage);\n return uint224(n);\n }\n\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\n require(n < 2**32, errorMessage);\n return uint32(n);\n }\n\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({mantissa: add_(a.mantissa, b.mantissa)});\n }\n\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({mantissa: add_(a.mantissa, b.mantissa)});\n }\n\n function add_(uint256 a, uint256 b) internal pure returns (uint256) {\n return add_(a, b, 'addition overflow');\n }\n\n function add_(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, errorMessage);\n return c;\n }\n\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({mantissa: sub_(a.mantissa, b.mantissa)});\n }\n\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({mantissa: sub_(a.mantissa, b.mantissa)});\n }\n\n function sub_(uint256 a, uint256 b) internal pure returns (uint256) {\n return sub_(a, b, 'subtraction underflow');\n }\n\n function sub_(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n return a - b;\n }\n\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({mantissa: mul_(a.mantissa, b.mantissa) / expScale});\n }\n\n function mul_(Exp memory a, 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) / expScale;\n }\n\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({mantissa: mul_(a.mantissa, b.mantissa) / doubleScale});\n }\n\n function mul_(Double memory a, 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) / doubleScale;\n }\n\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\n return mul_(a, b, 'multiplication overflow');\n }\n\n function mul_(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n if (a == 0 || b == 0) {\n return 0;\n }\n uint256 c = a * b;\n require(c / a == b, errorMessage);\n return c;\n }\n\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({mantissa: div_(mul_(a.mantissa, expScale), b.mantissa)});\n }\n\n function div_(Exp memory a, 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, expScale), b.mantissa);\n }\n\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa)});\n }\n\n function div_(Double memory a, 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, doubleScale), b.mantissa);\n }\n\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\n return div_(a, b, 'divide by zero');\n }\n\n function div_(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n require(b > 0, errorMessage);\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, doubleScale), b)});\n }\n}\n" }, "contracts/Comptroller/Comptroller.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\nimport './ComptrollerStorage.sol';\nimport '../Exponential/ExponentialNoError.sol';\nimport './Interfaces/ICToken.sol';\nimport './Interfaces/IUnderwriterAdmin.sol';\nimport './Interfaces/IPriceOracle.sol';\nimport '@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol';\n\ninterface ICompLogic {\n function setCompSpeed(address cToken, uint256 supplySpeed, uint256 borrowSpeed) external;\n\n function updateCompSupplyIndex(address cToken) external;\n\n function updateCompBorrowIndex(address cToken, Exp memory marketBorrowIndex) external;\n\n function distributeSupplierComp(address cToken, address supplier) external;\n\n function distributeBorrowerComp(address cToken, address borrower, Exp memory marketBorrowIndex) external;\n\n function initializeMarket(address cToken, uint32 blockNumber) external;\n}\n\ninterface IAccountLiquidity {\n function getHypotheticalAccountLiquidity(\n address account,\n address cTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount\n ) external view returns (uint256, uint256, uint256);\n}\n\n/**\n * @title Compound's Comptroller Contract\n * @author Compound\n */\ncontract Comptroller is AccessControlEnumerableUpgradeable, ComptrollerStorage {\n using ExponentialNoError for uint256;\n using ExponentialNoError for Exp;\n using ExponentialNoError for Double;\n\n ICompLogic public compLogic;\n IUnderwriterAdmin public underWriterAdmin;\n IPriceOracle public oracle;\n IAccountLiquidity public accountLiquidity;\n\n bytes32 public constant COMP_LOGIC = keccak256('COMP_LOGIC');\n\n function initialize(\n address _admin,\n IPriceOracle _oracle,\n IUnderwriterAdmin _underWriterAdmin,\n ICompLogic _compLogic,\n IAccountLiquidity _accountLiquidity,\n uint256 _closeFactorMantissa,\n uint256 _liquidationIncentiveMantissa\n ) external initializer {\n _setupRole(DEFAULT_ADMIN_ROLE, _admin);\n // Set comptroller's oracle to newOracle\n oracle = _oracle;\n // Emit NewPriceOracle(oldOracle, newOracle)\n emit NewPriceOracle(address(0), address(_oracle));\n compLogic = _compLogic;\n\n accountLiquidity = _accountLiquidity;\n\n closeFactorMantissa = _closeFactorMantissa;\n emit NewCloseFactor(0, _closeFactorMantissa);\n\n // Set liquidation incentive to new incentive\n liquidationIncentiveMantissa = _liquidationIncentiveMantissa;\n // Emit event with old incentive, new incentive\n emit NewLiquidationIncentive(0, _liquidationIncentiveMantissa);\n\n underWriterAdmin = _underWriterAdmin;\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 dynamic list with the assets the account has entered\n */\n function getAssetsIn(address account) external view returns (address[] memory) {\n address[] memory assetsIn = accountAssets[account];\n\n return assetsIn;\n }\n\n /**\n * @notice Returns whether the given account is entered in the given asset\n * @param account The address of the account to check\n * @param cToken The cToken to check\n * @return True if the account is in the asset, otherwise false.\n */\n function checkMembership(address account, address cToken) external view returns (bool) {\n return markets[cToken].accountMembership[account];\n }\n\n function isListed(address asset) external view returns (bool) {\n return markets[asset].isListed;\n }\n\n function marketGroupId(address asset) external view returns (uint8) {\n return markets[asset].assetGroupId;\n }\n\n /**\n * @notice Add assets to be included in account liquidity calculation\n * @param cTokens The list of addresses of the cToken markets to be enabled\n * @return Success indicator for whether each corresponding market was entered\n */\n function enterMarkets(address[] memory cTokens) public returns (uint256[] memory) {\n uint256 len = cTokens.length;\n\n uint256[] memory results = new uint256[](len);\n for (uint256 i = 0; i < len; ++i) {\n address cToken = cTokens[i];\n //IUnderwriterAdmin.AssetGroup memory eqAssets = underWriterAdmin.getAssetGroup(cToken);\n //results[i] = uint(addToMarketInternal(cToken, msg.sender, eqAssets.groupName, eqAssets.rateMantissas));\n results[i] = uint256(addToMarketInternal(cToken, msg.sender));\n }\n\n return results;\n }\n\n /**\n * @notice Add the market to the borrower's \"assets in\" for liquidity calculations\n * @param cToken The market to enter\n * @param borrower The address of the account to modify\n * @return Success indicator for whether the market was entered\n */\n function addToMarketInternal(address cToken, address borrower) internal returns (uint256) {\n Market storage marketToJoin = markets[cToken];\n\n require(marketToJoin.isListed, MARKET_NOT_LISTED);\n\n if (marketToJoin.accountMembership[borrower]) {\n // already joined\n return uint256(0);\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(cToken);\n\n // all tokens are grouped with equal assets.\n //addToEqualAssetGroupInternal(cToken, borrower, eqAssetGroup, rateMantissa);\n\n emit MarketEntered(cToken, borrower);\n\n return uint256(0);\n }\n\n /**\n * @notice Removes asset from sender's account liquidity calculation\n * @dev Sender must not have an outstanding borrow balance in the asset,\n * or be providing necessary collateral for an outstanding borrow.\n * @param cTokenAddress The address of the asset to be removed\n * @return Whether or not the account successfully exited the market\n */\n function exitMarket(address cTokenAddress) external returns (uint256) {\n address cToken = cTokenAddress;\n /* Get sender tokensHeld and amountOwed underlying from the cToken */\n (uint256 oErr, uint256 tokensHeld, uint256 amountOwed, ) = ICToken(cToken).getAccountSnapshot(msg.sender);\n require(oErr == 0, SNAPSHOT_ERROR); // semi-opaque error code\n\n /* Fail if the sender has a borrow balance */\n require(amountOwed == 0, 'nonzero borrow balance');\n\n /* Fail if the sender is not permitted to redeem all of their tokens */\n redeemAllowedInternal(cTokenAddress, msg.sender, tokensHeld);\n\n Market storage marketToExit = markets[cToken];\n\n /* Return true if the sender is not already ‘in’ the market */\n if (!marketToExit.accountMembership[msg.sender]) {\n return uint256(0);\n }\n\n /* Set cToken account membership to false */\n delete marketToExit.accountMembership[msg.sender];\n\n /* Delete cToken from the account’s list of assets */\n // load into memory for faster iteration\n address[] memory userAssetList = accountAssets[msg.sender];\n uint256 len = userAssetList.length;\n uint256 assetIndex = len;\n for (uint256 i = 0; i < len; ++i) {\n if (userAssetList[i] == cToken) {\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 address[] storage storedList = accountAssets[msg.sender];\n storedList[assetIndex] = storedList[storedList.length - 1];\n storedList.pop();\n\n // remove the same\n //exitEqualAssetGroupInternal(cTokenAddress, msg.sender);\n\n emit MarketExited(cToken, msg.sender);\n\n return uint256(0);\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 cToken The market to verify the mint against\n * @param minter The account which would get the minted tokens\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\n * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function mintAllowed(address cToken, address minter, uint256 mintAmount) external returns (uint256) {\n // Pausing is a very serious situation - we revert to sound the alarms\n //require(!mintGuardianPaused[cToken], \"mint is paused\");\n require(!underWriterAdmin._getMintPaused(cToken), 'mint paused');\n\n // Shh - currently unused: minter; mintAmount;\n\n require(markets[cToken].isListed, MARKET_NOT_LISTED);\n\n /* Get minter's cToken balance*/\n (uint256 oErr, uint256 tokensHeld, uint256 amountOwed, ) = ICToken(cToken).getAccountSnapshot(minter);\n require(oErr == 0, SNAPSHOT_ERROR); // semi-opaque error code\n\n // only enter market automatically at the first time\n if ((!markets[cToken].accountMembership[minter]) && (tokensHeld == 0) && (amountOwed == 0)) {\n // only cTokens may call mintAllowed if minter not in market\n require(msg.sender == cToken, 'sender must be cToken');\n\n // attempt to add borrower to the market\n addToMarketInternal(msg.sender, minter);\n\n // it should be impossible to break the important invariant\n assert(markets[cToken].accountMembership[minter]);\n }\n\n // Keep the flywheel moving\n compLogic.updateCompSupplyIndex(cToken);\n compLogic.distributeSupplierComp(cToken, minter);\n\n require(\n maxSupply[cToken] == 0 ||\n (maxSupply[cToken] > 0 && ICToken(cToken).totalSupply().add_(mintAmount) <= maxSupply[cToken]),\n 'cToken > maxSupply'\n );\n\n return uint256(0);\n }\n\n /**\n * @notice Checks if the account should be allowed to redeem tokens in the given market\n * @param cToken The market to verify the redeem against\n * @param redeemer The account which would redeem the tokens\n * @param redeemTokens The number of cTokens to exchange for the underlying asset in the market\n * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function redeemAllowed(address cToken, address redeemer, uint256 redeemTokens) external returns (uint256) {\n redeemAllowedInternal(cToken, redeemer, redeemTokens);\n\n // Keep the flywheel moving\n compLogic.updateCompSupplyIndex(cToken);\n compLogic.distributeSupplierComp(cToken, redeemer);\n\n return uint256(0);\n }\n\n function redeemAllowedInternal(\n address cToken,\n address redeemer,\n uint256 redeemTokens\n ) internal view returns (uint256) {\n require(markets[cToken].isListed, MARKET_NOT_LISTED);\n\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\n if (!markets[cToken].accountMembership[redeemer]) {\n return uint256(0);\n }\n\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\n (, , uint256 shortfall) = accountLiquidity.getHypotheticalAccountLiquidity(redeemer, cToken, redeemTokens, 0);\n require(shortfall == 0, INSUFFICIENT_LIQUIDITY);\n\n return uint256(0);\n }\n\n /**\n * @notice Validates redeem and reverts on rejection. May emit logs.\n * @param cToken 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 cToken, address redeemer, uint256 redeemAmount, uint256 redeemTokens) external {\n // Shh - currently unused: cToken; redeemer;\n\n // Require tokens is zero or amount is also zero\n if (redeemTokens == 0 && redeemAmount > 0) {\n revert('redeemTokens zero');\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\n * @param cToken The market to verify the borrow against\n * @param borrower The account which would borrow the asset\n * @param borrowAmount The amount of underlying the account would borrow\n * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function borrowAllowed(address cToken, address borrower, uint256 borrowAmount) external returns (uint256) {\n // Pausing is a very serious situation - we revert to sound the alarms\n //require(!borrowGuardianPaused[cToken], \"borrow is paused\");\n require(!underWriterAdmin._getBorrowPaused(cToken), 'borrow paused');\n\n require(markets[cToken].isListed, MARKET_NOT_LISTED);\n\n if (!markets[cToken].accountMembership[borrower]) {\n // only cTokens may call borrowAllowed if borrower not in market\n require(msg.sender == cToken, 'sender must be cToken');\n\n // attempt to add borrower to the market\n addToMarketInternal(msg.sender, borrower);\n\n // it should be impossible to break the important invariant\n assert(markets[cToken].accountMembership[borrower]);\n }\n\n require(oracle.getUnderlyingPrice(cToken) > 0, PRICE_ERROR);\n\n //uint borrowCap = borrowCaps[cToken];\n uint256 borrowCap = underWriterAdmin._getMarketBorrowCap(cToken);\n // Borrow cap of 0 corresponds to unlimited borrowing\n if (borrowCap != 0) {\n uint256 totalBorrows = ICToken(cToken).totalBorrows();\n uint256 nextTotalBorrows = totalBorrows.add_(borrowAmount);\n require(nextTotalBorrows < borrowCap, 'borrow cap reached');\n }\n\n (, , uint256 shortfall) = accountLiquidity.getHypotheticalAccountLiquidity(borrower, cToken, 0, borrowAmount);\n require(shortfall <= 0, INSUFFICIENT_LIQUIDITY);\n\n // Keep the flywheel moving\n Exp memory borrowIndex = Exp({mantissa: ICToken(cToken).borrowIndex()});\n compLogic.updateCompBorrowIndex(cToken, borrowIndex);\n compLogic.distributeBorrowerComp(cToken, borrower, borrowIndex);\n\n return uint256(0);\n }\n\n /**\n * @notice Checks if the account should be allowed to repay a borrow in the given market\n * @param cToken The market to verify the repay against\n * @param payer The account which would repay the asset\n * @param borrower The account which would borrowed the asset\n * @param repayAmount The amount of the underlying asset the account would repay\n * @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function repayBorrowAllowed(\n address cToken,\n address payer,\n address borrower,\n uint256 repayAmount\n ) external returns (uint256) {\n // Shh - currently unused: repayAmount;\n\n require(markets[cToken].isListed, MARKET_NOT_LISTED);\n\n // Keep the flywheel moving\n Exp memory borrowIndex = Exp({mantissa: ICToken(cToken).borrowIndex()});\n compLogic.updateCompBorrowIndex(cToken, borrowIndex);\n compLogic.distributeBorrowerComp(cToken, borrower, borrowIndex);\n\n return uint256(0);\n }\n\n /**\n * @notice Checks if the seizing of assets should be allowed to occur\n * @param cTokenCollateral Asset which was used as collateral and will be seized\n * @param cTokenBorrowed Asset which was borrowed by the borrower\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @param seizeTokens The number of collateral tokens to seize\n */\n function seizeAllowed(\n address cTokenCollateral,\n address cTokenBorrowed,\n address liquidator,\n address borrower,\n uint256 seizeTokens\n ) external returns (uint256) {\n // Pausing is a very serious situation - we revert to sound the alarms\n //require(!seizeGuardianPaused, \"seize is paused\");\n require(!underWriterAdmin._getSeizePaused(), 'seize paused');\n\n // Shh - currently unused: seizeTokens;\n\n require(markets[cTokenCollateral].isListed && markets[cTokenBorrowed].isListed, MARKET_NOT_LISTED);\n\n require(ICToken(cTokenCollateral).comptroller() == ICToken(cTokenBorrowed).comptroller(), 'comptroller mismatch');\n\n // Keep the flywheel moving\n compLogic.updateCompSupplyIndex(cTokenCollateral);\n compLogic.distributeSupplierComp(cTokenCollateral, borrower);\n compLogic.distributeSupplierComp(cTokenCollateral, liquidator);\n\n return uint256(0);\n }\n\n /**\n * @notice Checks if the account should be allowed to transfer tokens in the given market\n * @param cToken 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 cTokens to transfer\n * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function transferAllowed(\n address cToken,\n address src,\n address dst,\n uint256 transferTokens\n ) external returns (uint256) {\n // Pausing is a very serious situation - we revert to sound the alarms\n //require(!transferGuardianPaused, \"transfer is paused\");\n require(!underWriterAdmin._getTransferPaused(), 'transfer paused');\n\n // Currently the only consideration is whether or not\n // the src is allowed to redeem this many tokens\n redeemAllowedInternal(cToken, src, transferTokens);\n\n // Keep the flywheel moving\n compLogic.updateCompSupplyIndex(cToken);\n compLogic.distributeSupplierComp(cToken, src);\n compLogic.distributeSupplierComp(cToken, dst);\n\n return uint256(0);\n }\n\n /*** Liquidity/Liquidation Calculations ***/\n\n /**\n * @notice Determine the current account liquidity wrt collateral requirements\n * @return (possible error code (semi-opaque),\n account liquidity in excess of collateral requirements,\n * account shortfall below collateral requirements)\n */\n function getAccountLiquidity(address account) public view returns (uint256, uint256, uint256) {\n (uint256 err, uint256 liquidity, uint256 shortfall) = accountLiquidity.getHypotheticalAccountLiquidity(\n account,\n address(0),\n 0,\n 0\n );\n\n return (uint256(err), liquidity, shortfall);\n }\n\n /**\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\n * @param cTokenModify The market to hypothetically redeem/borrow in\n * @param account The account to determine liquidity for\n * @param redeemTokens The number of tokens to hypothetically redeem\n * @param borrowAmount The amount of underlying to hypothetically borrow\n * @return (possible error code (semi-opaque),\n hypothetical account liquidity in excess of collateral requirements,\n * hypothetical account shortfall below collateral requirements)\n */\n function getHypotheticalAccountLiquidity(\n address account,\n address cTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount\n ) public view returns (uint256, uint256, uint256) {\n (uint256 err, uint256 liquidity, uint256 shortfall) = accountLiquidity.getHypotheticalAccountLiquidity(\n account,\n address(cTokenModify),\n redeemTokens,\n borrowAmount\n );\n return (uint256(err), liquidity, shortfall);\n }\n\n /*** Admin Functions ***/\n\n function setMaxSupply(address cToken, uint256 amount) public onlyRole(DEFAULT_ADMIN_ROLE) returns (uint256) {\n // Check caller is admin\n maxSupply[cToken] = amount;\n emit SetMaxSupply(cToken, amount);\n return uint256(0);\n }\n\n /**\n * @notice Sets a new price oracle for the comptroller\n * @dev Admin function to set a new price oracle\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setPriceOracle(IPriceOracle newOracle) public onlyRole(DEFAULT_ADMIN_ROLE) returns (uint256) {\n // Check caller is admin\n // Track the old oracle for the comptroller\n IPriceOracle oldOracle = oracle;\n // Set comptroller's oracle to newOracle\n oracle = newOracle;\n // Emit NewPriceOracle(oldOracle, newOracle)\n emit NewPriceOracle(address(oldOracle), address(newOracle));\n return uint256(0);\n }\n\n /**\n * @notice Sets the closeFactor used when liquidating borrows\n * @dev Admin function to set closeFactor\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\n * @return uint 0=success, otherwise a failure\n */\n function _setCloseFactor(uint256 newCloseFactorMantissa) external onlyRole(DEFAULT_ADMIN_ROLE) returns (uint256) {\n // Check caller is admin\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\n closeFactorMantissa = newCloseFactorMantissa;\n emit NewCloseFactor(oldCloseFactorMantissa, closeFactorMantissa);\n\n return uint256(0);\n }\n\n function _setUnderWriterAdmin(\n IUnderwriterAdmin underWriter\n ) external onlyRole(DEFAULT_ADMIN_ROLE) returns (IUnderwriterAdmin) {\n // Check caller is admin\n require(address(underWriter) != address(0), 'Address is Zero!');\n underWriterAdmin = underWriter;\n return underWriter;\n }\n\n /**\n * @notice Sets liquidationIncentive\n * @dev Admin function to set liquidationIncentive\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\n * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\n */\n function _setLiquidationIncentive(\n uint256 newLiquidationIncentiveMantissa\n ) external onlyRole(DEFAULT_ADMIN_ROLE) returns (uint256) {\n // Check caller is admin\n // Save current value for use in log\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\n // Set liquidation incentive to new incentive\n liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\n // Emit event with old incentive, new incentive\n emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa);\n return uint256(0);\n }\n\n /**\n * @notice Add the market to the markets mapping and set it as listed\n * @dev Admin function to set isListed and add support for the market\n * @param cToken The address of the market (token) to list\n * @return uint 0=success, otherwise a failure. (See enum uint256 for details)\n */\n function _supportMarket(address cToken, uint8 groupId) external onlyRole(DEFAULT_ADMIN_ROLE) returns (uint256) {\n require(!markets[cToken].isListed, 'market already listed');\n\n // ICToken(cToken).isCToken(); // Sanity check to make sure its really a address\n (bool success, ) = cToken.call(abi.encodeWithSignature('isCToken()'));\n require(success && isContract(cToken), 'contract error!');\n\n // Note that isComped is not in active use anymore\n // markets[cToken] = Market({isListed: true, isComped: false, assetGroupId: groupId});\n Market storage market = markets[cToken];\n market.isListed = true;\n market.assetGroupId = groupId;\n\n _addMarketInternal(cToken);\n _initializeMarket(cToken);\n\n emit MarketListed(cToken);\n\n return uint256(0);\n }\n\n function _addMarketInternal(address cToken) internal {\n for (uint256 i = 0; i < allMarkets.length; ++i) {\n require(allMarkets[i] != cToken, 'market already added');\n }\n allMarkets.push(cToken);\n }\n\n function _initializeMarket(address cToken) internal {\n uint32 blockNumber = block.number.safe32('block number exceeds 32 bits');\n compLogic.initializeMarket(cToken, blockNumber);\n }\n\n function setCompSpeed(\n address cToken,\n uint256 supplySpeed,\n uint256 borrowSpeed\n ) external onlyRole(DEFAULT_ADMIN_ROLE) {\n compLogic.setCompSpeed(cToken, supplySpeed, borrowSpeed);\n }\n\n function setComptroller(ICompLogic _compLogic) external onlyRole(DEFAULT_ADMIN_ROLE) {\n compLogic = _compLogic;\n }\n\n function setAccountLiquidity(IAccountLiquidity _accountLiquidity) external onlyRole(DEFAULT_ADMIN_ROLE) {\n accountLiquidity = _accountLiquidity;\n }\n\n /**\n * @notice Return all of the markets\n * @dev The automatic getter may be used to access an individual market.\n * @return The list of market addresses\n */\n function getAllMarkets() public view returns (address[] memory) {\n return allMarkets;\n }\n\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n size := extcodesize(account)\n }\n return size > 0;\n }\n}\n" }, "contracts/Comptroller/ComptrollerStorage.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\ncontract ComptrollerStorage {\n /// @notice Indicator that this is a Comptroller contract (for inspection)\n bool public constant isComptroller = true;\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 string internal constant INSUFFICIENT_LIQUIDITY = \"insufficient liquidity\";\n string internal constant MARKET_NOT_LISTED = \"market not listed\";\n string internal constant UNAUTHORIZED = \"unauthorized\";\n string internal constant PRICE_ERROR = \"price error\";\n string internal constant SNAPSHOT_ERROR = \"snapshot error\";\n /**\n * @notice Per-account mapping of \"assets you are in\", capped by maxAssets\n */\n mapping(address => address[]) public accountAssets;\n /// @notice Whether or not this market is listed\n /// @notice Per-market mapping of \"accounts in this asset\"\n /// @notice Whether or not this market receives COMP\n struct Market {\n bool isListed;\n uint8 assetGroupId;\n mapping(address => bool) accountMembership;\n bool isComped;\n }\n\n /**\n * @notice Official mapping of cTokens -> 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 address[] public allMarkets;\n\n mapping(address => uint256) public maxSupply;\n\n /// @notice Emitted when an admin supports a market\n event MarketListed(address cToken);\n\n /// @notice Emitted when an account enters a market\n event MarketEntered(address cToken, address account);\n\n /// @notice Emitted when an account exits a market\n event MarketExited(address cToken, address account);\n\n /// @notice Emitted when close factor is changed by admin\n event NewCloseFactor(\n uint256 oldCloseFactorMantissa,\n uint256 newCloseFactorMantissa\n );\n\n /// @notice Emitted when liquidation incentive is changed by admin\n event NewLiquidationIncentive(\n uint256 oldLiquidationIncentiveMantissa,\n uint256 newLiquidationIncentiveMantissa\n );\n\n /// @notice Emitted when price oracle is changed\n event NewPriceOracle(address oldPriceOracle, address newPriceOracle);\n\n event SetMaxSupply(address indexed cToken, uint256 amount);\n}\n" }, "contracts/Comptroller/Interfaces/ICToken.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\ninterface ICToken {\n function comptroller() external view returns (address);\n\n function reserveFactorMantissa() external view returns (uint256);\n\n function borrowIndex() external view returns (uint256);\n\n function totalBorrows() external view returns (uint256);\n\n function totalSupply() external view returns (uint256);\n\n function isCToken() external view returns (bool);\n\n function balanceOf(address owner) external view returns (uint256);\n\n function getAccountSnapshot(address account)\n external\n view\n returns (\n uint256,\n uint256,\n uint256,\n uint256\n );\n\n function borrowBalanceStored(address account) external view returns (uint256);\n\n function exchangeRateStored() external view returns (uint256);\n\n function underlying() external view returns (address);\n\n function exchangeRateCurrent() external returns (uint256);\n\n function isCEther() external view returns (bool);\n\n function supplyRatePerBlock() external view returns (uint256);\n\n function borrowRatePerBlock() external view returns (uint256);\n\n function totalReserves() external view returns (uint256);\n\n function getCash() external view returns (uint256);\n\n function decimals() external view returns (uint8);\n\n function borrowBalanceCurrent(address account) external returns (uint256);\n\n function balanceOfUnderlying(address owner) external returns (uint256);\n\n function allowance(address owner, address spender) external view returns (uint256);\n\n function getCurrentVotes(address account) external view returns (uint96);\n\n function delegates(address) external view returns (address);\n\n function getPriorVotes(address account, uint256 blockNumber) external view returns (uint96);\n\n function getDiscountRate() external view returns (uint256);\n}\n" }, "contracts/Comptroller/UnderWriterAdmin.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\nimport './ComptrollerErrorReporter.sol';\nimport './UnderwriterStorage.sol';\nimport './Interfaces/IPriceOracle.sol';\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\n\ncontract UnderwriterAdmin is IUnderwriterAdmin, UnderwriterStorage, Initializable {\n function initialize(address _gov, address _admin) public initializer {\n admin = _admin;\n governanceToken = _gov;\n suTokenRateMantissa = 10**18;\n }\n\n function setAssetGroup(\n uint8 groupId,\n string memory groupName,\n uint256 intraCRateMantissa, // ctoken collateral rate for intra group ctoken liability\n uint256 intraMintRateMantissa, // ctoken collateral rate for intra group sutoken liability\n uint256 intraSuRateMantissa, // sutoken collateral rate for intra group ctoken liability\n uint256 interCRateMantissa, // ctoken collateral rate for inter group ctoken/sutoken liability\n uint256 interSuRateMantissa // sutoken collateral rate for inter group ctoken/sutoken liability\n ) public returns (uint256) {\n // Check caller is admin\n if (msg.sender != admin) {\n return\n ComptrollerErrorReporter.fail(\n ComptrollerErrorReporter.Error.UNAUTHORIZED,\n ComptrollerErrorReporter.FailureInfo.SET_EQUAL_ASSET_GROUP_OWNER_CHECK\n );\n }\n\n eqAssetGroup[groupId] = AssetGroup(\n groupId,\n groupName,\n intraCRateMantissa,\n intraMintRateMantissa,\n intraSuRateMantissa,\n interCRateMantissa,\n interSuRateMantissa\n );\n equalAssetsGroupNum++;\n emit NewAssetGroup(\n groupId,\n groupName,\n intraCRateMantissa,\n intraMintRateMantissa,\n intraSuRateMantissa,\n interCRateMantissa,\n interSuRateMantissa,\n equalAssetsGroupNum\n );\n return uint256(ComptrollerErrorReporter.Error.NO_ERROR);\n }\n\n function removeAssetGroup(uint8 groupId) public returns (uint256) {\n // Check caller is admin\n if (msg.sender != admin) {\n return\n ComptrollerErrorReporter.fail(\n ComptrollerErrorReporter.Error.UNAUTHORIZED,\n ComptrollerErrorReporter.FailureInfo.SET_EQUAL_ASSET_GROUP_OWNER_CHECK\n );\n }\n\n delete eqAssetGroup[groupId];\n equalAssetsGroupNum--;\n emit RemoveAssetGroup(groupId, equalAssetsGroupNum);\n return uint256(ComptrollerErrorReporter.Error.NO_ERROR);\n }\n\n function getAssetGroup(uint8 groupId) public view override returns (AssetGroup memory) {\n return eqAssetGroup[groupId];\n }\n\n function getAssetGroupNum() public view override returns (uint8) {\n return equalAssetsGroupNum;\n }\n\n /**\n * @notice Admin function to change the Pause Guardian\n * @param newPauseGuardian The address of the new Pause Guardian\n * @return uint 0=success, otherwise a failure. (See enum Error for details)\n */\n function _setPauseGuardian(address newPauseGuardian) public returns (uint256) {\n if (msg.sender != admin) {\n return\n ComptrollerErrorReporter.fail(\n ComptrollerErrorReporter.Error.UNAUTHORIZED,\n ComptrollerErrorReporter.FailureInfo.SET_PAUSE_GUARDIAN_OWNER_CHECK\n );\n }\n require(newPauseGuardian != address(0), 'Address is Zero!');\n\n // Save current value for inclusion in log\n address oldPauseGuardian = pauseGuardian;\n\n // Store pauseGuardian with value newPauseGuardian\n pauseGuardian = newPauseGuardian;\n\n // Emit NewPauseGuardian(OldPauseGuardian, NewPauseGuardian)\n emit NewPauseGuardian(oldPauseGuardian, pauseGuardian);\n\n return uint256(ComptrollerErrorReporter.Error.NO_ERROR);\n }\n\n function _getPauseGuardian() public view returns (address) {\n return pauseGuardian;\n }\n\n function _setMintPaused(ICToken cToken, bool state) public returns (bool) {\n //require(markets[address(cToken)].isListed, \"cannot pause a market that is not listed\");\n require(msg.sender == pauseGuardian || msg.sender == admin, 'only pause guardian and admin can pause');\n require(msg.sender == admin || state, 'only admin can unpause');\n\n mintGuardianPaused[address(cToken)] = state;\n emit ActionPaused(address(cToken), 'Mint', state);\n return state;\n }\n\n function _getMintPaused(address cToken) public view override returns (bool) {\n return mintGuardianPaused[cToken];\n }\n\n function _setBorrowPaused(ICToken cToken, bool state) public returns (bool) {\n //require(markets[address(cToken)].isListed, \"cannot pause a market that is not listed\");\n require(msg.sender == pauseGuardian || msg.sender == admin, 'only pause guardian and admin can pause');\n require(msg.sender == admin || state, 'only admin can unpause');\n\n borrowGuardianPaused[address(cToken)] = state;\n emit ActionPaused(address(cToken), 'Borrow', state);\n return state;\n }\n\n function _getBorrowPaused(address cToken) public view override returns (bool) {\n return borrowGuardianPaused[cToken];\n }\n\n function _setTransferPaused(bool state) public returns (bool) {\n require(msg.sender == pauseGuardian || msg.sender == admin, 'only pause guardian and admin can pause');\n require(msg.sender == admin || state, 'only admin can unpause');\n\n transferGuardianPaused = state;\n emit ActionPaused(address(0), 'Transfer', state);\n return state;\n }\n\n function _getTransferPaused() public view override returns (bool) {\n return transferGuardianPaused;\n }\n\n function _setSeizePaused(bool state) public returns (bool) {\n require(msg.sender == pauseGuardian || msg.sender == admin, 'only pause guardian and admin can pause');\n require(msg.sender == admin || state, 'only admin can unpause');\n\n seizeGuardianPaused = state;\n emit ActionPaused(address(0), 'Seize', state);\n return state;\n }\n\n function _getSeizePaused() public view override returns (bool) {\n return seizeGuardianPaused;\n }\n\n /**\n * @notice Return the address of the COMP token\n * @return The address of COMP\n */\n function getCompAddress() public view override returns (address) {\n /*\n return 0xc00e94Cb662C3520282E6f5717214004A7f26888;\n */\n return governanceToken;\n }\n\n /**\n * @notice Return the address of the COMP token\n * @param _governanceToken The address of COMP(governance token)\n */\n function setGovTokenAddress(address _governanceToken) public {\n //require(adminOrInitializing(), \"only admin can set governanceToken\");\n require(msg.sender == admin, 'only admin can set');\n require(_governanceToken != address(0), 'Address is Zero!');\n governanceToken = _governanceToken;\n }\n\n /**\n * @notice Set the given borrow caps for the given cToken markets. Borrowing that brings total borrows to or above borrow cap will revert.\n * @dev Admin or borrowCapGuardian function to set the borrow caps. A borrow cap of 0 corresponds to unlimited borrowing.\n * @param cTokens The addresses of the markets (tokens) to change the borrow caps for\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of 0 corresponds to unlimited borrowing.\n */\n function _setMarketBorrowCaps(ICToken[] calldata cTokens, uint256[] calldata newBorrowCaps) external {\n require(\n msg.sender == admin || msg.sender == borrowCapGuardian,\n 'only admin or borrow cap guardian can set borrow caps'\n );\n\n uint256 numMarkets = cTokens.length;\n uint256 numBorrowCaps = newBorrowCaps.length;\n\n require(numMarkets != 0 && numMarkets == numBorrowCaps, 'invalid input');\n\n for (uint256 i = 0; i < numMarkets; i++) {\n borrowCaps[address(cTokens[i])] = newBorrowCaps[i];\n emit NewBorrowCap(address(cTokens[i]), newBorrowCaps[i]);\n }\n }\n\n function _getMarketBorrowCap(address cToken) external view override returns (uint256) {\n return borrowCaps[cToken];\n }\n\n /**\n * @notice Admin function to change the Borrow Cap Guardian\n * @param newBorrowCapGuardian The address of the new Borrow Cap Guardian\n */\n function _setBorrowCapGuardian(address newBorrowCapGuardian) external {\n require(msg.sender == admin, 'only admin can set borrow cap guardian');\n require(newBorrowCapGuardian != address(0), 'Address is Zero!');\n\n // Save current value for inclusion in log\n address oldBorrowCapGuardian = borrowCapGuardian;\n\n // Store borrowCapGuardian with value newBorrowCapGuardian\n borrowCapGuardian = newBorrowCapGuardian;\n\n // Emit NewBorrowCapGuardian(OldBorrowCapGuardian, NewBorrowCapGuardian)\n emit NewBorrowCapGuardian(oldBorrowCapGuardian, newBorrowCapGuardian);\n }\n\n function _getBorrowCapGuardian() external view returns (address) {\n return borrowCapGuardian;\n }\n\n}\n" }, "contracts/Comptroller/ComptrollerErrorReporter.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\nlibrary ComptrollerErrorReporter {\n enum Error {\n NO_ERROR,\n UNAUTHORIZED,\n COMPTROLLER_MISMATCH,\n INSUFFICIENT_SHORTFALL,\n INSUFFICIENT_LIQUIDITY,\n INVALID_CLOSE_FACTOR,\n INVALID_COLLATERAL_FACTOR,\n INVALID_LIQUIDATION_INCENTIVE,\n MARKET_NOT_ENTERED,\n MARKET_NOT_LISTED,\n MARKET_ALREADY_LISTED,\n MATH_ERROR,\n NONZERO_BORROW_BALANCE,\n PRICE_ERROR,\n REJECTION,\n SNAPSHOT_ERROR,\n TOO_MANY_ASSETS,\n TOO_MUCH_REPAY\n }\n\n enum FailureInfo {\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\n EXIT_MARKET_BALANCE_OWED,\n EXIT_MARKET_REJECTION,\n SET_CLOSE_FACTOR_OWNER_CHECK,\n SET_CLOSE_FACTOR_VALIDATION,\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\n SET_COLLATERAL_FACTOR_NO_EXISTS,\n SET_COLLATERAL_FACTOR_VALIDATION,\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\n SET_IMPLEMENTATION_OWNER_CHECK,\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\n SET_MAX_ASSETS_OWNER_CHECK,\n SET_PENDING_ADMIN_OWNER_CHECK,\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\n SET_PRICE_ORACLE_OWNER_CHECK,\n SUPPORT_MARKET_EXISTS,\n SUPPORT_MARKET_OWNER_CHECK,\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\n SET_EQUAL_ASSET_GROUP_OWNER_CHECK\n }\n\n /**\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\n **/\n event Failure(uint256 error, uint256 info, uint256 detail);\n\n error ComptrollerError(uint256 errorCode, uint256 infoCode, uint256 detailCode);\n\n /**\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\n */\n function fail(Error err, FailureInfo info) internal returns (uint256) {\n\n // emit Failure(uint256(err), uint256(info), 0);\n revert ComptrollerError(uint256(err), uint256(info), 0);\n // return uint256(err);\n }\n\n /**\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\n */\n function failOpaque(\n Error err,\n FailureInfo info,\n uint256 opaqueError\n ) internal returns (uint256) {\n // emit Failure(uint256(err), uint256(info), opaqueError);\n revert ComptrollerError(uint256(err), uint256(info), opaqueError);\n // return uint256(err);\n }\n}\n" }, "contracts/Comptroller/UnderwriterStorage.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\npragma experimental ABIEncoderV2;\nimport './Interfaces/ICToken.sol';\nimport './Interfaces/IUnderwriterAdmin.sol';\n\ncontract UnderwriterStorage {\n /**\n * @notice Administrator for this contract\n */\n address public admin;\n address public governanceToken;\n\n uint256 public suTokenRateMantissa;\n\n /**\n * @notice eqAssetGroup, cToken -> equal assets info.\n */\n\n uint8 public equalAssetsGroupNum;\n /**\n * @notice eqAssetGroup, groupId -> equal assets info.\n */\n mapping(uint8 => IUnderwriterAdmin.AssetGroup) public eqAssetGroup;\n\n /**\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\n * Actions which allow users to remove their own assets cannot be paused.\n * Liquidation / seizing / transfer can only be paused globally, not by market.\n */\n address public pauseGuardian;\n bool public _mintGuardianPaused;\n bool public _borrowGuardianPaused;\n bool public transferGuardianPaused;\n bool public seizeGuardianPaused;\n mapping(address => bool) public mintGuardianPaused;\n mapping(address => bool) public borrowGuardianPaused;\n\n // @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\n address public borrowCapGuardian;\n\n // @notice Borrow caps enforced by borrowAllowed for each cToken address. Defaults to zero which corresponds to unlimited borrowing.\n mapping(address => uint256) public borrowCaps;\n}\n" }, "contracts/Comptroller/CompoundLens.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\nimport './Interfaces/ICToken.sol';\nimport './Interfaces/IPriceOracle.sol';\nimport './Interfaces/IGovernorAlpha.sol';\nimport './Interfaces/IComptroller.sol';\nimport './Interfaces/IGovernorBravo.sol';\nimport './Interfaces/IUnderwriterAdmin.sol';\nimport '../Exponential/ExponentialNoError.sol';\nimport './ComptrollerStorage.sol';\n\ncontract CompoundLens {\n using ExponentialNoError for uint256;\n using ExponentialNoError for Exp;\n using ExponentialNoError for Double;\n struct CTokenMetadata {\n address cToken;\n uint256 exchangeRateCurrent;\n uint256 supplyRatePerBlock;\n uint256 borrowRatePerBlock;\n uint256 reserveFactorMantissa;\n uint256 totalBorrows;\n uint256 totalReserves;\n uint256 totalSupply;\n uint256 totalCash;\n bool isListed;\n // uint256 collateralFactorMantissa;\n address underlyingAssetAddress;\n uint256 cTokenDecimals;\n uint256 underlyingDecimals;\n bool isCToken;\n bool isCEther;\n uint256 borrowCap;\n uint256 depositCap;\n uint256 liquidationIncentive;\n uint8 groupId;\n uint256 intraRate;\n uint256 mintRate;\n uint256 interRate;\n uint256 discountRate;\n }\n\n struct GroupInfo {\n uint256 intraRate;\n uint256 mintRate;\n uint256 interRate;\n }\n\n function cTokenMetadata(ICToken cToken) public returns (CTokenMetadata memory) {\n IComptroller comptroller = IComptroller(address(cToken.comptroller()));\n IUnderwriterAdmin ua = IUnderwriterAdmin(comptroller.underWriterAdmin());\n\n // get underlying info\n address underlyingAssetAddress;\n uint256 underlyingDecimals;\n if (cToken.isCEther()) {\n underlyingAssetAddress = address(0);\n underlyingDecimals = 18;\n } else {\n underlyingAssetAddress = cToken.underlying();\n underlyingDecimals = ICToken(cToken.underlying()).decimals();\n }\n\n // get group info\n (bool isListed, uint8 assetGroupId, ) = comptroller.markets(address(cToken));\n IUnderwriterAdmin.AssetGroup memory group = ua.getAssetGroup(assetGroupId);\n GroupInfo memory gi;\n if (cToken.isCToken()) {\n gi.intraRate = group.intraCRateMantissa;\n gi.interRate = group.interCRateMantissa;\n gi.mintRate = group.intraMintRateMantissa;\n } else {\n gi.intraRate = group.intraSuRateMantissa;\n gi.interRate = group.interSuRateMantissa;\n gi.mintRate = group.intraSuRateMantissa;\n }\n\n return\n CTokenMetadata({\n cToken: address(cToken),\n exchangeRateCurrent: cToken.exchangeRateCurrent(),\n supplyRatePerBlock: cToken.supplyRatePerBlock(),\n borrowRatePerBlock: cToken.borrowRatePerBlock(),\n reserveFactorMantissa: cToken.reserveFactorMantissa(),\n totalBorrows: cToken.totalBorrows(),\n totalReserves: cToken.totalReserves(),\n totalSupply: cToken.totalSupply(),\n totalCash: cToken.getCash(),\n isListed: isListed,\n underlyingAssetAddress: underlyingAssetAddress,\n cTokenDecimals: cToken.decimals(),\n underlyingDecimals: underlyingDecimals,\n isCToken: cToken.isCToken(),\n isCEther: cToken.isCEther(),\n borrowCap: ua._getMarketBorrowCap(address(cToken)),\n depositCap: ComptrollerStorage(address(comptroller)).maxSupply(address(cToken)),\n liquidationIncentive: comptroller.liquidationIncentiveMantissa(),\n groupId: assetGroupId,\n intraRate: gi.intraRate,\n interRate: gi.interRate,\n mintRate: gi.mintRate,\n discountRate: cToken.getDiscountRate()\n });\n }\n\n function cTokenMetadataAll(ICToken[] calldata cTokens) external returns (CTokenMetadata[] memory) {\n uint256 cTokenCount = cTokens.length;\n CTokenMetadata[] memory res = new CTokenMetadata[](cTokenCount);\n for (uint256 i = 0; i < cTokenCount; i++) {\n res[i] = cTokenMetadata(cTokens[i]);\n }\n return res;\n }\n\n struct CTokenBalances {\n address cToken;\n bool isCToken;\n bool isCEther;\n uint256 balanceOf;\n uint256 borrowBalanceCurrent;\n uint256 balanceOfUnderlying;\n uint256 tokenBalance;\n uint256 tokenAllowance;\n }\n\n function cTokenBalances(ICToken cToken, address payable account) public returns (CTokenBalances memory) {\n uint256 balanceOf = cToken.balanceOf(account);\n uint256 borrowBalanceCurrent = cToken.borrowBalanceCurrent(account);\n uint256 balanceOfUnderlying = cToken.balanceOfUnderlying(account);\n uint256 tokenBalance;\n uint256 tokenAllowance;\n\n if (cToken.isCEther()) {\n tokenBalance = account.balance;\n tokenAllowance = account.balance;\n } else {\n ICToken underlying = ICToken(cToken.underlying());\n tokenBalance = underlying.balanceOf(account);\n tokenAllowance = underlying.allowance(account, address(cToken));\n }\n\n return\n CTokenBalances({\n cToken: address(cToken),\n isCToken: cToken.isCToken(),\n isCEther: cToken.isCEther(),\n balanceOf: balanceOf,\n borrowBalanceCurrent: borrowBalanceCurrent,\n balanceOfUnderlying: balanceOfUnderlying,\n tokenBalance: tokenBalance,\n tokenAllowance: tokenAllowance\n });\n }\n\n function cTokenBalancesAll(\n ICToken[] calldata cTokens,\n address payable account\n ) external returns (CTokenBalances[] memory) {\n uint256 cTokenCount = cTokens.length;\n CTokenBalances[] memory res = new CTokenBalances[](cTokenCount);\n for (uint256 i = 0; i < cTokenCount; i++) {\n res[i] = cTokenBalances(cTokens[i], account);\n }\n return res;\n }\n\n struct CTokenUnderlyingPrice {\n address cToken;\n uint256 underlyingPrice;\n }\n\n function cTokenUnderlyingPrice(ICToken cToken) public view returns (CTokenUnderlyingPrice memory) {\n IComptroller comptroller = IComptroller(address(cToken.comptroller()));\n IPriceOracle priceOracle = IPriceOracle(comptroller.oracle());\n\n return\n CTokenUnderlyingPrice({\n cToken: address(cToken),\n underlyingPrice: priceOracle.getUnderlyingPrice(address(cToken))\n });\n }\n\n function cTokenUnderlyingPriceAll(ICToken[] calldata cTokens) external view returns (CTokenUnderlyingPrice[] memory) {\n uint256 cTokenCount = cTokens.length;\n CTokenUnderlyingPrice[] memory res = new CTokenUnderlyingPrice[](cTokenCount);\n for (uint256 i = 0; i < cTokenCount; i++) {\n res[i] = cTokenUnderlyingPrice(cTokens[i]);\n }\n return res;\n }\n\n struct AccountLimits {\n address[] markets;\n uint256 liquidity;\n uint256 shortfall;\n }\n\n function getAccountLimits(IComptroller comptroller, address account) public returns (AccountLimits memory) {\n (uint256 errorCode, uint256 liquidity, uint256 shortfall) = comptroller.getAccountLiquidity(account);\n require(errorCode == 0);\n\n return AccountLimits({markets: comptroller.getAssetsIn(account), liquidity: liquidity, shortfall: shortfall});\n }\n\n struct GovReceipt {\n uint256 proposalId;\n bool hasVoted;\n bool support;\n uint96 votes;\n }\n\n function getGovReceipts(\n IGovernorAlpha governor,\n address voter,\n uint256[] memory proposalIds\n ) public view returns (GovReceipt[] memory) {\n uint256 proposalCount = proposalIds.length;\n GovReceipt[] memory res = new GovReceipt[](proposalCount);\n for (uint256 i = 0; i < proposalCount; i++) {\n IGovernorAlpha.Receipt memory receipt;\n\n (receipt.hasVoted, receipt.support, receipt.votes) = governor.getReceipt(proposalIds[i], voter);\n res[i] = GovReceipt({\n proposalId: proposalIds[i],\n hasVoted: receipt.hasVoted,\n support: receipt.support,\n votes: receipt.votes\n });\n }\n return res;\n }\n\n struct GovBravoReceipt {\n uint256 proposalId;\n bool hasVoted;\n uint8 support;\n uint96 votes;\n }\n\n function getGovBravoReceipts(\n IGovernorBravo governor,\n address voter,\n uint256[] memory proposalIds\n ) public view returns (GovBravoReceipt[] memory) {\n uint256 proposalCount = proposalIds.length;\n GovBravoReceipt[] memory res = new GovBravoReceipt[](proposalCount);\n for (uint256 i = 0; i < proposalCount; i++) {\n IGovernorBravo.Receipt memory receipt = governor.getReceipt(proposalIds[i], voter);\n res[i] = GovBravoReceipt({\n proposalId: proposalIds[i],\n hasVoted: receipt.hasVoted,\n support: receipt.support,\n votes: receipt.votes\n });\n }\n return res;\n }\n\n struct GovProposal {\n uint256 proposalId;\n address proposer;\n uint256 eta;\n address[] targets;\n uint256[] values;\n string[] signatures;\n bytes[] calldatas;\n uint256 startBlock;\n uint256 endBlock;\n uint256 forVotes;\n uint256 againstVotes;\n bool canceled;\n bool executed;\n }\n\n function setProposal(GovProposal memory res, IGovernorAlpha governor, uint256 proposalId) internal view {\n (\n ,\n address proposer,\n uint256 eta,\n uint256 startBlock,\n uint256 endBlock,\n uint256 forVotes,\n uint256 againstVotes,\n bool canceled,\n bool executed\n ) = governor.proposals(proposalId);\n res.proposalId = proposalId;\n res.proposer = proposer;\n res.eta = eta;\n res.startBlock = startBlock;\n res.endBlock = endBlock;\n res.forVotes = forVotes;\n res.againstVotes = againstVotes;\n res.canceled = canceled;\n res.executed = executed;\n }\n\n function getGovProposals(\n IGovernorAlpha governor,\n uint256[] calldata proposalIds\n ) external view returns (GovProposal[] memory) {\n GovProposal[] memory res = new GovProposal[](proposalIds.length);\n for (uint256 i = 0; i < proposalIds.length; i++) {\n (\n address[] memory targets,\n uint256[] memory values,\n string[] memory signatures,\n bytes[] memory calldatas\n ) = governor.getActions(proposalIds[i]);\n res[i] = GovProposal({\n proposalId: 0,\n proposer: address(0),\n eta: 0,\n targets: targets,\n values: values,\n signatures: signatures,\n calldatas: calldatas,\n startBlock: 0,\n endBlock: 0,\n forVotes: 0,\n againstVotes: 0,\n canceled: false,\n executed: false\n });\n setProposal(res[i], governor, proposalIds[i]);\n }\n return res;\n }\n\n struct GovBravoProposal {\n uint256 proposalId;\n address proposer;\n uint256 eta;\n address[] targets;\n uint256[] values;\n string[] signatures;\n bytes[] calldatas;\n uint256 startBlock;\n uint256 endBlock;\n uint256 forVotes;\n uint256 againstVotes;\n uint256 abstainVotes;\n bool canceled;\n bool executed;\n }\n\n function setBravoProposal(GovBravoProposal memory res, IGovernorBravo governor, uint256 proposalId) internal view {\n IGovernorBravo.Proposal memory p = governor.proposals(proposalId);\n\n res.proposalId = proposalId;\n res.proposer = p.proposer;\n res.eta = p.eta;\n res.startBlock = p.startBlock;\n res.endBlock = p.endBlock;\n res.forVotes = p.forVotes;\n res.againstVotes = p.againstVotes;\n res.abstainVotes = p.abstainVotes;\n res.canceled = p.canceled;\n res.executed = p.executed;\n }\n\n function getGovBravoProposals(\n IGovernorBravo governor,\n uint256[] calldata proposalIds\n ) external view returns (GovBravoProposal[] memory) {\n GovBravoProposal[] memory res = new GovBravoProposal[](proposalIds.length);\n for (uint256 i = 0; i < proposalIds.length; i++) {\n (\n address[] memory targets,\n uint256[] memory values,\n string[] memory signatures,\n bytes[] memory calldatas\n ) = governor.getActions(proposalIds[i]);\n res[i] = GovBravoProposal({\n proposalId: 0,\n proposer: address(0),\n eta: 0,\n targets: targets,\n values: values,\n signatures: signatures,\n calldatas: calldatas,\n startBlock: 0,\n endBlock: 0,\n forVotes: 0,\n againstVotes: 0,\n abstainVotes: 0,\n canceled: false,\n executed: false\n });\n setBravoProposal(res[i], governor, proposalIds[i]);\n }\n return res;\n }\n\n struct CompBalanceMetadata {\n uint256 balance;\n uint256 votes;\n address delegate;\n }\n\n function getCompBalanceMetadata(ICToken comp, address account) external view returns (CompBalanceMetadata memory) {\n return\n CompBalanceMetadata({\n balance: comp.balanceOf(account),\n votes: uint256(comp.getCurrentVotes(account)),\n delegate: comp.delegates(account)\n });\n }\n\n struct CompBalanceMetadataExt {\n uint256 balance;\n uint256 votes;\n address delegate;\n uint256 allocated;\n }\n\n function getCompBalanceMetadataExt(\n ICToken comp,\n IComptroller comptroller,\n address account\n ) external returns (CompBalanceMetadataExt memory) {\n uint256 balance = comp.balanceOf(account);\n comptroller.claimComp(account);\n uint256 newBalance = comp.balanceOf(account);\n uint256 accrued = comptroller.compAccrued(account);\n uint256 total = add(accrued, newBalance, 'sum comp total');\n uint256 allocated = sub(total, balance, 'sub allocated');\n\n return\n CompBalanceMetadataExt({\n balance: balance,\n votes: uint256(comp.getCurrentVotes(account)),\n delegate: comp.delegates(account),\n allocated: allocated\n });\n }\n\n struct CompVotes {\n uint256 blockNumber;\n uint256 votes;\n }\n\n function getCompVotes(\n ICToken comp,\n address account,\n uint32[] calldata blockNumbers\n ) external view returns (CompVotes[] memory) {\n CompVotes[] memory res = new CompVotes[](blockNumbers.length);\n for (uint256 i = 0; i < blockNumbers.length; i++) {\n res[i] = CompVotes({\n blockNumber: uint256(blockNumbers[i]),\n votes: uint256(comp.getPriorVotes(account, blockNumbers[i]))\n });\n }\n return res;\n }\n\n function compareStrings(string memory a, string memory b) internal pure returns (bool) {\n return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));\n }\n\n function add(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, errorMessage);\n return c;\n }\n\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n uint256 c = a - b;\n return c;\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 ICToken(cToken).liquidateBorrowFresh)\n * @param cTokenBorrowed The address of the borrowed cToken\n * @param cTokenCollateral The address of the collateral cToken\n * @param actualRepayAmount The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens\n * @return (errorCode, number of cTokenCollateral tokens to be seized in a liquidation)\n */\n function liquidateCalculateSeizeTokens(\n address cTokenBorrowed,\n address cTokenCollateral,\n uint256 actualRepayAmount,\n IComptroller comptroller\n ) external view returns (uint256, uint256) {\n /* Read oracle prices for borrowed and collateral markets */\n address oracle = comptroller.oracle();\n uint256 priceBorrowedMantissa = IPriceOracle(oracle).getUnderlyingPrice(address(cTokenBorrowed));\n uint256 priceCollateralMantissa = IPriceOracle(oracle).getUnderlyingPrice(address(cTokenCollateral));\n require(priceBorrowedMantissa > 0 && priceCollateralMantissa > 0, 'PRICE_ERROR');\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 = ICToken(cTokenCollateral).exchangeRateStored(); // Note: reverts on error\n uint256 seizeTokens;\n Exp memory numerator;\n Exp memory denominator;\n Exp memory ratio;\n\n numerator = Exp({mantissa: comptroller.liquidationIncentiveMantissa()}).mul_(\n Exp({mantissa: priceBorrowedMantissa})\n );\n denominator = Exp({mantissa: priceCollateralMantissa}).mul_(Exp({mantissa: exchangeRateMantissa}));\n ratio = numerator.div_(denominator);\n\n seizeTokens = ratio.mul_ScalarTruncate(actualRepayAmount);\n\n return (uint256(0), seizeTokens);\n }\n\n /**\n * @notice Returns true if the given cToken market has been deprecated\n * @dev All borrows in a deprecated cToken market can be immediately liquidated\n * @param cToken The market to check if deprecated\n */\n function isDeprecated(address cToken, IComptroller comptroller) public view returns (bool) {\n return\n comptroller.marketGroupId(cToken) == 0 &&\n //borrowGuardianPaused[cToken] == true &&\n IUnderwriterAdmin(comptroller.underWriterAdmin())._getBorrowPaused(cToken) &&\n ICToken(cToken).reserveFactorMantissa() == 1e18;\n }\n\n /**\n * @notice Checks if the liquidation should be allowed to occur\n * @param cTokenBorrowed Asset which was borrowed by the borrower\n * @param cTokenCollateral Asset which was used as collateral and will be seized\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @param repayAmount The amount of underlying being repaid\n */\n function liquidateBorrowAllowed(\n address cTokenBorrowed,\n address cTokenCollateral,\n address liquidator,\n address borrower,\n uint256 repayAmount,\n IComptroller comptroller\n ) external view returns (uint256) {\n // Shh - currently unused: liquidator;\n\n require(comptroller.isListed(cTokenBorrowed) && comptroller.isListed(cTokenCollateral), 'MARKET_NOT_LISTED');\n\n uint256 borrowBalance = ICToken(cTokenBorrowed).borrowBalanceStored(borrower);\n\n /* allow accounts to be liquidated if the market is deprecated */\n if (isDeprecated(cTokenBorrowed, comptroller)) {\n require(borrowBalance >= repayAmount, 'too much repay');\n } else {\n /* The borrower must have shortfall in order to be liquidatable */\n (, , uint256 shortfall) = comptroller.getHypotheticalAccountLiquidity(borrower, cTokenBorrowed, 0, 0);\n\n require(shortfall > 0, 'insufficient shortfall');\n\n /* The liquidator may not repay more than what is allowed by the closeFactor */\n uint256 maxClose = Exp({mantissa: comptroller.closeFactorMantissa()}).mul_ScalarTruncate(borrowBalance);\n require(repayAmount <= maxClose, 'too much repay');\n }\n return uint256(0);\n }\n}\n" }, "contracts/Comptroller/Interfaces/IGovernorAlpha.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\nabstract contract IGovernorAlpha {\n struct Proposal {\n // Unique id for looking up a proposal\n uint256 id;\n // Creator of the proposal\n address proposer;\n // The timestamp that the proposal will be available for execution, set once the vote succeeds\n uint256 eta;\n // the ordered list of target addresses for calls to be made\n address[] targets;\n // The ordered list of values (i.e. msg.value) to be passed to the calls to be made\n uint256[] values;\n // The ordered list of function signatures to be called\n string[] signatures;\n // The ordered list of calldata to be passed to each call\n bytes[] calldatas;\n // The block at which voting begins: holders must delegate their votes prior to this block\n uint256 startBlock;\n // The block at which voting ends: votes must be cast prior to this block\n uint256 endBlock;\n // Current number of votes in favor of this proposal\n uint256 forVotes;\n // Current number of votes in opposition to this proposal\n uint256 againstVotes;\n // Flag marking whether the proposal has been canceled\n bool canceled;\n // Flag marking whether the proposal has been executed\n bool executed;\n // Receipts of ballots for the entire set of voters\n mapping(address => Receipt) receipts;\n }\n // Ballot receipt record for a voter\n // Whether or not a vote has been cast\n // Whether or not the voter supports the proposal\n // The number of votes the voter had, which were cast\n struct Receipt {\n bool hasVoted;\n bool support;\n uint96 votes;\n }\n\n function getReceipt(uint256 proposalId, address voter)\n external\n view\n virtual\n returns (\n bool,\n bool,\n uint96\n );\n\n mapping(uint256 => Proposal) public proposals;\n\n function getActions(uint256 proposalId)\n public\n view\n virtual\n returns (\n address[] memory targets,\n uint256[] memory values,\n string[] memory signatures,\n bytes[] memory calldatas\n );\n}\n" }, "contracts/Comptroller/Interfaces/IGovernorBravo.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\ninterface IGovernorBravo {\n struct Receipt {\n bool hasVoted;\n uint8 support;\n uint96 votes;\n }\n struct Proposal {\n uint256 id;\n address proposer;\n uint256 eta;\n uint256 startBlock;\n uint256 endBlock;\n uint256 forVotes;\n uint256 againstVotes;\n uint256 abstainVotes;\n bool canceled;\n bool executed;\n }\n\n function getActions(uint256 proposalId)\n external\n view\n returns (\n address[] memory targets,\n uint256[] memory values,\n string[] memory signatures,\n bytes[] memory calldatas\n );\n\n function proposals(uint256 proposalId) external view returns (Proposal memory);\n\n function getReceipt(uint256 proposalId, address voter) external view returns (Receipt memory);\n}\n" }, "contracts/Comptroller/CompLogic.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\nimport '../Exponential/ExponentialNoError.sol';\nimport './Interfaces/IComptroller.sol';\nimport './Interfaces/ICToken.sol';\nimport '@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol';\n\ncontract CompLogic is AccessControlEnumerableUpgradeable {\n using ExponentialNoError for uint256;\n using ExponentialNoError for Exp;\n using ExponentialNoError for Double;\n\n /// @notice The market's last updated compBorrowIndex or compSupplyIndex\n /// @notice The block number the index was last updated at\n struct CompMarketState {\n uint224 index;\n uint32 block;\n }\n address public comp;\n\n IComptroller public comptroller;\n /// @notice The COMP accrued but not yet transferred to each user\n mapping(address => uint256) public compAccrued;\n /// @notice The portion of COMP that each contributor receives per block\n mapping(address => uint256) public compContributorSpeeds;\n /// @notice The initial COMP index for a market\n uint224 public constant compInitialIndex = 1e36;\n /// @notice Last block at which a contributor's COMP rewards have been allocated\n mapping(address => uint256) public lastContributorBlock;\n /// @notice The COMP borrow index for each market for each supplier as of the last time they accrued COMP\n mapping(address => mapping(address => uint256)) public compSupplierIndex;\n /// @notice The COMP borrow index for each market for each borrower as of the last time they accrued COMP\n mapping(address => mapping(address => uint256)) public compBorrowerIndex;\n /// @notice The rate at which comp is distributed to the corresponding supply market (per block)\n mapping(address => uint256) public compSupplySpeeds;\n /// @notice The rate at which comp is distributed to the corresponding borrow market (per block)\n mapping(address => uint256) public compBorrowSpeeds;\n /// @notice The COMP market supply state for each market\n mapping(address => CompMarketState) public compSupplyState;\n /// @notice The COMP market borrow state for each market\n mapping(address => CompMarketState) public compBorrowState;\n\n /// @notice Emitted when COMP is granted by admin\n event CompGranted(address recipient, uint256 amount);\n /// @notice Emitted when a new COMP speed is set for a contributor\n event ContributorCompSpeedUpdated(address indexed contributor, uint256 newSpeed);\n /// @notice Emitted when a new supply-side COMP speed is calculated for a market\n event CompSupplySpeedUpdated(address indexed cToken, uint256 newSpeed);\n /// @notice Emitted when a new borrow-side COMP speed is calculated for a market\n event CompBorrowSpeedUpdated(address indexed cToken, uint256 newSpeed);\n /// @notice Emitted when COMP is distributed to a supplier\n event DistributedSupplierComp(\n address indexed cToken,\n address indexed supplier,\n uint256 compDelta,\n uint256 compSupplyIndex\n );\n\n /// @notice Emitted when COMP is distributed to a borrower\n event DistributedBorrowerComp(\n address indexed cToken,\n address indexed borrower,\n uint256 compDelta,\n uint256 compBorrowIndex\n );\n\n function initialize(address _admin, address _comp) external initializer {\n comp = _comp;\n _setupRole(DEFAULT_ADMIN_ROLE, _admin);\n }\n\n event SetComptroller(address comptroller);\n\n function setComptroller(IComptroller _comptroller) external onlyRole(DEFAULT_ADMIN_ROLE) {\n comptroller = _comptroller;\n emit SetComptroller(address(comptroller));\n }\n\n /*** Comp Distribution ***/\n\n /**\n * @notice Set COMP speed for a single market\n * @param cToken The market whose COMP speed to update\n * @param supplySpeed New supply-side COMP speed for market\n * @param borrowSpeed New borrow-side COMP speed for market\n */\n function setCompSpeed(address cToken, uint256 supplySpeed, uint256 borrowSpeed) external {\n require(msg.sender == address(comptroller), 'forbidden!');\n _setCompSpeedInternal(cToken, supplySpeed, borrowSpeed);\n }\n\n function _setCompSpeedInternal(address cToken, uint256 supplySpeed, uint256 borrowSpeed) private {\n (bool isListed, , ) = comptroller.markets(cToken);\n require(isListed, 'comp market is not listed');\n\n if (compSupplySpeeds[cToken] != supplySpeed) {\n // Supply speed updated so let's update supply state to ensure that\n // 1. COMP accrued properly for the old speed, and\n // 2. COMP accrued at the new speed starts after this block.\n _updateCompSupplyIndex(cToken);\n\n // Update speed and emit event\n compSupplySpeeds[cToken] = supplySpeed;\n emit CompSupplySpeedUpdated(cToken, supplySpeed);\n }\n\n if (compBorrowSpeeds[cToken] != borrowSpeed) {\n // Borrow speed updated so let's update borrow state to ensure that\n // 1. COMP accrued properly for the old speed, and\n // 2. COMP accrued at the new speed starts after this block.\n Exp memory borrowIndex = Exp({mantissa: ICToken(cToken).borrowIndex()});\n _updateCompBorrowIndex(cToken, borrowIndex);\n\n // Update speed and emit event\n compBorrowSpeeds[cToken] = borrowSpeed;\n emit CompBorrowSpeedUpdated(cToken, borrowSpeed);\n }\n }\n\n /**\n * @notice Accrue COMP to the market by updating the supply index\n * @param cToken The market whose supply index to update\n * @dev Index is a cumulative sum of the COMP per cToken accrued.\n */\n function updateCompSupplyIndex(address cToken) external {\n require(msg.sender == address(comptroller), 'forbidden!');\n _updateCompSupplyIndex(cToken);\n }\n\n function _updateCompSupplyIndex(address cToken) private {\n CompMarketState storage supplyState = compSupplyState[cToken];\n uint256 supplySpeed = compSupplySpeeds[cToken];\n uint32 blockNumber = block.number.safe32('block number exceeds 32 bits');\n uint256 deltaBlocks = uint256(blockNumber).sub_(uint256(supplyState.block));\n if (deltaBlocks > 0 && supplySpeed > 0) {\n uint256 supplyTokens = ICToken(cToken).totalSupply();\n uint256 _compAccrued = deltaBlocks.mul_(supplySpeed);\n Double memory ratio = supplyTokens > 0 ? _compAccrued.fraction(supplyTokens) : Double({mantissa: 0});\n supplyState.index = Double({mantissa: supplyState.index}).add_(ratio).mantissa.safe224(\n 'new index exceeds 224 bits'\n );\n supplyState.block = blockNumber;\n } else if (deltaBlocks > 0) {\n supplyState.block = blockNumber;\n }\n }\n\n /**\n * @notice Accrue COMP to the market by updating the borrow index\n * @param cToken The market whose borrow index to update\n * @dev Index is a cumulative sum of the COMP per cToken accrued.\n */\n\n function updateCompBorrowIndex(address cToken, Exp memory marketBorrowIndex) external {\n require(msg.sender == address(comptroller), 'forbidden!');\n _updateCompBorrowIndex(cToken, marketBorrowIndex);\n }\n\n function _updateCompBorrowIndex(address cToken, Exp memory marketBorrowIndex) private {\n CompMarketState storage borrowState = compBorrowState[cToken];\n uint256 borrowSpeed = compBorrowSpeeds[cToken];\n uint32 blockNumber = block.number.safe32('block number exceeds 32 bits');\n uint256 deltaBlocks = uint256(blockNumber).sub_(uint256(borrowState.block));\n if (deltaBlocks > 0 && borrowSpeed > 0) {\n uint256 borrowAmount = ICToken(cToken).totalBorrows().div_(marketBorrowIndex);\n uint256 _compAccrued = deltaBlocks.mul_(borrowSpeed);\n Double memory ratio = borrowAmount > 0 ? _compAccrued.fraction(borrowAmount) : Double({mantissa: 0});\n borrowState.index = Double({mantissa: borrowState.index}).add_(ratio).mantissa.safe224(\n 'new index exceeds 224 bits'\n );\n borrowState.block = blockNumber;\n } else if (deltaBlocks > 0) {\n borrowState.block = blockNumber;\n }\n }\n\n /**\n * @notice Calculate COMP accrued by a supplier and possibly transfer it to them\n * @param cToken The market in which the supplier is interacting\n * @param supplier The address of the supplier to distribute COMP to\n */\n\n function distributeSupplierComp(address cToken, address supplier) external {\n require(msg.sender == address(comptroller), 'forbidden!');\n _distributeSupplierComp(cToken, supplier);\n }\n\n function _distributeSupplierComp(address cToken, address supplier) private {\n // TODO: Don't distribute supplier COMP if the user is not in the supplier market.\n // This check should be as gas efficient as possible as distributeSupplierComp is called in many places.\n // - We really don't want to call an external contract as that's quite expensive.\n\n CompMarketState storage supplyState = compSupplyState[cToken];\n uint256 supplyIndex = supplyState.index;\n uint256 supplierIndex = compSupplierIndex[cToken][supplier];\n\n // Update supplier's index to the current index since we are distributing accrued COMP\n compSupplierIndex[cToken][supplier] = supplyIndex;\n\n if (supplierIndex == 0 && supplyIndex >= compInitialIndex) {\n // Covers the case where users supplied tokens before the market's supply state index was set.\n // Rewards the user with COMP accrued from the start of when supplier rewards were first\n // set for the market.\n supplierIndex = compInitialIndex;\n }\n\n // Calculate change in the cumulative sum of the COMP per cToken accrued\n Double memory deltaIndex = Double({mantissa: supplyIndex.sub_(supplierIndex)});\n\n uint256 supplierTokens = ICToken(cToken).balanceOf(supplier);\n\n // Calculate COMP accrued: cTokenAmount * accruedPerCTokenInterface\n uint256 supplierDelta = supplierTokens.mul_(deltaIndex);\n\n uint256 supplierAccrued = compAccrued[supplier].add_(supplierDelta);\n compAccrued[supplier] = supplierAccrued;\n\n emit DistributedSupplierComp(cToken, supplier, supplierDelta, supplyIndex);\n }\n\n /**\n * @notice Calculate COMP accrued by a borrower and possibly transfer it to them\n * @dev Borrowers will not begin to accrue until after the first interaction with the protocol.\n * @param cToken The market in which the borrower is interacting\n * @param borrower The address of the borrower to distribute COMP to\n */\n function distributeBorrowerComp(address cToken, address borrower, Exp memory marketBorrowIndex) external {\n require(msg.sender == address(comptroller), 'forbidden!');\n _distributeBorrowerComp(cToken, borrower, marketBorrowIndex);\n }\n\n function _distributeBorrowerComp(address cToken, address borrower, Exp memory marketBorrowIndex) private {\n // TODO: Don't distribute supplier COMP if the user is not in the borrower market.\n // This check should be as gas efficient as possible as distributeBorrowerComp is called in many places.\n // - We really don't want to call an external contract as that's quite expensive.\n\n CompMarketState storage borrowState = compBorrowState[cToken];\n uint256 borrowIndex = borrowState.index;\n uint256 borrowerIndex = compBorrowerIndex[cToken][borrower];\n\n // Update borrowers's index to the current index since we are distributing accrued COMP\n compBorrowerIndex[cToken][borrower] = borrowIndex;\n\n if (borrowerIndex == 0 && borrowIndex >= compInitialIndex) {\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\n // Rewards the user with COMP accrued from the start of when borrower rewards were first\n // set for the market.\n borrowerIndex = compInitialIndex;\n }\n\n // Calculate change in the cumulative sum of the COMP per borrowed unit accrued\n Double memory deltaIndex = Double({mantissa: borrowIndex.sub_(borrowerIndex)});\n\n uint256 borrowerAmount = ICToken(cToken).borrowBalanceStored(borrower).div_(marketBorrowIndex);\n\n // Calculate COMP accrued: cTokenAmount * accruedPerBorrowedUnit\n uint256 borrowerDelta = borrowerAmount.mul_(deltaIndex);\n\n uint256 borrowerAccrued = compAccrued[borrower].add_(borrowerDelta);\n compAccrued[borrower] = borrowerAccrued;\n\n emit DistributedBorrowerComp(cToken, borrower, borrowerDelta, borrowIndex);\n }\n\n /**\n * @notice Calculate additional accrued COMP 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 compSpeed = compContributorSpeeds[contributor];\n uint256 blockNumber = block.number;\n uint256 deltaBlocks = blockNumber.sub_(lastContributorBlock[contributor]);\n if (deltaBlocks > 0 && compSpeed > 0) {\n uint256 newAccrued = deltaBlocks.mul_(compSpeed);\n uint256 contributorAccrued = compAccrued[contributor].add_(newAccrued);\n\n compAccrued[contributor] = contributorAccrued;\n lastContributorBlock[contributor] = blockNumber;\n }\n }\n\n /**\n * @notice Claim all the comp accrued by holder in all markets\n * @param holder The address to claim COMP for\n */\n function claimSumer(address holder) public {\n return claimSumer(holder, comptroller.getAllMarkets());\n }\n\n /**\n * @notice Claim all the comp accrued by holder in the specified markets\n * @param holder The address to claim COMP for\n * @param cTokens The list of markets to claim COMP in\n */\n function claimSumer(address holder, address[] memory cTokens) public {\n address[] memory holders = new address[](1);\n holders[0] = holder;\n claimSumer(holders, cTokens, true, true);\n }\n\n /**\n * @notice Claim all comp accrued by the holders\n * @param holders The addresses to claim COMP for\n * @param cTokens The list of markets to claim COMP in\n * @param borrowers Whether or not to claim COMP earned by borrowing\n * @param suppliers Whether or not to claim COMP earned by supplying\n */\n function claimSumer(address[] memory holders, address[] memory cTokens, bool borrowers, bool suppliers) public {\n for (uint256 i = 0; i < cTokens.length; ++i) {\n address cToken = cTokens[i];\n (bool isListed, , ) = comptroller.markets(cToken);\n require(isListed, 'market must be listed');\n if (borrowers) {\n Exp memory borrowIndex = Exp({mantissa: ICToken(cToken).borrowIndex()});\n _updateCompBorrowIndex(cToken, borrowIndex);\n for (uint256 j = 0; j < holders.length; j++) {\n _distributeBorrowerComp(cToken, holders[j], borrowIndex);\n }\n }\n if (suppliers) {\n _updateCompSupplyIndex(cToken);\n for (uint256 j = 0; j < holders.length; j++) {\n _distributeSupplierComp(cToken, holders[j]);\n }\n }\n }\n for (uint256 j = 0; j < holders.length; j++) {\n compAccrued[holders[j]] = grantCompInternal(holders[j], compAccrued[holders[j]]);\n }\n }\n\n /**\n * @notice Transfer COMP to the user\n * @dev Note: If there is not enough COMP, we do not perform the transfer all.\n * @param user The address of the user to transfer COMP to\n * @param amount The amount of COMP to (possibly) transfer\n * @return The amount of COMP which was NOT transferred to the user\n */\n function grantCompInternal(address user, uint256 amount) private returns (uint256) {\n address[] memory markets = comptroller.getAssetsIn(user);\n /***\n for (uint i = 0; i < allMarkets.length; ++i) {\n address market = address(allMarkets[i]);\n ***/\n for (uint256 i = 0; i < markets.length; ++i) {\n address market = address(markets[i]);\n bool noOriginalSpeed = compBorrowSpeeds[market] == 0;\n bool invalidSupply = noOriginalSpeed && compSupplierIndex[market][user] > 0;\n bool invalidBorrow = noOriginalSpeed && compBorrowerIndex[market][user] > 0;\n\n if (invalidSupply || invalidBorrow) {\n return amount;\n }\n }\n\n uint256 compRemaining = ICToken(comp).balanceOf(address(this));\n if (amount > 0 && amount <= compRemaining) {\n comp.call(abi.encodeWithSignature('transfer(address,uint256)', user, amount));\n return 0;\n }\n return amount;\n }\n\n function initializeMarket(address cToken, uint32 blockNumber) external {\n require(msg.sender == address(comptroller), 'forbidden!');\n CompMarketState storage supplyState = compSupplyState[cToken];\n CompMarketState storage borrowState = compBorrowState[cToken];\n /*\n * Update market state indices\n */\n if (supplyState.index == 0) {\n // Initialize supply state index with default value\n supplyState.index = compInitialIndex;\n }\n if (borrowState.index == 0) {\n // Initialize borrow state index with default value\n borrowState.index = compInitialIndex;\n }\n /*\n * Update market state block numbers\n */\n supplyState.block = borrowState.block = blockNumber;\n }\n\n /*** Comp Distribution Admin ***/\n /**\n * @notice Transfer COMP to the recipient\n * @dev Note: If there is not enough COMP, we do not perform the transfer all.\n * @param recipient The address of the recipient to transfer COMP to\n * @param amount The amount of COMP to (possibly) transfer\n */\n function _grantComp(address recipient, uint256 amount) public onlyRole(DEFAULT_ADMIN_ROLE) {\n uint256 amountLeft = grantCompInternal(recipient, amount);\n require(amountLeft == 0, 'insufficient comp for grant');\n emit CompGranted(recipient, amount);\n }\n\n /**\n * @notice Set COMP borrow and supply speeds for the specified markets.\n * @param cTokens The markets whose COMP speed to update.\n * @param supplySpeeds New supply-side COMP speed for the corresponding market.\n * @param borrowSpeeds New borrow-side COMP speed for the corresponding market.\n */\n function _setCompSpeeds(\n address[] memory cTokens,\n uint256[] memory supplySpeeds,\n uint256[] memory borrowSpeeds\n ) public onlyRole(DEFAULT_ADMIN_ROLE) {\n uint256 numTokens = cTokens.length;\n require(\n numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length,\n 'Comptroller::_setCompSpeeds invalid input'\n );\n\n for (uint256 i = 0; i < numTokens; ++i) {\n _setCompSpeedInternal(cTokens[i], supplySpeeds[i], borrowSpeeds[i]);\n }\n }\n\n /**\n * @notice Set COMP speed for a single contributor\n * @param contributor The contributor whose COMP speed to update\n * @param compSpeed New COMP speed for contributor\n */\n function _setContributorCompSpeed(address contributor, uint256 compSpeed) public onlyRole(DEFAULT_ADMIN_ROLE) {\n // note that COMP speed could be set to 0 to halt liquidity rewards for a contributor\n updateContributorRewards(contributor);\n if (compSpeed == 0) {\n // release storage\n delete lastContributorBlock[contributor];\n } else {\n lastContributorBlock[contributor] = block.number;\n }\n compContributorSpeeds[contributor] = compSpeed;\n\n emit ContributorCompSpeedUpdated(contributor, compSpeed);\n }\n\n function calculateComp(address holder) external view returns (uint256) {\n address[] memory cTokens = comptroller.getAllMarkets();\n uint256 accrued = compAccrued[holder];\n for (uint256 i = 0; i < cTokens.length; ++i) {\n address cToken = cTokens[i];\n Exp memory marketBorrowIndex = Exp({mantissa: ICToken(cToken).borrowIndex()});\n // _updateCompBorrowIndex\n CompMarketState memory borrowState = compBorrowState[cToken];\n uint256 borrowSpeed = compBorrowSpeeds[cToken];\n uint32 blockNumber = block.number.safe32('block number exceeds 32 bits');\n uint256 borrowDeltaBlocks = uint256(blockNumber).sub_(uint256(borrowState.block));\n if (borrowDeltaBlocks > 0 && borrowSpeed > 0) {\n uint256 borrowAmount = ICToken(cToken).totalBorrows().div_(marketBorrowIndex);\n uint256 _compAccrued = borrowDeltaBlocks.mul_(borrowSpeed);\n Double memory ratio = borrowAmount > 0 ? _compAccrued.fraction(borrowAmount) : Double({mantissa: 0});\n borrowState.index = Double({mantissa: borrowState.index}).add_(ratio).mantissa.safe224(\n 'new index exceeds 224 bits'\n );\n borrowState.block = blockNumber;\n } else if (borrowDeltaBlocks > 0) {\n borrowState.block = blockNumber;\n }\n // _distributeBorrowerComp\n uint256 borrowIndex = borrowState.index;\n uint256 borrowerIndex = compBorrowerIndex[cToken][holder];\n if (borrowerIndex == 0 && borrowIndex >= compInitialIndex) {\n borrowerIndex = compInitialIndex;\n }\n Double memory borrowDeltaIndex = Double({mantissa: borrowIndex.sub_(borrowerIndex)});\n uint256 borrowerAmount = ICToken(cToken).borrowBalanceStored(holder).div_(marketBorrowIndex);\n uint256 borrowerDelta = borrowerAmount.mul_(borrowDeltaIndex);\n accrued = accrued.add_(borrowerDelta);\n // _updateCompSupplyIndex\n CompMarketState memory supplyState = compSupplyState[cToken];\n uint256 supplySpeed = compSupplySpeeds[cToken];\n uint256 supplyDeltaBlocks = uint256(blockNumber).sub_(uint256(supplyState.block));\n if (supplyDeltaBlocks > 0 && supplySpeed > 0) {\n uint256 supplyTokens = ICToken(cToken).totalSupply();\n uint256 _compAccrued = supplyDeltaBlocks.mul_(supplySpeed);\n Double memory ratio = supplyTokens > 0 ? _compAccrued.fraction(supplyTokens) : Double({mantissa: 0});\n supplyState.index = Double({mantissa: supplyState.index}).add_(ratio).mantissa.safe224(\n 'new index exceeds 224 bits'\n );\n supplyState.block = blockNumber;\n } else if (supplyDeltaBlocks > 0) {\n supplyState.block = blockNumber;\n }\n // _distributeSupplierComp\n uint256 supplyIndex = supplyState.index;\n uint256 supplierIndex = compSupplierIndex[cToken][holder];\n if (supplierIndex == 0 && supplyIndex >= compInitialIndex) {\n supplierIndex = compInitialIndex;\n }\n Double memory supplyDeltaIndex = Double({mantissa: supplyIndex.sub_(supplierIndex)});\n uint256 supplierTokens = ICToken(cToken).balanceOf(holder);\n uint256 supplierDelta = supplierTokens.mul_(supplyDeltaIndex);\n accrued = accrued.add_(supplierDelta);\n }\n return accrued;\n }\n}\n" }, "contracts/Comptroller/AccountLiquidity.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\nimport '../Exponential/ExponentialNoError.sol';\nimport './Interfaces/IComptroller.sol';\nimport './Interfaces/ICToken.sol';\nimport './Interfaces/IUnderwriterAdmin.sol';\nimport './Interfaces/IPriceOracle.sol';\nimport '@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol';\n\ncontract AccountLiquidity is AccessControlEnumerableUpgradeable {\n using ExponentialNoError for uint256;\n using ExponentialNoError for Exp;\n using ExponentialNoError for Double;\n\n IUnderwriterAdmin public underWriterAdmin;\n IComptroller public comptroller;\n\n function initialize(address _admin) external initializer {\n _setupRole(DEFAULT_ADMIN_ROLE, _admin);\n }\n\n function setComptroller(IComptroller _comptroller) external onlyRole(DEFAULT_ADMIN_ROLE) {\n comptroller = _comptroller;\n underWriterAdmin = IUnderwriterAdmin(comptroller.underWriterAdmin());\n }\n\n /**\n * @dev Local vars for avoiding stack-depth limits in calculating account liquidity.\n * Note that `cTokenBalance` is the number of cTokens the account owns in the market,\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\n */\n struct AccountLiquidityLocalVars {\n uint8 equalAssetsGroupNum;\n uint8 assetGroupId;\n uint256 sumCollateral;\n uint256 sumBorrowPlusEffects;\n uint256 cTokenBalance;\n uint256 borrowBalance;\n uint256 exchangeRateMantissa;\n uint256 oraclePriceMantissa;\n Exp collateralFactor;\n Exp exchangeRate;\n Exp oraclePrice;\n Exp tokensToDenom;\n Exp intraCRate;\n Exp intraMintRate;\n Exp interCRate;\n Exp intraSuRate;\n Exp interSuRate;\n Exp discountRate;\n bool isSuToken;\n uint256 tokenDepositVal;\n uint256 tokenBorrowVal;\n }\n\n struct AccountGroupLocalVars {\n uint8 groupId;\n uint256 cTokenBalanceSum;\n uint256 cTokenBorrowSum;\n uint256 suTokenBalanceSum;\n uint256 suTokenBorrowSum;\n }\n\n /**\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\n * @param cTokenModify The market to hypothetically redeem/borrow in\n * @param account The account to determine liquidity for\n * @param redeemTokens The number of tokens to hypothetically redeem\n * @param borrowAmount The amount of underlying to hypothetically borrow\n * @dev Note that we calculate the exchangeRateStored for each collateral cToken using stored data,\n * without calculating accumulated interest.\n * @return (possible error code,\n hypothetical account liquidity in excess of collateral requirements,\n * hypothetical account shortfall below collateral requirements)\n */\n function getHypotheticalAccountLiquidity(\n address account,\n address cTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount\n ) public view returns (uint256, uint256, uint256) {\n AccountLiquidityLocalVars memory vars; // Holds all our calculation results\n uint256 oErr;\n\n vars.equalAssetsGroupNum = IUnderwriterAdmin(underWriterAdmin).getAssetGroupNum();\n AccountGroupLocalVars[] memory groupVars = new AccountGroupLocalVars[](vars.equalAssetsGroupNum);\n\n if ((cTokenModify != address(0)) && !ICToken(cTokenModify).isCToken()) {\n vars.isSuToken = true;\n } else {\n vars.isSuToken = false;\n }\n\n // For each asset the account is in\n address[] memory assets = comptroller.getAssetsIn(account);\n for (uint256 i = 0; i < assets.length; ++i) {\n address asset = assets[i];\n vars.tokenDepositVal = uint256(0);\n vars.tokenBorrowVal = uint256(0);\n\n (, uint8 assetGroupId, ) = comptroller.markets(asset);\n\n //IUnderwriterAdmin.AssetGroup memory eqAsset = IUnderwriterAdmin(underWriterAdmin).getAssetGroup(asset);\n\n // Read the balances and exchange rate from the cToken\n (oErr, vars.cTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = ICToken(asset).getAccountSnapshot(\n account\n );\n require(oErr == 0, 'snapshot error');\n vars.exchangeRate = Exp({mantissa: vars.exchangeRateMantissa});\n vars.discountRate = Exp({mantissa: ICToken(asset).getDiscountRate()});\n\n // Get the normalized price of the asset\n IPriceOracle oracle = IPriceOracle(comptroller.oracle());\n vars.oraclePriceMantissa = oracle.getUnderlyingPrice(asset);\n require(vars.oraclePriceMantissa > 0, 'price error');\n vars.oraclePrice = Exp({mantissa: vars.oraclePriceMantissa});\n\n // Pre-compute a conversion factor from tokens -> ether (normalized price value)\n // vars.tokensToDenom = vars.exchangeRate.mul_(vars.oraclePriceMantissa).div_(1e18);\n vars.tokensToDenom = vars.exchangeRate.mul_(vars.oraclePrice);\n vars.tokensToDenom = vars.tokensToDenom.mul_(vars.discountRate);\n\n uint8 index;\n for (index = 0; index < vars.equalAssetsGroupNum; ++index) {\n if (groupVars[index].groupId > 0) {\n if (groupVars[index].groupId == assetGroupId) {\n break;\n }\n } else {\n groupVars[index].groupId = assetGroupId;\n break;\n }\n }\n // require(index < vars.equalAssetsGroupNum);\n vars.tokenDepositVal = vars.tokensToDenom.mul_ScalarTruncateAddUInt(vars.cTokenBalance, vars.tokenDepositVal);\n vars.tokenBorrowVal = vars.oraclePrice.mul_ScalarTruncateAddUInt(vars.borrowBalance, vars.tokenBorrowVal);\n if (asset == cTokenModify) {\n uint256 redeemVal = vars.tokensToDenom.mul_(redeemTokens).truncate();\n if (redeemVal <= vars.tokenDepositVal) {\n // if redeemedVal <= tokenDepositVal\n // absorb it with deposits\n // tokenDepositVal -= redeemVal\n vars.tokenDepositVal = vars.tokenDepositVal.sub_(redeemVal);\n redeemVal = 0;\n } else {\n // if redeemVal > tokenDepositVal\n // redeemVal -= tokenDepositVal\n redeemVal = redeemVal.sub_(vars.tokenDepositVal);\n vars.tokenBorrowVal = vars.tokenBorrowVal.add_(redeemVal);\n vars.tokenDepositVal = 0;\n }\n\n vars.tokenBorrowVal = vars.oraclePrice.mul_ScalarTruncateAddUInt(borrowAmount, vars.tokenBorrowVal);\n }\n\n if (ICToken(asset).isCToken()) {\n groupVars[index].cTokenBalanceSum = vars.tokenDepositVal.add_(groupVars[index].cTokenBalanceSum);\n groupVars[index].cTokenBorrowSum = vars.tokenBorrowVal.add_(groupVars[index].cTokenBorrowSum);\n } else {\n groupVars[index].suTokenBalanceSum = vars.tokenDepositVal.add_(groupVars[index].suTokenBalanceSum);\n groupVars[index].suTokenBorrowSum = vars.tokenBorrowVal.add_(groupVars[index].suTokenBorrowSum);\n }\n }\n\n AccountGroupLocalVars memory targetGroup;\n AccountLiquidityLocalVars memory targetVars;\n for (uint8 i = 0; i < vars.equalAssetsGroupNum; ++i) {\n (, uint8 assetGroupId, ) = comptroller.markets(cTokenModify);\n if (groupVars[i].groupId == 0) {\n continue;\n }\n IUnderwriterAdmin.AssetGroup memory equalAssetsGroup = IUnderwriterAdmin(underWriterAdmin).getAssetGroup(\n groupVars[i].groupId\n );\n\n vars.intraCRate = Exp({mantissa: equalAssetsGroup.intraCRateMantissa});\n vars.intraMintRate = Exp({mantissa: equalAssetsGroup.intraMintRateMantissa});\n vars.intraSuRate = Exp({mantissa: equalAssetsGroup.intraSuRateMantissa});\n vars.interCRate = Exp({mantissa: equalAssetsGroup.interCRateMantissa});\n vars.interSuRate = Exp({mantissa: equalAssetsGroup.interSuRateMantissa});\n\n // absorb sutoken loan with ctoken collateral\n if (groupVars[i].suTokenBorrowSum > 0) {\n uint256 collateralizedLoan = vars.intraMintRate.mul_ScalarTruncate(groupVars[i].cTokenBalanceSum);\n if (groupVars[i].suTokenBorrowSum <= collateralizedLoan) {\n // collateral could cover the loan\n uint256 usedCollateral = groupVars[i].suTokenBorrowSum.div_(vars.intraMintRate);\n groupVars[i].cTokenBalanceSum = groupVars[i].cTokenBalanceSum.sub_(usedCollateral);\n groupVars[i].suTokenBorrowSum = 0;\n } else {\n // collateral could not cover the loan\n groupVars[i].suTokenBorrowSum = groupVars[i].suTokenBorrowSum.sub_(collateralizedLoan);\n groupVars[i].cTokenBalanceSum = 0;\n }\n }\n\n // absorb ctoken loan with ctoken collateral\n if (groupVars[i].cTokenBorrowSum > 0) {\n uint256 collateralizedLoan = vars.intraCRate.mul_ScalarTruncate(groupVars[i].cTokenBalanceSum);\n if (groupVars[i].cTokenBorrowSum <= collateralizedLoan) {\n // collateral could cover the loan\n uint256 usedCollateral = groupVars[i].cTokenBorrowSum.div_(vars.intraCRate);\n groupVars[i].cTokenBalanceSum = groupVars[i].cTokenBalanceSum.sub_(usedCollateral);\n groupVars[i].cTokenBorrowSum = 0;\n } else {\n // collateral could not cover the loan\n groupVars[i].cTokenBalanceSum = 0;\n groupVars[i].cTokenBorrowSum = groupVars[i].cTokenBorrowSum.sub_(collateralizedLoan);\n }\n }\n\n // absorb sutoken loan with sutoken collateral\n if (groupVars[i].suTokenBorrowSum > 0) {\n uint256 collateralizedLoan = vars.intraSuRate.mul_ScalarTruncate(groupVars[i].suTokenBalanceSum);\n if (groupVars[i].suTokenBorrowSum <= collateralizedLoan) {\n // collateral could cover the loan\n uint256 usedCollateral = groupVars[i].suTokenBorrowSum.div_(vars.intraSuRate);\n groupVars[i].suTokenBalanceSum = groupVars[i].suTokenBalanceSum.sub_(usedCollateral);\n groupVars[i].suTokenBorrowSum = 0;\n } else {\n // collateral could not cover the loan\n groupVars[i].suTokenBalanceSum = 0;\n groupVars[i].suTokenBorrowSum = groupVars[i].suTokenBorrowSum.sub_(collateralizedLoan);\n }\n }\n\n // absorb ctoken loan with sutoken collateral\n if (groupVars[i].cTokenBorrowSum > 0) {\n uint256 collateralizedLoan = vars.intraSuRate.mul_ScalarTruncate(groupVars[i].suTokenBalanceSum);\n if (groupVars[i].cTokenBorrowSum <= collateralizedLoan) {\n uint256 usedCollateral = groupVars[i].cTokenBorrowSum.div_(vars.intraSuRate);\n groupVars[i].suTokenBalanceSum = groupVars[i].suTokenBalanceSum.sub_(usedCollateral);\n groupVars[i].cTokenBorrowSum = 0;\n } else {\n groupVars[i].suTokenBalanceSum = 0;\n groupVars[i].cTokenBorrowSum = groupVars[i].cTokenBorrowSum.sub_(collateralizedLoan);\n }\n }\n\n if (groupVars[i].groupId == assetGroupId) {\n targetGroup = groupVars[i];\n targetVars = vars;\n } else {\n vars.sumCollateral = vars.interCRate.mul_ScalarTruncateAddUInt(\n groupVars[i].cTokenBalanceSum,\n vars.sumCollateral\n );\n vars.sumCollateral = vars.interSuRate.mul_ScalarTruncateAddUInt(\n groupVars[i].suTokenBalanceSum,\n vars.sumCollateral\n );\n }\n\n vars.sumBorrowPlusEffects = vars.sumBorrowPlusEffects.add_(\n groupVars[i].cTokenBorrowSum.add_(groupVars[i].suTokenBorrowSum)\n );\n }\n\n // These are safe, as the underflow condition is checked first\n if (vars.sumCollateral > vars.sumBorrowPlusEffects) {\n vars.sumCollateral = vars.sumCollateral - vars.sumBorrowPlusEffects;\n vars.sumBorrowPlusEffects = 0;\n } else {\n vars.sumBorrowPlusEffects = vars.sumBorrowPlusEffects - vars.sumCollateral;\n vars.sumCollateral = 0;\n }\n\n if (vars.sumBorrowPlusEffects > 0) {\n uint256 collateralizedLoan = targetVars.interCRate.mul_ScalarTruncate(targetGroup.cTokenBalanceSum);\n if (collateralizedLoan > vars.sumBorrowPlusEffects) {\n targetGroup.cTokenBalanceSum = targetGroup.cTokenBalanceSum.sub_(\n vars.sumBorrowPlusEffects.div_(targetVars.interCRate)\n );\n vars.sumBorrowPlusEffects = 0;\n } else {\n vars.sumBorrowPlusEffects = vars.sumBorrowPlusEffects.sub_(collateralizedLoan);\n targetGroup.cTokenBalanceSum = 0;\n }\n }\n\n if (vars.sumBorrowPlusEffects > 0) {\n uint256 collateralizedLoan = targetVars.interSuRate.mul_ScalarTruncate(targetGroup.suTokenBalanceSum);\n if (collateralizedLoan > vars.sumBorrowPlusEffects) {\n targetGroup.suTokenBalanceSum = targetGroup.suTokenBalanceSum.sub_(\n vars.sumBorrowPlusEffects.div_(targetVars.interSuRate)\n );\n vars.sumBorrowPlusEffects = 0;\n } else {\n vars.sumBorrowPlusEffects = vars.sumBorrowPlusEffects.sub_(collateralizedLoan);\n targetGroup.suTokenBalanceSum = 0;\n }\n }\n if (vars.isSuToken) {\n vars.sumCollateral = vars.intraMintRate.mul_ScalarTruncateAddUInt(\n targetGroup.cTokenBalanceSum,\n vars.sumCollateral\n );\n } else {\n vars.sumCollateral = vars.intraCRate.mul_ScalarTruncateAddUInt(targetGroup.cTokenBalanceSum, vars.sumCollateral);\n }\n vars.sumCollateral = vars.intraSuRate.mul_ScalarTruncateAddUInt(targetGroup.suTokenBalanceSum, vars.sumCollateral);\n\n if (vars.sumCollateral > vars.sumBorrowPlusEffects) {\n return (0, vars.sumCollateral - vars.sumBorrowPlusEffects, 0);\n } else {\n return (0, 0, vars.sumBorrowPlusEffects - vars.sumCollateral);\n }\n }\n}\n" }, "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.1) (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 * ```\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\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" }, "contracts/Comptroller/Interfaces/IPriceOracle.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\ninterface IPriceOracle {\n /**\n * @notice Get the underlying price of a cToken asset\n * @param cToken The cToken to get the underlying price of\n * @return The underlying asset price mantissa (scaled by 1e18).\n * Zero means the price is unavailable.\n */\n function getUnderlyingPrice(address cToken) external view returns (uint256);\n}\n" }, "contracts/Comptroller/Interfaces/IUnderwriterAdmin.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\ninterface IUnderwriterAdmin {\n /// @notice Emitted when an action is paused on a market\n event ActionPaused(address cToken, string action, bool pauseState);\n\n /// @notice Emitted when borrow cap for a cToken is changed\n event NewBorrowCap(address indexed cToken, uint256 newBorrowCap);\n\n /// @notice Emitted when borrow cap guardian is changed\n event NewBorrowCapGuardian(address oldBorrowCapGuardian, address newBorrowCapGuardian);\n\n /// @notice Emitted when pause guardian is changed\n event NewPauseGuardian(address oldPauseGuardian, address newPauseGuardian);\n\n event NewAssetGroup(\n uint8 indexed groupId,\n string indexed groupName,\n uint256 intraCRateMantissa,\n uint256 intraMintRateMantissa,\n uint256 intraSuRateMantissa,\n uint256 interCRateMantissa,\n uint256 interSuRateMantissa,\n uint8 assetsGroupNum\n );\n\n event RemoveAssetGroup(uint8 indexed groupId, uint8 equalAssetsGroupNum);\n\n /// @notice AssetGroup, contains information of groupName and rateMantissas\n struct AssetGroup {\n uint8 groupId;\n string groupName;\n uint256 intraCRateMantissa;\n uint256 intraMintRateMantissa;\n uint256 intraSuRateMantissa;\n uint256 interCRateMantissa;\n uint256 interSuRateMantissa;\n }\n\n function getAssetGroupNum() external view returns (uint8);\n\n function getAssetGroup(uint8 groupId) external view returns (AssetGroup memory);\n\n function _getMintPaused(address cToken) external returns (bool);\n\n function _getTransferPaused() external view returns (bool);\n\n function _getBorrowPaused(address cToken) external view returns (bool);\n\n function _getSeizePaused() external view returns (bool);\n\n function getCompAddress() external view returns (address);\n\n function _getMarketBorrowCap(address cToken) external view returns (uint256);\n\n}\n" }, "contracts/Comptroller/Interfaces/IComptroller.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\ninterface IComptroller {\n /*** Assets You Are In ***/\n function isComptroller() external view returns (bool);\n\n function markets(address) external view returns (bool, uint8, bool);\n\n function getAllMarkets() external view returns (address[] memory);\n\n function oracle() external view returns (address);\n\n function underWriterAdmin() external view returns (address);\n\n function enterMarkets(address[] calldata cTokens) external returns (uint256[] memory);\n\n function exitMarket(address cToken) external returns (uint256);\n\n function closeFactorMantissa() external view returns (uint256);\n\n function getAccountLiquidity(address) external view returns (uint256, uint256, uint256);\n\n // function getAssetsIn(address) external view returns (ICToken[] memory);\n function claimComp(address) external;\n\n function compAccrued(address) external view returns (uint256);\n\n function getAssetsIn(address account) external view returns (address[] memory);\n\n /*** Policy Hooks ***/\n\n function mintAllowed(address cToken, address minter, uint256 mintAmount) external returns (uint256);\n\n function redeemAllowed(address cToken, address redeemer, uint256 redeemTokens) external returns (uint256);\n\n function redeemVerify(address cToken, address redeemer, uint256 redeemAmount, uint256 redeemTokens) external;\n\n function borrowAllowed(address cToken, address borrower, uint256 borrowAmount) external returns (uint256);\n\n function repayBorrowAllowed(\n address cToken,\n address payer,\n address borrower,\n uint256 repayAmount\n ) external returns (uint256);\n\n function seizeAllowed(\n address cTokenCollateral,\n address cTokenBorrowed,\n address liquidator,\n address borrower,\n uint256 seizeTokens\n ) external returns (uint256);\n\n function transferAllowed(address cToken, address src, address dst, uint256 transferTokens) external returns (uint256);\n\n /*** Liquidity/Liquidation Calculations ***/\n\n function liquidationIncentiveMantissa() external view returns (uint256);\n\n function isListed(address asset) external view returns (bool);\n\n function marketGroupId(address asset) external view returns (uint8);\n\n function getHypotheticalAccountLiquidity(\n address account,\n address cTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount\n ) external view returns (uint256, uint256, uint256);\n\n function _getMarketBorrowCap(address cToken) external view returns (uint256);\n}\n" }, "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControlEnumerableUpgradeable.sol\";\nimport \"./AccessControlUpgradeable.sol\";\nimport \"../utils/structs/EnumerableSetUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerableUpgradeable is Initializable, IAccessControlEnumerableUpgradeable, AccessControlUpgradeable {\n function __AccessControlEnumerable_init() internal onlyInitializing {\n }\n\n function __AccessControlEnumerable_init_unchained() internal onlyInitializing {\n }\n using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;\n\n mapping(bytes32 => EnumerableSetUpgradeable.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerableUpgradeable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override {\n super._grantRole(role, account);\n _roleMembers[role].add(account);\n }\n\n /**\n * @dev Overload {_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override {\n super._revokeRole(role, account);\n _roleMembers[role].remove(account);\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/IAccessControlEnumerableUpgradeable.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControlUpgradeable.sol\";\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC165 detection.\n */\ninterface IAccessControlEnumerableUpgradeable is IAccessControlUpgradeable {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n" }, "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.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 *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return 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(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (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 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/structs/EnumerableSetUpgradeable.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSetUpgradeable {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position of the value in the `values` array, plus 1 because index 0\n // means a value is not in the set.\n mapping(bytes32 => uint256) _indexes;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._indexes[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We read and store the value's index to prevent multiple reads from the same storage slot\n uint256 valueIndex = set._indexes[value];\n\n if (valueIndex != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 toDeleteIndex = valueIndex - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (lastIndex != toDeleteIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the last value to the index where the value to delete is\n set._values[toDeleteIndex] = lastValue;\n // Update the index for the moved value\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the index for the deleted slot\n delete set._indexes[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._indexes[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n" }, "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControlUpgradeable.sol\";\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../utils/StringsUpgradeable.sol\";\nimport \"../utils/introspection/ERC165Upgradeable.sol\";\nimport \"../proxy/utils/Initializable.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 * ```\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 * ```\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.\n */\nabstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControlUpgradeable, ERC165Upgradeable {\n function __AccessControl_init() internal onlyInitializing {\n }\n\n function __AccessControl_init_unchained() internal onlyInitializing {\n }\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(IAccessControlUpgradeable).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 StringsUpgradeable.toHexString(account),\n \" is missing role \",\n StringsUpgradeable.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 /**\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/IAccessControlUpgradeable.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 IAccessControlUpgradeable {\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-upgradeable/utils/StringsUpgradeable.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/MathUpgradeable.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary StringsUpgradeable {\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 = MathUpgradeable.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 `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, MathUpgradeable.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" }, "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../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 /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" }, "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165Upgradeable.sol\";\nimport \"../../proxy/utils/Initializable.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 ERC165Upgradeable is Initializable, IERC165Upgradeable {\n function __ERC165_init() internal onlyInitializing {\n }\n\n function __ERC165_init_unchained() internal onlyInitializing {\n }\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165Upgradeable).interfaceId;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" }, "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.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 MathUpgradeable {\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(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) 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 return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1);\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(\n uint256 x,\n uint256 y,\n uint256 denominator,\n Rounding rounding\n ) 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 10, 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 * 8) < value ? 1 : 0);\n }\n }\n}\n" }, "@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.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 IERC165Upgradeable {\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" }, "contracts/CToken/CErc20.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\nimport './CToken.sol';\nimport './Interfaces/ICErc20.sol';\nimport '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';\n\n/**\n * @title Compound's CErc20 Contract\n * @notice CTokens which wrap an EIP-20 underlying\n * @author Compound\n */\ncontract CErc20 is CToken, ICErc20, Initializable {\n /**\n * @notice Initialize the new money market\n * @param underlying_ The address of the underlying asset\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ 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 */\n function initialize(\n address underlying_,\n address comptroller_,\n address interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_,\n uint256 discountRateMantissa_\n ) public initializer {\n // CToken initialize does the bulk of the work\n super.initialize(\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n true,\n admin_,\n discountRateMantissa_\n );\n\n isCEther = false;\n\n // Set underlying and sanity check it\n require(underlying_ != address(0), 'Address is Zero!');\n underlying = underlying_;\n // ICToken(underlying).totalSupply();\n }\n\n /*** User Interface ***/\n\n /**\n * @notice Sender supplies assets into the market and receives cTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of the underlying asset to supply\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function mint(uint256 mintAmount) external override returns (uint256) {\n (uint256 err, ) = mintInternal(mintAmount);\n return err;\n }\n\n /**\n * @notice Sender redeems cTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemTokens The number of cTokens to redeem into underlying\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function redeem(uint256 redeemTokens) external override returns (uint256) {\n return redeemInternal(redeemTokens);\n }\n\n /**\n * @notice Sender redeems cTokens in exchange for a specified amount of underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemAmount The amount of underlying to redeem\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function redeemUnderlying(uint256 redeemAmount) external override returns (uint256) {\n return redeemUnderlyingInternal(redeemAmount);\n }\n\n /**\n * @notice Sender borrows assets from the protocol to their own address\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function borrow(uint256 borrowAmount) external override returns (uint256) {\n return borrowInternal(borrowAmount);\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function repayBorrow(uint256 repayAmount) external override returns (uint256) {\n (uint256 err, ) = repayBorrowInternal(repayAmount);\n return err;\n }\n\n /**\n * @notice Sender repays a borrow belonging to borrower\n * @param borrower the account with the debt being payed off\n * @param repayAmount The amount to repay\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external override returns (uint256) {\n (uint256 err, ) = repayBorrowBehalfInternal(borrower, repayAmount);\n return err;\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param borrower The borrower of this cToken to be liquidated\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @param cTokenCollateral The market in which to seize collateral from the borrower\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function liquidateBorrow(\n address borrower,\n uint256 repayAmount,\n address cTokenCollateral\n ) external override returns (uint256) {\n (uint256 err, ) = liquidateBorrowInternal(borrower, repayAmount, cTokenCollateral);\n return err;\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 */\n function sweepToken(address token) external override {\n require(address(token) != underlying, 'CErc20::sweepToken: can not sweep underlying token');\n uint256 underlyingBalanceBefore = ICToken(underlying).balanceOf(address(this));\n uint256 balance = ICToken(token).balanceOf(address(this));\n ICToken(token).transfer(admin, balance);\n uint256 underlyingBalanceAfter = ICToken(underlying).balanceOf(address(this));\n require(underlyingBalanceBefore == underlyingBalanceAfter, 'underlyingBalance error');\n }\n\n /**\n * @notice The sender adds to reserves.\n * @param addAmount The amount fo underlying token to add as reserves\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _addReserves(uint256 addAmount) external override returns (uint256) {\n return _addReservesInternal(addAmount);\n }\n\n /*** Safe Token ***/\n\n /**\n * @notice Gets balance of this contract in terms of the underlying\n * @dev This excludes the value of the current message, if any\n * @return The quantity of underlying tokens owned by this contract\n */\n function getCashPrior() internal view virtual override returns (uint256) {\n // ICToken token = ICToken(underlying);\n // return token.balanceOf(address(this));\n return underlyingBalance;\n }\n\n /**\n * @dev Similar to EIP20 transfer, except it handles a False result from `transferFrom` and reverts in that case.\n * This will revert due to insufficient balance or insufficient allowance.\n * This function returns the actual amount received,\n * which may be less than `amount` if there is a fee attached to the transfer.\n *\n * Note: This wrapper safely handles non-standard ERC-20 tokens that do not return a value.\n * See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n */\n function doTransferIn(address from, uint256 amount) internal virtual override returns (uint256) {\n ICToken token = ICToken(underlying);\n uint256 balanceBefore = ICToken(underlying).balanceOf(address(this));\n token.transferFrom(from, address(this), amount);\n\n bool success;\n assembly {\n switch returndatasize()\n case 0 {\n // This is a non-standard ERC-20\n success := not(0) // set success to true\n }\n case 32 {\n // This is a compliant ERC-20\n returndatacopy(0, 0, 32)\n success := mload(0) // Set `success = returndata` of external call\n }\n default {\n // This is an excessively non-compliant ERC-20, revert.\n revert(0, 0)\n }\n }\n require(success, 'TOKEN_TRANSFER_IN_FAILED');\n\n // Calculate the amount that was *actually* transferred\n uint256 balanceAfter = ICToken(underlying).balanceOf(address(this));\n require(balanceAfter >= balanceBefore, 'TOKEN_TRANSFER_IN_OVERFLOW');\n uint256 finalAmount = balanceAfter - balanceBefore;\n underlyingBalance += finalAmount;\n return finalAmount; // underflow already checked above, just subtract\n }\n\n /**\n * @dev Similar to EIP20 transfer, except it handles a False success from `transfer` and returns an explanatory\n * error code rather than reverting. If caller has not called checked protocol's balance, this may revert due to\n * insufficient cash held in this contract. If caller has checked protocol's balance prior to this call, and verified\n * it is >= amount, this should not revert in normal conditions.\n *\n * Note: This wrapper safely handles non-standard ERC-20 tokens that do not return a value.\n * See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n */\n function doTransferOut(address payable to, uint256 amount) internal virtual override {\n ICToken token = ICToken(underlying);\n token.transfer(to, amount);\n underlyingBalance -= amount;\n\n bool success;\n assembly {\n switch returndatasize()\n case 0 {\n // This is a non-standard ERC-20\n success := not(0) // set success to true\n }\n case 32 {\n // This is a compliant ERC-20\n returndatacopy(0, 0, 32)\n success := mload(0) // Set `success = returndata` of external call\n }\n default {\n // This is an excessively non-compliant ERC-20, revert.\n revert(0, 0)\n }\n }\n require(success, 'TOKEN_TRANSFER_OUT_FAILED');\n }\n}\n" }, "contracts/CToken/CToken.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\nimport '../Comptroller/Interfaces/IComptroller.sol';\nimport '../Comptroller/Interfaces/IUnderwriterAdmin.sol';\nimport '../Comptroller/Interfaces/IPriceOracle.sol';\nimport './Interfaces/IInterestRateModel.sol';\nimport './TokenErrorReporter.sol';\nimport './CTokenStorage.sol';\nimport '../Exponential/Exponential.sol';\nimport '../Exponential/CarefulMath.sol';\n\n/**\n * @title Compound's CToken Contract\n * @notice Abstract base for CTokens\n * @author Compound\n */\nabstract contract CToken is CTokenStorage {\n using Exponential for uint256;\n using Exponential for Exp;\n using ExponentialNoError for uint256;\n using ExponentialNoError for Exp;\n using CarefulMath for uint256;\n using TokenErrorReporter for Error;\n\n modifier onlyAdmin() {\n // Check caller is admin\n require(msg.sender == admin, 'UNAUTHORIZED');\n _;\n }\n\n /**\n * @notice Initialize the money market\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ EIP-20 name of this token\n * @param symbol_ EIP-20 symbol of this token\n * @param decimals_ EIP-20 decimal precision of this token\n */\n function initialize(\n address comptroller_,\n address interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n bool isCToken_,\n address payable _admin,\n uint256 discountRateMantissa_\n ) internal {\n admin = _admin;\n require(accrualBlockNumber == 0 && borrowIndex == 0, 'market may only be initialized once');\n\n isCToken = isCToken_;\n\n // Set initial exchange rate\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\n require(initialExchangeRateMantissa > 0, 'initial exchange rate must be greater than zero.');\n\n discountRateMantissa = discountRateMantissa_;\n require(discountRateMantissa > 0 && discountRateMantissa <= 1e18, 'rate must in [0,100]');\n\n // Set the comptroller\n // Set market's comptroller to newComptroller\n comptroller = comptroller_;\n\n // Emit NewComptroller(oldComptroller, newComptroller)\n emit NewComptroller(address(0), comptroller_);\n\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\n accrualBlockNumber = getBlockNumber();\n borrowIndex = 1e18;\n\n // Set the interest rate model (depends on block number / borrow index)\n interestRateModel = interestRateModel_;\n emit NewMarketInterestRateModel(address(0), interestRateModel_);\n\n name = name_;\n symbol = symbol_;\n decimals = decimals_;\n\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\n _notEntered = true;\n }\n\n /**\n * @notice 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 * @return Whether or not the transfer succeeded\n */\n function transferTokens(address spender, address src, address dst, uint256 tokens) internal returns (uint256) {\n /* Fail if transfer not allowed */\n uint256 allowed = IComptroller(comptroller).transferAllowed(address(this), src, dst, tokens);\n if (allowed != 0) {\n Error.COMPTROLLER_REJECTION.failOpaque(FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\n }\n\n /* Do not allow self-transfers */\n if (src == dst) {\n Error.BAD_INPUT.fail(FailureInfo.TRANSFER_NOT_ALLOWED);\n }\n\n /* Get the allowance, infinite for the account owner */\n uint256 startingAllowance = 0;\n if (spender == src) {\n startingAllowance = uint256(0);\n } else {\n startingAllowance = transferAllowances[src][spender];\n }\n\n /* Do the calculations, checking for {under,over}flow */\n MathError mathErr;\n uint256 allowanceNew;\n uint256 srcTokensNew;\n uint256 dstTokensNew;\n\n (mathErr, allowanceNew) = startingAllowance.subUInt(tokens);\n if (mathErr != MathError.NO_ERROR) {\n Error.MATH_ERROR.fail(FailureInfo.TRANSFER_NOT_ALLOWED);\n }\n\n (mathErr, srcTokensNew) = accountTokens[src].subUInt(tokens);\n if (mathErr != MathError.NO_ERROR) {\n Error.MATH_ERROR.fail(FailureInfo.TRANSFER_NOT_ENOUGH);\n }\n\n (mathErr, dstTokensNew) = accountTokens[dst].addUInt(tokens);\n if (mathErr != MathError.NO_ERROR) {\n Error.MATH_ERROR.fail(FailureInfo.TRANSFER_TOO_MUCH);\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n accountTokens[src] = srcTokensNew;\n accountTokens[dst] = dstTokensNew;\n\n /* Eat some of the allowance (if necessary) */\n if (startingAllowance != uint256(0)) {\n transferAllowances[src][spender] = allowanceNew;\n }\n\n /* We emit a Transfer event */\n emit Transfer(src, dst, tokens);\n\n // unused function\n // comptroller.transferVerify(address(this), src, dst, tokens);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Transfer `amount` tokens from `src` to `dst`\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\n return transferTokens(msg.sender, src, dst, amount) == uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Approve `spender` to transfer up to `amount` from `src`\n * @dev This will overwrite the approval amount for `spender`\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\n * @param spender The address of the account which may transfer tokens\n * @param amount The number of tokens that are approved (-1 means infinite)\n * @return Whether or not the approval succeeded\n */\n function approve(address spender, uint256 amount) external override returns (bool) {\n address src = msg.sender;\n transferAllowances[src][spender] = amount;\n emit Approval(src, spender, amount);\n return true;\n }\n\n /**\n * @notice Get the current allowance from `owner` for `spender`\n * @param owner The address of the account which owns the tokens to be spent\n * @param spender The address of the account which may transfer tokens\n * @return The number of tokens allowed to be spent (-1 means infinite)\n */\n function allowance(address owner, address spender) external view override returns (uint256) {\n return transferAllowances[owner][spender];\n }\n\n /**\n * @notice Get the token balance of the `owner`\n * @param owner The address of the account to query\n * @return The number of tokens owned by `owner`\n */\n function balanceOf(address owner) external view override returns (uint256) {\n return accountTokens[owner];\n }\n\n /**\n * @notice Get the underlying balance of the `owner`\n * @dev This also accrues interest in a transaction\n * @param owner The address of the account to query\n * @return The amount of underlying owned by `owner`\n */\n function balanceOfUnderlying(address owner) external override returns (uint256) {\n Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()});\n (MathError mErr, uint256 balance) = exchangeRate.mulScalarTruncate(accountTokens[owner]);\n require(mErr == MathError.NO_ERROR, 'balance could not be calculated');\n return balance;\n }\n\n /**\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\n * @param account Address of the account to snapshot\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\n */\n function getAccountSnapshot(address account) external view override returns (uint256, uint256, uint256, uint256) {\n uint256 cTokenBalance = accountTokens[account];\n uint256 borrowBalance;\n uint256 exchangeRateMantissa;\n\n MathError mErr;\n\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\n if (mErr != MathError.NO_ERROR) {\n return (uint256(Error.MATH_ERROR), 0, 0, 0);\n }\n\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\n if (mErr != MathError.NO_ERROR) {\n return (uint256(Error.MATH_ERROR), 0, 0, 0);\n }\n\n return (uint256(Error.NO_ERROR), cTokenBalance, borrowBalance, exchangeRateMantissa);\n }\n\n /**\n * @dev Function to simply retrieve block number\n * This exists mainly for inheriting test contracts to stub this result.\n */\n function getBlockNumber() internal view returns (uint256) {\n return block.number;\n }\n\n /**\n * @notice Returns the current per-block borrow interest rate for this cToken\n * @return The borrow interest rate per block, scaled by 1e18\n */\n function borrowRatePerBlock() external view override returns (uint256) {\n return IInterestRateModel(interestRateModel).getBorrowRate(getCashPrior(), totalBorrows, totalReserves);\n }\n\n /**\n * @notice Returns the current per-block supply interest rate for this cToken\n * @return The supply interest rate per block, scaled by 1e18\n */\n function supplyRatePerBlock() external view override returns (uint256) {\n return\n IInterestRateModel(interestRateModel).getSupplyRate(\n getCashPrior(),\n totalBorrows,\n totalReserves,\n reserveFactorMantissa\n );\n }\n\n /**\n * @notice Returns the current total borrows plus accrued interest\n * @return The total borrows with interest\n */\n function totalBorrowsCurrent() external override nonReentrant returns (uint256) {\n require(accrueInterest() == uint256(Error.NO_ERROR), 'accrue interest failed');\n return totalBorrows;\n }\n\n /**\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\n * @param account The address whose balance should be calculated after updating borrowIndex\n * @return The calculated balance\n */\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint256) {\n require(accrueInterest() == uint256(Error.NO_ERROR), 'accrue interest failed');\n return borrowBalanceStored(account);\n }\n\n /**\n * @notice Return the borrow balance of account based on stored data\n * @param account The address whose balance should be calculated\n * @return The calculated balance\n */\n function borrowBalanceStored(address account) public view override returns (uint256) {\n (MathError err, uint256 result) = borrowBalanceStoredInternal(account);\n require(err == MathError.NO_ERROR, 'borrowBalanceStored: borrowBalanceStoredInternal failed');\n return result;\n }\n\n /**\n * @notice Return the borrow balance of account based on stored data\n * @param account The address whose balance should be calculated\n * @return (error code, the calculated balance or 0 if error code is non-zero)\n */\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint256) {\n /* Note: we do not assert that the market is up to date */\n MathError mathErr;\n uint256 principalTimesIndex;\n uint256 result;\n\n /* Get borrowBalance and borrowIndex */\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\n\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\n */\n if (borrowSnapshot.principal == 0) {\n return (MathError.NO_ERROR, 0);\n }\n\n /* Calculate new borrow balance using the interest index:\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\n */\n (mathErr, principalTimesIndex) = borrowSnapshot.principal.mulUInt(borrowIndex);\n if (mathErr != MathError.NO_ERROR) {\n return (mathErr, 0);\n }\n\n (mathErr, result) = principalTimesIndex.divUInt(borrowSnapshot.interestIndex);\n if (mathErr != MathError.NO_ERROR) {\n return (mathErr, 0);\n }\n\n return (MathError.NO_ERROR, result);\n }\n\n /**\n * @notice Accrue interest then return the up-to-date exchange rate\n * @return Calculated exchange rate scaled by 1e18\n */\n function exchangeRateCurrent() public override nonReentrant returns (uint256) {\n require(accrueInterest() == uint256(Error.NO_ERROR), 'accrue interest failed');\n return exchangeRateStored();\n }\n\n /**\n * @notice Calculates the exchange rate from the underlying to the CToken\n * @dev This function does not accrue interest before calculating the exchange rate\n * @return Calculated exchange rate scaled by 1e18\n */\n function exchangeRateStored() public view override returns (uint256) {\n (MathError err, uint256 result) = exchangeRateStoredInternal();\n require(err == MathError.NO_ERROR, 'exchangeRateStored: exchangeRateStoredInternal failed');\n return result;\n }\n\n /**\n * @notice Calculates the exchange rate from the underlying to the CToken\n * @dev This function does not accrue interest before calculating the exchange rate\n * @return (error code, calculated exchange rate scaled by 1e18)\n */\n function exchangeRateStoredInternal() internal view returns (MathError, uint256) {\n if (!isCToken) {\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\n }\n\n uint256 _totalSupply = totalSupply;\n if (_totalSupply == 0) {\n /*\n * If there are no tokens minted:\n * exchangeRate = initialExchangeRate\n */\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\n } else {\n /*\n * Otherwise:\n * exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply\n */\n uint256 totalCash = getCashPrior();\n uint256 cashPlusBorrowsMinusReserves;\n Exp memory exchangeRate;\n MathError mathErr;\n\n (mathErr, cashPlusBorrowsMinusReserves) = totalCash.addThenSubUInt(totalBorrows, totalReserves);\n if (mathErr != MathError.NO_ERROR) {\n return (mathErr, 0);\n }\n\n (mathErr, exchangeRate) = cashPlusBorrowsMinusReserves.getExp(_totalSupply);\n if (mathErr != MathError.NO_ERROR) {\n return (mathErr, 0);\n }\n\n return (MathError.NO_ERROR, exchangeRate.mantissa);\n }\n }\n\n /**\n * @notice Get cash balance of this cToken in the underlying asset\n * @return The quantity of underlying asset owned by this contract\n */\n function getCash() external view override returns (uint256) {\n return getCashPrior();\n }\n\n /**\n * @notice Applies accrued interest to total borrows and reserves\n * @dev This calculates interest accrued from the last checkpointed block\n * up to the current block and writes new checkpoint to storage.\n */\n function accrueInterest() public virtual override returns (uint256) {\n /* Remember the initial block number */\n uint256 currentBlockNumber = getBlockNumber();\n uint256 accrualBlockNumberPrior = accrualBlockNumber;\n\n /* Short-circuit accumulating 0 interest */\n if (accrualBlockNumberPrior == currentBlockNumber) {\n return uint256(Error.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 = IInterestRateModel(interestRateModel).getBorrowRate(\n cashPrior,\n borrowsPrior,\n reservesPrior\n );\n require(borrowRateMantissa <= BORROW_RATE_MAX_MANTISSA, 'borrow rate is absurdly high');\n\n /* Calculate the number of blocks elapsed since the last accrual */\n (MathError mathErr, uint256 blockDelta) = currentBlockNumber.subUInt(accrualBlockNumberPrior);\n require(mathErr == MathError.NO_ERROR, 'could not calculate block delta');\n\n /*\n * Calculate the interest accumulated into borrows and reserves and the new index:\n * simpleInterestFactor = borrowRate * blockDelta\n * interestAccumulated = simpleInterestFactor * totalBorrows\n * totalBorrowsNew = interestAccumulated + totalBorrows\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\n */\n\n Exp memory simpleInterestFactor;\n uint256 interestAccumulated;\n uint256 totalBorrowsNew;\n uint256 totalReservesNew;\n uint256 borrowIndexNew;\n\n (mathErr, simpleInterestFactor) = Exp({mantissa: borrowRateMantissa}).mulScalar(blockDelta);\n if (mathErr != MathError.NO_ERROR) {\n return\n Error.MATH_ERROR.failOpaque(\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\n uint256(mathErr)\n );\n }\n\n (mathErr, interestAccumulated) = simpleInterestFactor.mulScalarTruncate(borrowsPrior);\n if (mathErr != MathError.NO_ERROR) {\n return\n Error.MATH_ERROR.failOpaque(\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\n uint256(mathErr)\n );\n }\n\n (mathErr, totalBorrowsNew) = interestAccumulated.addUInt(borrowsPrior);\n if (mathErr != MathError.NO_ERROR) {\n return\n Error.MATH_ERROR.failOpaque(FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED, uint256(mathErr));\n }\n\n (mathErr, totalReservesNew) = Exp({mantissa: reserveFactorMantissa}).mulScalarTruncateAddUInt(\n interestAccumulated,\n reservesPrior\n );\n if (mathErr != MathError.NO_ERROR) {\n return\n Error.MATH_ERROR.failOpaque(\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\n uint256(mathErr)\n );\n }\n\n (mathErr, borrowIndexNew) = simpleInterestFactor.mulScalarTruncateAddUInt(borrowIndexPrior, borrowIndexPrior);\n if (mathErr != MathError.NO_ERROR) {\n return\n Error.MATH_ERROR.failOpaque(FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED, uint256(mathErr));\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the previously calculated values into storage */\n accrualBlockNumber = currentBlockNumber;\n borrowIndex = borrowIndexNew;\n totalBorrows = totalBorrowsNew;\n totalReserves = totalReservesNew;\n\n /* We emit an AccrueInterest event */\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Sender supplies assets into the market and receives cTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of the underlying asset to supply\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\n */\n function mintInternal(uint256 mintAmount) internal nonReentrant returns (uint256, uint256) {\n uint256 error = accrueInterest();\n if (error != uint256(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\n Error(error).fail(FailureInfo.MINT_ACCRUE_INTEREST_FAILED);\n }\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\n return mintFresh(msg.sender, mintAmount);\n }\n\n struct MintLocalVars {\n Error err;\n MathError mathErr;\n uint256 exchangeRateMantissa;\n uint256 mintTokens;\n uint256 totalSupplyNew;\n uint256 accountTokensNew;\n uint256 actualMintAmount;\n }\n\n /**\n * @notice User supplies assets into the market and receives cTokens in exchange\n * @dev Assumes interest has already been accrued up to the current block\n * @param minter The address of the account which is supplying the assets\n * @param mintAmount The amount of the underlying asset to supply\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\n */\n function mintFresh(address minter, uint256 mintAmount) internal returns (uint256, uint256) {\n /* Fail if mint not allowed */\n uint256 allowed = IComptroller(comptroller).mintAllowed(address(this), minter, mintAmount);\n if (allowed != 0) {\n Error.COMPTROLLER_REJECTION.failOpaque(FailureInfo.MINT_COMPTROLLER_REJECTION, allowed);\n }\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != getBlockNumber()) {\n Error.MARKET_NOT_FRESH.fail(FailureInfo.MINT_FRESHNESS_CHECK);\n }\n\n MintLocalVars memory vars;\n\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\n if (vars.mathErr != MathError.NO_ERROR) {\n Error.MATH_ERROR.failOpaque(FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint256(vars.mathErr));\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We call `doTransferIn` for the minter and the mintAmount.\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\n * side-effects occurred. The function returns the amount actually transferred,\n * in case of a fee. On success, the cToken holds an additional `actualMintAmount`\n * of cash.\n */\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\n\n /*\n * We get the current exchange rate and calculate the number of cTokens to be minted:\n * mintTokens = actualMintAmount / exchangeRate\n */\n\n (vars.mathErr, vars.mintTokens) = vars.actualMintAmount.divScalarByExpTruncate(\n Exp({mantissa: vars.exchangeRateMantissa})\n );\n require(vars.mathErr == MathError.NO_ERROR, 'MINT_EXCHANGE_CALCULATION_FAILED');\n\n /*\n * We calculate the new total supply of cTokens and minter token balance, checking for overflow:\n * totalSupplyNew = totalSupply + mintTokens\n * accountTokensNew = accountTokens[minter] + mintTokens\n */\n (vars.mathErr, vars.totalSupplyNew) = totalSupply.addUInt(vars.mintTokens);\n require(vars.mathErr == MathError.NO_ERROR, 'MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED');\n\n (vars.mathErr, vars.accountTokensNew) = accountTokens[minter].addUInt(vars.mintTokens);\n require(vars.mathErr == MathError.NO_ERROR, 'MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED');\n\n /* We write previously calculated values into storage */\n totalSupply = vars.totalSupplyNew;\n accountTokens[minter] = vars.accountTokensNew;\n\n /* We emit a Mint event, and a Transfer event */\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens);\n emit Transfer(address(this), minter, vars.mintTokens);\n\n /* We call the defense hook */\n // unused function\n // comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\n\n return (uint256(Error.NO_ERROR), vars.actualMintAmount);\n }\n\n /**\n * @notice Sender redeems cTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemTokens The number of cTokens to redeem into underlying\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function redeemInternal(uint256 redeemTokens) internal nonReentrant returns (uint256) {\n uint256 error = accrueInterest();\n if (error != uint256(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\n Error(error).fail(FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\n }\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\n return redeemFresh(payable(msg.sender), redeemTokens, 0);\n }\n\n /**\n * @notice Sender redeems cTokens 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 cTokens\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function redeemUnderlyingInternal(uint256 redeemAmount) internal nonReentrant returns (uint256) {\n uint256 error = accrueInterest();\n if (error != uint256(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\n Error(error).fail(FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\n }\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\n return redeemFresh(payable(msg.sender), 0, redeemAmount);\n }\n\n struct RedeemLocalVars {\n Error err;\n MathError mathErr;\n uint256 exchangeRateMantissa;\n uint256 redeemTokens;\n uint256 redeemAmount;\n uint256 totalSupplyNew;\n uint256 accountTokensNew;\n }\n\n /**\n * @notice User redeems cTokens in exchange for the underlying asset\n * @dev Assumes interest has already been accrued up to the current block\n * @param redeemer The address of the account which is redeeming the tokens\n * @param redeemTokensIn The number of cTokens 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 cTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function redeemFresh(\n address payable redeemer,\n uint256 redeemTokensIn,\n uint256 redeemAmountIn\n ) internal returns (uint256) {\n require(redeemTokensIn == 0 || redeemAmountIn == 0, 'one of redeemTokensIn or redeemAmountIn must be zero');\n\n RedeemLocalVars memory vars;\n\n /* exchangeRate = invoke Exchange Rate Stored() */\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\n if (vars.mathErr != MathError.NO_ERROR) {\n Error.MATH_ERROR.failOpaque(FailureInfo.REDEEM_EXCHANGE_RATE_READ_FAILED, uint256(vars.mathErr));\n }\n\n /* If redeemTokensIn > 0: */\n if (redeemTokensIn > 0) {\n /*\n * We calculate the exchange rate and the amount of underlying to be redeemed:\n * redeemTokens = redeemTokensIn\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\n */\n vars.redeemTokens = redeemTokensIn;\n\n (vars.mathErr, vars.redeemAmount) = Exp({mantissa: vars.exchangeRateMantissa}).mulScalarTruncate(redeemTokensIn);\n if (vars.mathErr != MathError.NO_ERROR) {\n Error.MATH_ERROR.failOpaque(FailureInfo.REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED, uint256(vars.mathErr));\n }\n } else {\n /*\n * We get the current exchange rate and calculate the amount to be redeemed:\n * redeemTokens = redeemAmountIn / exchangeRate\n * redeemAmount = redeemAmountIn\n */\n\n (vars.mathErr, vars.redeemTokens) = redeemAmountIn.divScalarByExpTruncate(\n Exp({mantissa: vars.exchangeRateMantissa})\n );\n if (vars.mathErr != MathError.NO_ERROR) {\n return\n Error.MATH_ERROR.failOpaque(FailureInfo.REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED, uint256(vars.mathErr));\n }\n\n vars.redeemAmount = redeemAmountIn;\n }\n\n /* Fail if redeem not allowed */\n uint256 allowed = IComptroller(comptroller).redeemAllowed(address(this), redeemer, vars.redeemTokens);\n if (allowed != 0) {\n Error.COMPTROLLER_REJECTION.failOpaque(FailureInfo.REDEEM_COMPTROLLER_REJECTION, allowed);\n }\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != getBlockNumber()) {\n Error.MARKET_NOT_FRESH.fail(FailureInfo.REDEEM_FRESHNESS_CHECK);\n }\n\n /*\n * We calculate the new total supply and redeemer balance, checking for underflow:\n * totalSupplyNew = totalSupply - redeemTokens\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\n */\n (vars.mathErr, vars.totalSupplyNew) = totalSupply.subUInt(vars.redeemTokens);\n if (vars.mathErr != MathError.NO_ERROR) {\n Error.MATH_ERROR.failOpaque(FailureInfo.REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED, uint256(vars.mathErr));\n }\n\n (vars.mathErr, vars.accountTokensNew) = accountTokens[redeemer].subUInt(vars.redeemTokens);\n if (vars.mathErr != MathError.NO_ERROR) {\n Error.MATH_ERROR.failOpaque(FailureInfo.REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, uint256(vars.mathErr));\n }\n\n /* Fail gracefully if protocol has insufficient cash */\n if (isCToken && (getCashPrior() < vars.redeemAmount)) {\n Error.TOKEN_INSUFFICIENT_CASH.fail(FailureInfo.REDEEM_TRANSFER_OUT_NOT_POSSIBLE);\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write previously calculated values into storage */\n totalSupply = vars.totalSupplyNew;\n accountTokens[redeemer] = vars.accountTokensNew;\n\n /*\n * We invoke doTransferOut for the redeemer and the redeemAmount.\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\n * On success, the cToken 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(redeemer, vars.redeemAmount);\n\n /* We emit a Transfer event, and a Redeem event */\n emit Transfer(redeemer, address(this), vars.redeemTokens);\n emit Redeem(redeemer, vars.redeemAmount, vars.redeemTokens);\n\n /* We call the defense hook */\n IComptroller(comptroller).redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\n\n return uint256(Error.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 uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function borrowInternal(uint256 borrowAmount) internal nonReentrant returns (uint256) {\n uint256 error = accrueInterest();\n if (error != uint256(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\n Error(error).fail(FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\n }\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\n return borrowFresh(payable(msg.sender), borrowAmount);\n }\n\n struct BorrowLocalVars {\n MathError mathErr;\n uint256 accountBorrows;\n uint256 accountBorrowsNew;\n uint256 totalBorrowsNew;\n }\n\n /**\n * @notice Users borrow assets from the protocol to their own address\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function borrowFresh(address payable borrower, uint256 borrowAmount) internal returns (uint256) {\n /* Fail if borrow not allowed */\n uint256 allowed = IComptroller(comptroller).borrowAllowed(address(this), borrower, borrowAmount);\n if (allowed != 0) {\n Error.COMPTROLLER_REJECTION.failOpaque(FailureInfo.BORROW_COMPTROLLER_REJECTION, allowed);\n }\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != getBlockNumber()) {\n Error.MARKET_NOT_FRESH.fail(FailureInfo.BORROW_FRESHNESS_CHECK);\n }\n\n /* Fail gracefully if protocol has insufficient underlying cash */\n if (isCToken && (getCashPrior() < borrowAmount)) {\n Error.TOKEN_INSUFFICIENT_CASH.fail(FailureInfo.BORROW_CASH_NOT_AVAILABLE);\n }\n\n BorrowLocalVars memory vars;\n\n /*\n * We calculate the new borrower and total borrow balances, failing on overflow:\n * accountBorrowsNew = accountBorrows + borrowAmount\n * totalBorrowsNew = totalBorrows + borrowAmount\n */\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\n if (vars.mathErr != MathError.NO_ERROR) {\n return\n Error.MATH_ERROR.failOpaque(FailureInfo.BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED, uint256(vars.mathErr));\n }\n\n (vars.mathErr, vars.accountBorrowsNew) = vars.accountBorrows.addUInt(borrowAmount);\n if (vars.mathErr != MathError.NO_ERROR) {\n return\n Error.MATH_ERROR.failOpaque(\n FailureInfo.BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\n uint256(vars.mathErr)\n );\n }\n\n (vars.mathErr, vars.totalBorrowsNew) = totalBorrows.addUInt(borrowAmount);\n if (vars.mathErr != MathError.NO_ERROR) {\n return\n Error.MATH_ERROR.failOpaque(FailureInfo.BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED, uint256(vars.mathErr));\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the previously calculated values into storage */\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = vars.totalBorrowsNew;\n\n /*\n * We invoke doTransferOut for the borrower and the borrowAmount.\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\n * On success, the cToken borrowAmount less of cash.\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n */\n doTransferOut(borrower, borrowAmount);\n\n /* We emit a Borrow event */\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\n\n /* We call the defense hook */\n // unused function\n // comptroller.borrowVerify(address(this), borrower, borrowAmount);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\n */\n function repayBorrowInternal(uint256 repayAmount) internal nonReentrant returns (uint256, uint256) {\n uint256 error = accrueInterest();\n if (error != uint256(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\n Error(error).fail(FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED);\n }\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\n }\n\n /**\n * @notice Sender repays a borrow belonging to borrower\n * @param borrower the account with the debt being payed off\n * @param repayAmount The amount to repay\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\n */\n function repayBorrowBehalfInternal(\n address borrower,\n uint256 repayAmount\n ) internal nonReentrant returns (uint256, uint256) {\n uint256 error = accrueInterest();\n if (error != uint256(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\n Error(error).fail(FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED);\n }\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\n }\n\n struct RepayBorrowLocalVars {\n Error err;\n MathError mathErr;\n uint256 repayAmount;\n uint256 borrowerIndex;\n uint256 accountBorrows;\n uint256 accountBorrowsNew;\n uint256 totalBorrowsNew;\n uint256 actualRepayAmount;\n }\n\n /**\n * @notice Borrows are repaid by another user (possibly the borrower).\n * @param payer the account paying off the borrow\n * @param borrower the account with the debt being payed off\n * @param repayAmount the amount of undelrying tokens being returned\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\n */\n function repayBorrowFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256, uint256) {\n /* Fail if repayBorrow not allowed */\n uint256 allowed = IComptroller(comptroller).repayBorrowAllowed(address(this), payer, borrower, repayAmount);\n if (allowed != 0) {\n Error.COMPTROLLER_REJECTION.failOpaque(FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed);\n }\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != getBlockNumber()) {\n Error.MARKET_NOT_FRESH.fail(FailureInfo.REPAY_BORROW_FRESHNESS_CHECK);\n }\n\n RepayBorrowLocalVars memory vars;\n\n /* We remember the original borrowerIndex for verification purposes */\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\n\n /* We fetch the amount the borrower owes, with accumulated interest */\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\n if (vars.mathErr != MathError.NO_ERROR) {\n Error.MATH_ERROR.failOpaque(\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\n uint256(vars.mathErr)\n );\n }\n\n /* If repayAmount == -1, repayAmount = accountBorrows */\n if (repayAmount == ~uint256(0)) {\n vars.repayAmount = vars.accountBorrows;\n } else {\n vars.repayAmount = repayAmount;\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We call doTransferIn for the payer and the repayAmount\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\n * On success, the cToken holds an additional repayAmount of cash.\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\n * it returns the amount actually transferred, in case of a fee.\n */\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\n\n /*\n * We calculate the new borrower and total borrow balances, failing on underflow:\n * accountBorrowsNew = accountBorrows - actualRepayAmount\n * totalBorrowsNew = totalBorrows - actualRepayAmount\n */\n (vars.mathErr, vars.accountBorrowsNew) = vars.accountBorrows.subUInt(vars.actualRepayAmount);\n require(vars.mathErr == MathError.NO_ERROR, 'REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED');\n\n (vars.mathErr, vars.totalBorrowsNew) = totalBorrows.subUInt(vars.actualRepayAmount);\n require(vars.mathErr == MathError.NO_ERROR, 'REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED');\n\n /* We write the previously calculated values into storage */\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = vars.totalBorrowsNew;\n\n /* We emit a RepayBorrow event */\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\n\n /* We call the defense hook */\n // unused function\n // comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\n\n return (uint256(Error.NO_ERROR), vars.actualRepayAmount);\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param borrower The borrower of this cToken to be liquidated\n * @param cTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\n */\n function liquidateBorrowInternal(\n address borrower,\n uint256 repayAmount,\n address cTokenCollateral\n ) internal nonReentrant returns (uint256, uint256) {\n uint256 error = accrueInterest();\n if (error != uint256(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\n Error(error).fail(FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED);\n }\n\n error = ICToken(cTokenCollateral).accrueInterest();\n if (error != uint256(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\n Error(error).fail(FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED);\n }\n\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, cTokenCollateral);\n }\n\n /**\n * @notice The liquidator liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param borrower The borrower of this cToken to be liquidated\n * @param liquidator The address repaying the borrow and seizing collateral\n * @param cTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\n */\n function liquidateBorrowFresh(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n address cTokenCollateral\n ) internal returns (uint256, uint256) {\n /* Fail if liquidate not allowed */\n uint256 allowed = liquidateBorrowAllowed(address(cTokenCollateral), liquidator, borrower, repayAmount);\n if (allowed != 0) {\n Error.COMPTROLLER_REJECTION.failOpaque(FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed);\n }\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != getBlockNumber()) {\n Error.MARKET_NOT_FRESH.fail(FailureInfo.LIQUIDATE_FRESHNESS_CHECK);\n }\n\n /* Verify cTokenCollateral market's block number equals current block number */\n if (ICToken(cTokenCollateral).accrualBlockNumber() != getBlockNumber()) {\n Error.MARKET_NOT_FRESH.fail(FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK);\n }\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n Error.INVALID_ACCOUNT_PAIR.fail(FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER);\n }\n\n /* Fail if repayAmount = 0 */\n if (repayAmount == 0) {\n Error.INVALID_CLOSE_AMOUNT_REQUESTED.fail(FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO);\n }\n\n /* Fail if repayAmount = -1 */\n if (repayAmount == ~uint256(0)) {\n Error.INVALID_CLOSE_AMOUNT_REQUESTED.fail(FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX);\n }\n\n /* Fail if repayBorrow fails */\n (uint256 repayBorrowError, uint256 actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\n if (repayBorrowError != uint256(Error.NO_ERROR)) {\n Error(repayBorrowError).fail(FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED);\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We calculate the number of collateral tokens that will be seized */\n (uint256 amountSeizeError, uint256 seizeTokens) = liquidateCalculateSeizeTokens(\n cTokenCollateral,\n actualRepayAmount\n );\n require(amountSeizeError == uint256(Error.NO_ERROR), 'LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED');\n\n /* Revert if borrower collateral token balance < seizeTokens */\n require(ICToken(cTokenCollateral).balanceOf(borrower) >= seizeTokens, 'LIQUIDATE_SEIZE_TOO_MUCH');\n\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\n uint256 seizeError;\n if (cTokenCollateral == address(this)) {\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\n } else {\n seizeError = ICToken(cTokenCollateral).seize(liquidator, borrower, seizeTokens);\n }\n\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\n require(seizeError == uint256(Error.NO_ERROR), 'token seizure failed');\n\n /* We emit a LiquidateBorrow event */\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(cTokenCollateral), seizeTokens);\n\n /* We call the defense hook */\n // unused function\n // comptroller.liquidateBorrowVerify(address(this), address(cTokenCollateral), liquidator, borrower, actualRepayAmount, seizeTokens);\n\n return (uint256(Error.NO_ERROR), actualRepayAmount);\n }\n\n /**\n * @notice Transfers collateral tokens (this market) to the liquidator.\n * @dev Will fail unless called by another cToken during the process of liquidation.\n * Its absolutely critical to use msg.sender as the borrowed cToken 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 cTokens to seize\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function seize(\n address liquidator,\n address borrower,\n uint256 seizeTokens\n ) external override nonReentrant returns (uint256) {\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\n }\n\n struct SeizeInternalLocalVars {\n MathError mathErr;\n uint256 borrowerTokensNew;\n uint256 liquidatorTokensNew;\n uint256 liquidatorSeizeTokens;\n uint256 protocolSeizeTokens;\n uint256 protocolSeizeAmount;\n uint256 exchangeRateMantissa;\n uint256 totalReservesNew;\n uint256 totalSupplyNew;\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 CToken.\n * Its absolutely critical to use msg.sender as the seizer cToken and not a parameter.\n * @param seizerToken The contract seizing the collateral (i.e. borrowed cToken)\n * @param liquidator The account receiving seized collateral\n * @param borrower The account having collateral seized\n * @param seizeTokens The number of cTokens to seize\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function seizeInternal(\n address seizerToken,\n address liquidator,\n address borrower,\n uint256 seizeTokens\n ) internal returns (uint256) {\n /* Fail if seize not allowed */\n uint256 allowed = IComptroller(comptroller).seizeAllowed(\n address(this),\n seizerToken,\n liquidator,\n borrower,\n seizeTokens\n );\n if (allowed != 0) {\n Error.COMPTROLLER_REJECTION.failOpaque(FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\n }\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n Error.INVALID_ACCOUNT_PAIR.fail(FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\n }\n\n SeizeInternalLocalVars memory vars;\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 (vars.mathErr, vars.borrowerTokensNew) = accountTokens[borrower].subUInt(seizeTokens);\n if (vars.mathErr != MathError.NO_ERROR) {\n Error.MATH_ERROR.failOpaque(FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint256(vars.mathErr));\n }\n\n vars.protocolSeizeTokens = seizeTokens.mul_(Exp({mantissa: protocolSeizeShareMantissa}));\n vars.liquidatorSeizeTokens = seizeTokens.sub_(vars.protocolSeizeTokens);\n\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\n require(vars.mathErr == MathError.NO_ERROR, 'exchange rate math error');\n\n vars.protocolSeizeAmount = Exp({mantissa: vars.exchangeRateMantissa}).mul_ScalarTruncate(vars.protocolSeizeTokens);\n\n vars.totalReservesNew = totalReserves.add_(vars.protocolSeizeAmount);\n vars.totalSupplyNew = totalSupply.sub_(vars.protocolSeizeTokens);\n\n (vars.mathErr, vars.liquidatorTokensNew) = accountTokens[liquidator].addUInt(vars.liquidatorSeizeTokens);\n if (vars.mathErr != MathError.NO_ERROR) {\n Error.MATH_ERROR.failOpaque(FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint256(vars.mathErr));\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the previously calculated values into storage */\n totalReserves = vars.totalReservesNew;\n totalSupply = vars.totalSupplyNew;\n accountTokens[borrower] = vars.borrowerTokensNew;\n accountTokens[liquidator] = vars.liquidatorTokensNew;\n\n /* Emit a Transfer event */\n emit Transfer(borrower, liquidator, vars.liquidatorSeizeTokens);\n emit Transfer(borrower, address(this), vars.protocolSeizeTokens);\n emit ReservesAdded(address(this), vars.protocolSeizeAmount, vars.totalReservesNew);\n\n /* We call the defense hook */\n // unused function\n // comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\n\n return uint256(Error.NO_ERROR);\n }\n\n /*** Admin Functions ***/\n\n /**\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @param newPendingAdmin New pending admin.\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setPendingAdmin(address payable newPendingAdmin) external override onlyAdmin returns (uint256) {\n // Save current value, if any, for inclusion in log\n address oldPendingAdmin = pendingAdmin;\n\n // Store pendingAdmin with value newPendingAdmin\n require(newPendingAdmin != address(0), 'Address is Zero!');\n pendingAdmin = newPendingAdmin;\n\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\n * @dev Admin function for pending admin to accept role and update admin\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _acceptAdmin() external override returns (uint256) {\n // Check caller is pendingAdmin and pendingAdmin ≠ address(0)\n if (msg.sender != pendingAdmin || msg.sender == address(0)) {\n Error.UNAUTHORIZED.fail(FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\n }\n\n // Save current values for inclusion in log\n address oldAdmin = admin;\n address oldPendingAdmin = pendingAdmin;\n\n // Store admin with value pendingAdmin\n admin = pendingAdmin;\n\n // Clear the pending value\n pendingAdmin = payable(0);\n\n emit NewAdmin(oldAdmin, admin);\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Sets a new comptroller for the market\n * @dev Admin function to set a new comptroller\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setComptroller(address newComptroller) public override onlyAdmin returns (uint256) {\n address oldComptroller = comptroller;\n // Ensure invoke comptroller.isComptroller() returns true\n require(IComptroller(newComptroller).isComptroller(), 'marker method returned false');\n\n // Set market's comptroller to newComptroller\n comptroller = newComptroller;\n\n // Emit NewComptroller(oldComptroller, newComptroller)\n emit NewComptroller(oldComptroller, newComptroller);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\n * @dev Admin function to accrue interest and set a new reserve factor\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setReserveFactor(uint256 newReserveFactorMantissa) external override nonReentrant returns (uint256) {\n uint256 error = accrueInterest();\n if (error != uint256(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\n Error(error).fail(FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\n }\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\n return _setReserveFactorFresh(newReserveFactorMantissa);\n }\n\n /**\n * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\n * @dev Admin function to set a new reserve factor\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setReserveFactorFresh(uint256 newReserveFactorMantissa) internal onlyAdmin returns (uint256) {\n // Verify market's block number equals current block number\n if (accrualBlockNumber != getBlockNumber()) {\n Error.MARKET_NOT_FRESH.fail(FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\n }\n\n // Check newReserveFactor ≤ maxReserveFactor\n if (newReserveFactorMantissa > RESERVE_FACTOR_MAX_MANTISSA) {\n Error.BAD_INPUT.fail(FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\n }\n\n uint256 oldReserveFactorMantissa = reserveFactorMantissa;\n reserveFactorMantissa = newReserveFactorMantissa;\n\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Accrues interest and reduces reserves by transferring from msg.sender\n * @param addAmount Amount of addition to reserves\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _addReservesInternal(uint256 addAmount) internal nonReentrant returns (uint256) {\n uint256 error = accrueInterest();\n if (error != uint256(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\n Error(error).fail(FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\n }\n\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\n (error, ) = _addReservesFresh(addAmount);\n return error;\n }\n\n /**\n * @notice Add reserves by transferring from caller\n * @dev Requires fresh interest accrual\n * @param addAmount Amount of addition to reserves\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\n */\n function _addReservesFresh(uint256 addAmount) internal returns (uint256, uint256) {\n // totalReserves + actualAddAmount\n uint256 totalReservesNew;\n uint256 actualAddAmount;\n\n // We fail gracefully unless market's block number equals current block number\n if (accrualBlockNumber != getBlockNumber()) {\n Error.MARKET_NOT_FRESH.fail(FailureInfo.ADD_RESERVES_FRESH_CHECK);\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We call doTransferIn for the caller and the addAmount\n * Note: The cToken must handle variations between ERC-20 and ETH underlying.\n * On success, the cToken holds an additional addAmount of cash.\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\n * it returns the amount actually transferred, in case of a fee.\n */\n\n actualAddAmount = doTransferIn(msg.sender, addAmount);\n\n totalReservesNew = totalReserves + actualAddAmount;\n\n /* Revert on overflow */\n require(totalReservesNew >= totalReserves, 'add reserves unexpected overflow');\n\n // Store reserves[n+1] = reserves[n] + actualAddAmount\n totalReserves = totalReservesNew;\n\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\n\n /* Return (NO_ERROR, actualAddAmount) */\n return (uint256(Error.NO_ERROR), actualAddAmount);\n }\n\n /**\n * @notice Accrues interest and reduces reserves by transferring to admin\n * @param reduceAmount Amount of reduction to reserves\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _reduceReserves(uint256 reduceAmount) external override nonReentrant returns (uint256) {\n uint256 error = accrueInterest();\n if (error != uint256(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\n Error(error).fail(FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\n }\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\n return _reduceReservesFresh(reduceAmount);\n }\n\n /**\n * @notice Reduces reserves by transferring to admin\n * @dev Requires fresh interest accrual\n * @param reduceAmount Amount of reduction to reserves\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _reduceReservesFresh(uint256 reduceAmount) internal onlyAdmin returns (uint256) {\n // totalReserves - reduceAmount\n uint256 totalReservesNew;\n\n // We fail gracefully unless market's block number equals current block number\n if (accrualBlockNumber != getBlockNumber()) {\n Error.MARKET_NOT_FRESH.fail(FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\n }\n\n // Fail gracefully if protocol has insufficient underlying cash\n if (getCashPrior() < reduceAmount) {\n Error.TOKEN_INSUFFICIENT_CASH.fail(FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\n }\n\n // Check reduceAmount ≤ reserves[n] (totalReserves)\n if (reduceAmount > totalReserves) {\n Error.BAD_INPUT.fail(FailureInfo.REDUCE_RESERVES_VALIDATION);\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n totalReservesNew = totalReserves - reduceAmount;\n // We checked reduceAmount <= totalReserves above, so this should never revert.\n require(totalReservesNew <= totalReserves, 'reduce reserves unexpected underflow');\n\n // Store reserves[n+1] = reserves[n] - reduceAmount\n totalReserves = totalReservesNew;\n\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n doTransferOut(admin, reduceAmount);\n\n emit ReservesReduced(admin, reduceAmount, totalReservesNew);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\n * @dev Admin function to accrue interest and update the interest rate model\n * @param newInterestRateModel the new interest rate model to use\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setInterestRateModel(address newInterestRateModel) public override returns (uint256) {\n uint256 error = accrueInterest();\n if (error != uint256(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\n Error(error).fail(FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\n }\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\n return _setInterestRateModelFresh(newInterestRateModel);\n }\n\n /**\n * @notice 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 * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setInterestRateModelFresh(address newInterestRateModel) internal onlyAdmin returns (uint256) {\n // Used to store old model for use in the event that is emitted on success\n address oldInterestRateModel;\n // We fail gracefully unless market's block number equals current block number\n if (accrualBlockNumber != getBlockNumber()) {\n Error.MARKET_NOT_FRESH.fail(FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\n }\n\n // Track the market's current interest rate model\n oldInterestRateModel = interestRateModel;\n\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\n require(IInterestRateModel(interestRateModel).isInterestRateModel(), 'marker method returned false');\n\n // Set the interest rate model to newInterestRateModel\n interestRateModel = newInterestRateModel;\n\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\n\n return uint256(Error.NO_ERROR);\n }\n\n function _syncUnderlyingBalance() external onlyAdmin {\n underlyingBalance = ICToken(underlying).balanceOf(address(this));\n }\n\n /*** Safe Token ***/\n\n /**\n * @notice Gets balance of this contract in terms of the underlying\n * @dev This excludes the value of the current message, if any\n * @return The quantity of underlying owned by this contract\n */\n function getCashPrior() internal view virtual returns (uint256);\n\n /**\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\n * This may revert due to insufficient balance or insufficient allowance.\n */\n function doTransferIn(address from, uint256 amount) internal virtual returns (uint256);\n\n /**\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure tather than reverting.\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\n */\n function doTransferOut(address payable to, uint256 amount) internal virtual;\n\n /*** Reentrancy Guard ***/\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n */\n modifier nonReentrant() {\n require(_notEntered, 're-entered');\n _notEntered = false;\n _;\n _notEntered = true; // get a gas-refund post-Istanbul\n }\n\n /**\n * @notice Returns true if the given cToken market has been deprecated\n * @dev All borrows in a deprecated cToken market can be immediately liquidated\n */\n function isDeprecated() public view returns (bool) {\n return\n IComptroller(comptroller).marketGroupId(address(this)) == 0 &&\n //borrowGuardianPaused[cToken] == true &&\n IUnderwriterAdmin(IComptroller(comptroller).underWriterAdmin())._getBorrowPaused(address(this)) &&\n reserveFactorMantissa == 1e18;\n }\n\n /**\n * @notice Checks if the liquidation should be allowed to occur\n * @param cTokenCollateral Asset which was used as collateral and will be seized\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @param repayAmount The amount of underlying being repaid\n */\n function liquidateBorrowAllowed(\n address cTokenCollateral,\n address liquidator,\n address borrower,\n uint256 repayAmount\n ) public view returns (uint256) {\n // Shh - currently unused: liquidator;\n\n require(\n IComptroller(comptroller).isListed(address(this)) && IComptroller(comptroller).isListed(cTokenCollateral),\n 'MARKET_NOT_LISTED'\n );\n\n (, uint256 borrowBalance) = borrowBalanceStoredInternal(borrower);\n\n /* allow accounts to be liquidated if the market is deprecated */\n if (isDeprecated()) {\n require(borrowBalance >= repayAmount, 'too much repay');\n } else {\n /* The borrower must have shortfall in order to be liquidatable */\n (, , uint256 shortfall) = IComptroller(comptroller).getHypotheticalAccountLiquidity(\n borrower,\n address(this),\n 0,\n 0\n );\n\n require(shortfall > 0, 'insufficient shortfall');\n\n /* The liquidator may not repay more than what is allowed by the closeFactor */\n uint256 maxClose = Exp({mantissa: IComptroller(comptroller).closeFactorMantissa()}).mul_ScalarTruncate(\n borrowBalance\n );\n require(repayAmount <= maxClose, 'too much repay');\n }\n return uint256(0);\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 ICToken(cToken).liquidateBorrowFresh)\n * @param cTokenCollateral The address of the collateral cToken\n * @param actualRepayAmount The amount of cTokenBorrowed underlying to convert into cTokenCollateral tokens\n * @return (errorCode, number of cTokenCollateral tokens to be seized in a liquidation)\n */\n function liquidateCalculateSeizeTokens(\n address cTokenCollateral,\n uint256 actualRepayAmount\n ) public view returns (uint256, uint256) {\n /* Read oracle prices for borrowed and collateral markets */\n address oracle = IComptroller(comptroller).oracle();\n uint256 priceBorrowedMantissa = IPriceOracle(oracle).getUnderlyingPrice(address(address(this)));\n uint256 priceCollateralMantissa = IPriceOracle(oracle).getUnderlyingPrice(address(cTokenCollateral));\n require(priceBorrowedMantissa > 0 && priceCollateralMantissa > 0, 'PRICE_ERROR');\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 = ICToken(cTokenCollateral).exchangeRateStored(); // Note: reverts on error\n uint256 seizeTokens;\n Exp memory numerator;\n Exp memory denominator;\n Exp memory ratio;\n\n numerator = Exp({mantissa: IComptroller(comptroller).liquidationIncentiveMantissa()}).mul_(\n Exp({mantissa: priceBorrowedMantissa})\n );\n denominator = Exp({mantissa: priceCollateralMantissa}).mul_(Exp({mantissa: exchangeRateMantissa}));\n ratio = numerator.div_(denominator);\n\n seizeTokens = ratio.mul_ScalarTruncate(actualRepayAmount);\n\n return (uint256(0), seizeTokens);\n }\n\n function getAccountBorrows(address account) public view returns (uint256 principal, uint256 interestIndex) {\n BorrowSnapshot memory accountBorrow = accountBorrows[account];\n principal = accountBorrow.principal;\n interestIndex = accountBorrow.interestIndex;\n }\n\n function getDiscountRate() public view returns (uint256) {\n return discountRateMantissa;\n }\n\n function _setDiscountRate(uint256 discountRateMantissa_) external returns (uint256) {\n require(msg.sender == admin, 'UNAUTHORIZED');\n uint256 oldDiscountRateMantissa_ = discountRateMantissa;\n discountRateMantissa = discountRateMantissa_;\n emit NewDiscountRate(oldDiscountRateMantissa_, discountRateMantissa_);\n return discountRateMantissa;\n }\n}\n" }, "contracts/CToken/Interfaces/ICErc20.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\ninterface ICErc20 {\n /*** User Interface ***/\n\n function mint(uint256 mintAmount) external returns (uint256);\n\n function redeem(uint256 redeemTokens) external returns (uint256);\n\n function redeemUnderlying(uint256 redeemAmount) external returns (uint256);\n\n function borrow(uint256 borrowAmount) external returns (uint256);\n\n function repayBorrow(uint256 repayAmount) external returns (uint256);\n\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external returns (uint256);\n\n function liquidateBorrow(\n address borrower,\n uint256 repayAmount,\n address cTokenCollateral\n ) external returns (uint256);\n\n function sweepToken(address token) external;\n\n /*** Admin Functions ***/\n\n function _addReserves(uint256 addAmount) external returns (uint256);\n}\n" }, "contracts/Exponential/Exponential.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\nimport '../Exponential/ExponentialNoError.sol';\nimport './CarefulMath.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 */\nlibrary Exponential {\n uint256 constant expScale = 1e18;\n uint256 constant halfExpScale = expScale / 2;\n using CarefulMath for uint256;\n using ExponentialNoError for Exp;\n\n /**\n * @dev Creates an exponential from numerator and denominator values.\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\n * or if `denom` is zero.\n */\n function getExp(uint256 num, uint256 denom) internal pure returns (MathError, Exp memory) {\n (MathError err0, uint256 scaledNumerator) = num.mulUInt(expScale);\n if (err0 != MathError.NO_ERROR) {\n return (err0, Exp({mantissa: 0}));\n }\n\n (MathError err1, uint256 rational) = scaledNumerator.divUInt(denom);\n if (err1 != MathError.NO_ERROR) {\n return (err1, Exp({mantissa: 0}));\n }\n\n return (MathError.NO_ERROR, Exp({mantissa: rational}));\n }\n\n /**\n * @dev Adds two exponentials, returning a new exponential.\n */\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\n (MathError error, uint256 result) = a.mantissa.addUInt(b.mantissa);\n\n return (error, Exp({mantissa: result}));\n }\n\n /**\n * @dev Subtracts two exponentials, returning a new exponential.\n */\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\n (MathError error, uint256 result) = a.mantissa.subUInt(b.mantissa);\n\n return (error, Exp({mantissa: result}));\n }\n\n /**\n * @dev Multiply an Exp by a scalar, returning a new Exp.\n */\n function mulScalar(Exp memory a, uint256 scalar) internal pure returns (MathError, Exp memory) {\n (MathError err0, uint256 scaledMantissa) = a.mantissa.mulUInt(scalar);\n if (err0 != MathError.NO_ERROR) {\n return (err0, Exp({mantissa: 0}));\n }\n\n return (MathError.NO_ERROR, Exp({mantissa: scaledMantissa}));\n }\n\n /**\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\n */\n function mulScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (MathError, uint256) {\n (MathError err, Exp memory product) = mulScalar(a, scalar);\n if (err != MathError.NO_ERROR) {\n return (err, 0);\n }\n\n return (MathError.NO_ERROR, product.truncate());\n }\n\n /**\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\n */\n function mulScalarTruncateAddUInt(\n Exp memory a,\n uint256 scalar,\n uint256 addend\n ) internal pure returns (MathError, uint256) {\n (MathError err, Exp memory product) = mulScalar(a, scalar);\n if (err != MathError.NO_ERROR) {\n return (err, 0);\n }\n\n return product.truncate().addUInt(addend);\n }\n\n /**\n * @dev Divide an Exp by a scalar, returning a new Exp.\n */\n function divScalar(Exp memory a, uint256 scalar) internal pure returns (MathError, Exp memory) {\n (MathError err0, uint256 descaledMantissa) = a.mantissa.divUInt(scalar);\n if (err0 != MathError.NO_ERROR) {\n return (err0, Exp({mantissa: 0}));\n }\n\n return (MathError.NO_ERROR, Exp({mantissa: descaledMantissa}));\n }\n\n /**\n * @dev Divide a scalar by an Exp, returning a new Exp.\n */\n function divScalarByExp(uint256 scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\n /*\n We are doing this as:\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\n\n How it works:\n Exp = a / b;\n Scalar = s;\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\n */\n (MathError err0, uint256 numerator) = expScale.mulUInt(scalar);\n if (err0 != MathError.NO_ERROR) {\n return (err0, Exp({mantissa: 0}));\n }\n return getExp(numerator, divisor.mantissa);\n }\n\n /**\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\n */\n function divScalarByExpTruncate(uint256 scalar, Exp memory divisor) internal pure returns (MathError, uint256) {\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\n if (err != MathError.NO_ERROR) {\n return (err, 0);\n }\n\n return (MathError.NO_ERROR, fraction.truncate());\n }\n\n /**\n * @dev Multiplies two exponentials, returning a new exponential.\n */\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\n (MathError err0, uint256 doubleScaledProduct) = a.mantissa.mulUInt(b.mantissa);\n if (err0 != MathError.NO_ERROR) {\n return (err0, Exp({mantissa: 0}));\n }\n\n // We add half the scale before dividing so that we get rounding instead of truncation.\n // See \"Listing 6\" and text above it at https://accu.org/index.php/journals/1717\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\n (MathError err1, uint256 doubleScaledProductWithHalfScale) = halfExpScale.addUInt(doubleScaledProduct);\n if (err1 != MathError.NO_ERROR) {\n return (err1, Exp({mantissa: 0}));\n }\n\n (MathError err2, uint256 product) = doubleScaledProductWithHalfScale.divUInt(expScale);\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\n assert(err2 == MathError.NO_ERROR);\n\n return (MathError.NO_ERROR, Exp({mantissa: product}));\n }\n\n /**\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\n */\n function mulExp(uint256 a, uint256 b) internal pure returns (MathError, Exp memory) {\n return mulExp(Exp({mantissa: a}), Exp({mantissa: b}));\n }\n\n /**\n * @dev Multiplies three exponentials, returning a new exponential.\n */\n function mulExp3(\n Exp memory a,\n Exp memory b,\n Exp memory c\n ) internal pure returns (MathError, Exp memory) {\n (MathError err, Exp memory ab) = mulExp(a, b);\n if (err != MathError.NO_ERROR) {\n return (err, ab);\n }\n return mulExp(ab, c);\n }\n\n /**\n * @dev Divides two exponentials, returning a new exponential.\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\n */\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\n return getExp(a.mantissa, b.mantissa);\n }\n}\n" }, "contracts/Exponential/CarefulMath.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\n/**\n * @dev Possible error codes that we can return\n */\nenum MathError {\n NO_ERROR,\n DIVISION_BY_ZERO,\n INTEGER_OVERFLOW,\n INTEGER_UNDERFLOW\n}\n\n/**\n * @title Careful Math\n * @author Compound\n * @notice Derived from OpenZeppelin's SafeMath library\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\n */\nlibrary CarefulMath {\n /**\n * @dev Multiplies two numbers, returns an error on overflow.\n */\n function mulUInt(uint256 a, uint256 b) internal pure returns (MathError, uint256) {\n if (a == 0) {\n return (MathError.NO_ERROR, 0);\n }\n\n uint256 c = a * b;\n\n if (c / a != b) {\n return (MathError.INTEGER_OVERFLOW, 0);\n } else {\n return (MathError.NO_ERROR, c);\n }\n }\n\n /**\n * @dev Integer division of two numbers, truncating the quotient.\n */\n function divUInt(uint256 a, uint256 b) internal pure returns (MathError, uint256) {\n if (b == 0) {\n return (MathError.DIVISION_BY_ZERO, 0);\n }\n\n return (MathError.NO_ERROR, a / b);\n }\n\n /**\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\n */\n function subUInt(uint256 a, uint256 b) internal pure returns (MathError, uint256) {\n if (b <= a) {\n return (MathError.NO_ERROR, a - b);\n } else {\n return (MathError.INTEGER_UNDERFLOW, 0);\n }\n }\n\n /**\n * @dev Adds two numbers, returns an error on overflow.\n */\n function addUInt(uint256 a, uint256 b) internal pure returns (MathError, uint256) {\n uint256 c = a + b;\n\n if (c >= a) {\n return (MathError.NO_ERROR, c);\n } else {\n return (MathError.INTEGER_OVERFLOW, 0);\n }\n }\n\n /**\n * @dev add a and b and then subtract c\n */\n function addThenSubUInt(\n uint256 a,\n uint256 b,\n uint256 c\n ) internal pure returns (MathError, uint256) {\n (MathError err0, uint256 sum) = addUInt(a, b);\n\n if (err0 != MathError.NO_ERROR) {\n return (err0, 0);\n }\n\n return subUInt(sum, c);\n }\n}\n" }, "contracts/CToken/TokenErrorReporter.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\nenum Error {\n NO_ERROR,\n UNAUTHORIZED,\n BAD_INPUT,\n COMPTROLLER_REJECTION,\n COMPTROLLER_CALCULATION_ERROR,\n INTEREST_RATE_MODEL_ERROR,\n INVALID_ACCOUNT_PAIR,\n INVALID_CLOSE_AMOUNT_REQUESTED,\n INVALID_COLLATERAL_FACTOR,\n MATH_ERROR,\n MARKET_NOT_FRESH,\n MARKET_NOT_LISTED,\n TOKEN_INSUFFICIENT_ALLOWANCE,\n TOKEN_INSUFFICIENT_BALANCE,\n TOKEN_INSUFFICIENT_CASH,\n TOKEN_TRANSFER_IN_FAILED,\n TOKEN_TRANSFER_OUT_FAILED\n}\n\n/*\n * Note: FailureInfo (but not Error) is kept in alphabetical order\n * This is because FailureInfo grows significantly faster, and\n * the order of Error has some meaning, while the order of FailureInfo\n * is entirely arbitrary.\n */\nenum FailureInfo {\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\n BORROW_ACCRUE_INTEREST_FAILED,\n BORROW_CASH_NOT_AVAILABLE,\n BORROW_FRESHNESS_CHECK,\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\n BORROW_MARKET_NOT_LISTED,\n BORROW_COMPTROLLER_REJECTION,\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\n LIQUIDATE_COMPTROLLER_REJECTION,\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\n LIQUIDATE_FRESHNESS_CHECK,\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\n LIQUIDATE_SEIZE_TOO_MUCH,\n MINT_ACCRUE_INTEREST_FAILED,\n MINT_COMPTROLLER_REJECTION,\n MINT_EXCHANGE_CALCULATION_FAILED,\n MINT_EXCHANGE_RATE_READ_FAILED,\n MINT_FRESHNESS_CHECK,\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\n MINT_TRANSFER_IN_FAILED,\n MINT_TRANSFER_IN_NOT_POSSIBLE,\n REDEEM_ACCRUE_INTEREST_FAILED,\n REDEEM_COMPTROLLER_REJECTION,\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\n REDEEM_EXCHANGE_RATE_READ_FAILED,\n REDEEM_FRESHNESS_CHECK,\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\n REDUCE_RESERVES_ADMIN_CHECK,\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\n REDUCE_RESERVES_FRESH_CHECK,\n REDUCE_RESERVES_VALIDATION,\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\n REPAY_BORROW_COMPTROLLER_REJECTION,\n REPAY_BORROW_FRESHNESS_CHECK,\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\n SET_COLLATERAL_FACTOR_VALIDATION,\n SET_COMPTROLLER_OWNER_CHECK,\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\n SET_MAX_ASSETS_OWNER_CHECK,\n SET_ORACLE_MARKET_NOT_LISTED,\n SET_PENDING_ADMIN_OWNER_CHECK,\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\n SET_RESERVE_FACTOR_ADMIN_CHECK,\n SET_RESERVE_FACTOR_FRESH_CHECK,\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\n TRANSFER_COMPTROLLER_REJECTION,\n TRANSFER_NOT_ALLOWED,\n TRANSFER_NOT_ENOUGH,\n TRANSFER_TOO_MUCH,\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\n ADD_RESERVES_FRESH_CHECK,\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE\n}\n\nlibrary TokenErrorReporter {\n /**\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\n **/\n event Failure(uint256 error, uint256 info, uint256 detail);\n\n error TokenError(uint256 errorCode, uint256 infoCode, uint256 detailCode);\n\n /**\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\n */\n function fail(Error err, FailureInfo info) internal pure returns (uint256) {\n // emit Failure(uint256(err), uint256(info), 0);\n revert TokenError(uint256(err), uint256(info), 0);\n // return uint256(err);\n }\n\n /**\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\n */\n function failOpaque(\n Error err,\n FailureInfo info,\n uint256 opaqueError\n ) internal pure returns (uint256) {\n // emit Failure(uint256(err), uint256(info), opaqueError);\n revert TokenError(uint256(err), uint256(info), opaqueError);\n // return uint256(err);\n }\n}\n" }, "contracts/CToken/CTokenStorage.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\nimport './Interfaces/ICToken.sol';\n\nabstract contract CTokenStorage is ICToken {\n bool public isCToken;\n bool public isCEther;\n /// @dev Guard variable for re-entrancy checks\n bool internal _notEntered;\n\n /// @notice Underlying asset for this CToken\n address public underlying;\n\n /// @notice EIP-20 token name for this token\n string public name;\n\n /// @notice EIP-20 token symbol for this token\n string public symbol;\n\n /// @notice EIP-20 token decimals for this token\n uint8 public decimals;\n\n /// @dev Maximum borrow rate that can ever be applied (.0005% / block)\n uint256 internal constant BORROW_RATE_MAX_MANTISSA = 0.0005e16;\n\n /// @dev Maximum fraction of interest that can be set aside for reserves\n uint256 internal constant RESERVE_FACTOR_MAX_MANTISSA = 1e18;\n\n /// @notice Administrator for this contract\n address payable public admin;\n\n /// @notice Pending administrator for this contract\n address payable public pendingAdmin;\n\n /// @notice Contract which oversees inter-cToken operations\n address public comptroller;\n\n /// @notice Model which tells what the current interest rate should be\n address public interestRateModel;\n\n /// @dev Initial exchange rate used when minting the first CTokens (used when totalSupply = 0)\n uint256 internal initialExchangeRateMantissa;\n\n /// @notice Fraction of interest currently set aside for reserves\n uint256 public reserveFactorMantissa;\n\n /// @notice Block number that interest was last accrued at\n uint256 public override accrualBlockNumber;\n\n /// @notice Accumulator of the total earned interest rate since the opening of the market\n uint256 public borrowIndex;\n\n /// @notice Total amount of outstanding borrows of the underlying in this market\n uint256 public totalBorrows;\n\n /// @notice Total amount of reserves of the underlying held in this market\n uint256 public totalReserves;\n\n /// @notice Total number of tokens in circulation\n uint256 public override totalSupply;\n\n /// @dev Official record of token balances for each account\n mapping(address => uint256) internal accountTokens;\n\n /// @dev Approved token transfer amounts on behalf of others\n mapping(address => mapping(address => uint256)) internal transferAllowances;\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 struct BorrowSnapshot {\n uint256 principal;\n uint256 interestIndex;\n }\n\n /// @dev Mapping of account addresses to outstanding borrow balances\n mapping(address => BorrowSnapshot) internal accountBorrows;\n\n /// @notice Share of seized collateral that is added to reserves\n uint256 public constant protocolSeizeShareMantissa = 2.8e16; //2.8%\n\n uint256 public discountRateMantissa = 1e18;\n\n uint256 public underlyingBalance;\n}\n" }, "contracts/CToken/Interfaces/IInterestRateModel.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\n/**\n * @title Compound's InterestRateModel Interface\n * @author Compound\n */\ninterface IInterestRateModel {\n function isInterestRateModel() external view returns (bool);\n\n /**\n * @notice Calculates the current borrow interest rate per block\n * @param cash The total amount of cash the market has\n * @param borrows The total amount of borrows the market has outstanding\n * @param reserves The total amount of reserves the market has\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\n */\n function getBorrowRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves\n ) external view returns (uint256);\n\n /**\n * @notice Calculates the current supply interest rate per block\n * @param cash The total amount of cash the market has\n * @param borrows The total amount of borrows the market has outstanding\n * @param reserves The total amount of reserves the market has\n * @param reserveFactorMantissa The current reserve factor the market has\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\n */\n function getSupplyRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 reserveFactorMantissa\n ) external view returns (uint256);\n}\n" }, "contracts/CToken/Interfaces/ICToken.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\ninterface ICToken {\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 minter, uint256 mintAmount, uint256 mintTokens);\n\n /**\n * @notice Event emitted when tokens are redeemed\n */\n event Redeem(address redeemer, uint256 redeemAmount, uint256 redeemTokens);\n\n /**\n * @notice Event emitted when underlying is borrowed\n */\n event Borrow(address borrower, uint256 borrowAmount, uint256 accountBorrows, uint256 totalBorrows);\n\n /**\n * @notice Event emitted when a borrow is repaid\n */\n event RepayBorrow(address payer, address borrower, uint256 repayAmount, uint256 accountBorrows, uint256 totalBorrows);\n\n /**\n * @notice Event emitted when a borrow is liquidated\n */\n event LiquidateBorrow(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n address cTokenCollateral,\n uint256 seizeTokens\n );\n\n /*** Admin Events ***/\n\n /**\n * @notice Event emitted when pendingAdmin is changed\n */\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\n\n /**\n * @notice Event emitted when pendingAdmin is accepted, which means admin is updated\n */\n event NewAdmin(address oldAdmin, address newAdmin);\n\n /**\n * @notice Event emitted when comptroller is changed\n */\n event NewComptroller(address oldComptroller, address newComptroller);\n\n /**\n * @notice Event emitted when interestRateModel is changed\n */\n event NewMarketInterestRateModel(address oldInterestRateModel, address newInterestRateModel);\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 benefactor, uint256 addAmount, uint256 newTotalReserves);\n\n /**\n * @notice Event emitted when the reserves are reduced\n */\n event ReservesReduced(address admin, 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 event NewDiscountRate(uint256 oldDiscountRateMantissa, uint256 newDiscountRateMantissa);\n\n /*** User Interface ***/\n\n function transfer(address dst, uint256 amount) external returns (bool);\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external returns (bool);\n\n function approve(address spender, uint256 amount) external returns (bool);\n\n function allowance(address owner, address spender) external view returns (uint256);\n\n function balanceOf(address owner) external view returns (uint256);\n\n function totalSupply() external view returns (uint256);\n\n function balanceOfUnderlying(address owner) external returns (uint256);\n\n function getAccountSnapshot(address account)\n external\n view\n returns (\n uint256,\n uint256,\n uint256,\n uint256\n );\n\n function borrowRatePerBlock() external view returns (uint256);\n\n function supplyRatePerBlock() external view returns (uint256);\n\n function totalBorrowsCurrent() external returns (uint256);\n\n function borrowBalanceCurrent(address account) external returns (uint256);\n\n function borrowBalanceStored(address account) external view returns (uint256);\n\n function exchangeRateCurrent() external returns (uint256);\n\n function exchangeRateStored() external view returns (uint256);\n\n function getCash() external view returns (uint256);\n\n function accrueInterest() external returns (uint256);\n\n function accrualBlockNumber() external returns (uint256);\n\n function seize(\n address liquidator,\n address borrower,\n uint256 seizeTokens\n ) external returns (uint256);\n\n /*** Admin Functions ***/\n\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint256);\n\n function _acceptAdmin() external returns (uint256);\n\n function _setComptroller(address newComptroller) external returns (uint256);\n\n function _setReserveFactor(uint256 newReserveFactorMantissa) external returns (uint256);\n\n function _reduceReserves(uint256 reduceAmount) external returns (uint256);\n\n function _setInterestRateModel(address newInterestRateModel) external returns (uint256);\n\n function getDiscountRate() external view returns (uint256);\n\n function _setDiscountRate(uint256 discountRateMantissa) external returns (uint256);\n}\n" }, "contracts/CToken/suErc20.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\nimport './Interfaces/IEIP20NonStandard.sol';\nimport './CErc20.sol';\n\n/**\n * @title Compound's suErc20 Contract\n * @notice CTokens which wrap an EIP-20 underlying\n * @author Compound\n */\ncontract suErc20 is CErc20 {\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 override returns (uint256) {\n ICToken token = ICToken(underlying);\n return token.balanceOf(address(this));\n }\n\n /**\n * @dev Similar to EIP20 transfer, except it handles a False result from `transferFrom` and reverts in that case.\n * This will revert due to insufficient balance or insufficient allowance.\n * This function returns the actual amount received,\n * which may be less than `amount` if there is a fee attached to the transfer.\n *\n * Note: This wrapper safely handles non-standard ERC-20 tokens that do not return a value.\n * See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n */\n function doTransferIn(address from, uint256 amount) internal override returns (uint256) {\n IEIP20NonStandard token = IEIP20NonStandard(underlying);\n token.burnFrom(from, amount);\n\n bool success;\n assembly {\n switch returndatasize()\n case 0 {\n // This is a non-standard ERC-20\n success := not(0) // set success to true\n }\n case 32 {\n // This is a compliant ERC-20\n returndatacopy(0, 0, 32)\n success := mload(0) // Set `success = returndata` of external call\n }\n default {\n // This is an excessively non-compliant ERC-20, revert.\n revert(0, 0)\n }\n }\n require(success, 'TOKEN_TRANSFER_IN_FAILED');\n\n // Calculate the amount that was *actually* transferred\n return amount;\n }\n\n /**\n * @dev Similar to EIP20 transfer, except it handles a False success from `transfer` and returns an explanatory\n * error code rather than reverting. If caller has not called checked protocol's balance, this may revert due to\n * insufficient cash held in this contract. If caller has checked protocol's balance prior to this call, and verified\n * it is >= amount, this should not revert in normal conditions.\n *\n * Note: This wrapper safely handles non-standard ERC-20 tokens that do not return a value.\n * See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n */\n function doTransferOut(address payable to, uint256 amount) internal override {\n IEIP20NonStandard token = IEIP20NonStandard(underlying);\n token.mint(to, amount);\n\n bool success;\n assembly {\n switch returndatasize()\n case 0 {\n // This is a non-standard ERC-20\n success := not(0) // set success to true\n }\n case 32 {\n // This is a compliant ERC-20\n returndatacopy(0, 0, 32)\n success := mload(0) // Set `success = returndata` of external call\n }\n default {\n // This is an excessively non-compliant ERC-20, revert.\n revert(0, 0)\n }\n }\n require(success, 'TOKEN_TRANSFER_OUT_FAILED');\n }\n\n function changeCtoken() public onlyAdmin {\n isCToken = !isCToken;\n }\n}\n" }, "contracts/CToken/Interfaces/IEIP20NonStandard.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\n/**\n * @title EIP20NonStandardInterface\n * @dev Version of ERC20 with no return values for `transfer` and `transferFrom`\n * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n */\ninterface IEIP20NonStandard {\n /**\n * @notice Get the total number of tokens in circulation\n * @return The supply of tokens\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @notice Gets the balance of the specified address\n * @param owner The address from which the balance will be retrieved\n * @return balance The balance\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n ///\n /// !!!!!!!!!!!!!!\n /// !!! NOTICE !!! `transfer` does not return a value, in violation of the ERC-20 specification\n /// !!!!!!!!!!!!!!\n ///\n\n /**\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n */\n function transfer(address dst, uint256 amount) external;\n\n ///\n /// !!!!!!!!!!!!!!\n /// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the ERC-20 specification\n /// !!!!!!!!!!!!!!\n ///\n\n /**\n * @notice Transfer `amount` tokens from `src` to `dst`\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n */\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) external;\n\n /**\n * @notice Approve `spender` to transfer up to `amount` from `src`\n * @dev This will overwrite the approval amount for `spender`\n * 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\n * @return success Whether or not the approval succeeded\n */\n function approve(address spender, uint256 amount) external returns (bool success);\n\n /**\n * @notice Get the current allowance from `owner` for `spender`\n * @param owner The address of the account which owns the tokens to be spent\n * @param spender The address of the account which may transfer tokens\n * @return remaining The number of tokens allowed to be spent\n */\n function allowance(address owner, address spender) external view returns (uint256 remaining);\n\n /**\n * @dev Creates `amount` new tokens for `to`.\n * See {ERC20-_mint}.\n * Requirements:\n * - the caller must have the `MINTER_ROLE`.\n */\n function mint(address to, uint256 amount) external;\n\n /**\n * @dev Destroys `amount` tokens from the caller.\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) external;\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n * See {ERC20-_burn} and {ERC20-allowance}.\n * Requirements:\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) external;\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n}\n" }, "contracts/OFT/OFTCore.sol": { "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport './lzApp/NonblockingLzApp.sol';\nimport './interfaces/IOFTCore.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\n\nabstract contract OFTCore is NonblockingLzApp, IOFTCore {\n using BytesLib for bytes;\n\n uint256 public constant NO_EXTRA_GAS = 0;\n // packet type\n uint16 public constant PT_SEND = 0;\n bool public useCustomAdapterParams;\n\n\n constructor(address _lzEndpoint) NonblockingLzApp(_lzEndpoint) {}\n\n function estimateSendFee(\n uint16 _dstChainId,\n bytes calldata _toAddress,\n uint256 _amount,\n bool _useZro,\n bytes calldata _adapterParams\n ) public view virtual override returns (uint256 nativeFee, uint256 zroFee) {\n // mock the payload for sendFrom()\n bytes memory payload = abi.encode(PT_SEND, _toAddress, _amount);\n return lzEndpoint.estimateFees(_dstChainId, address(this), payload, _useZro, _adapterParams);\n }\n\n function sendFrom(\n address _from,\n uint16 _dstChainId,\n bytes calldata _toAddress,\n uint256 _amount,\n address payable _refundAddress,\n address _zroPaymentAddress,\n bytes calldata _adapterParams\n ) public payable virtual override {\n _send(_from, _dstChainId, _toAddress, _amount, _refundAddress, _zroPaymentAddress, _adapterParams);\n }\n\n function setUseCustomAdapterParams(bool _useCustomAdapterParams) public virtual onlyAdmin {\n useCustomAdapterParams = _useCustomAdapterParams;\n emit SetUseCustomAdapterParams(_useCustomAdapterParams);\n }\n\n function _nonblockingLzReceive(\n uint16 _srcChainId,\n bytes memory _srcAddress,\n uint64 _nonce,\n bytes memory _payload\n ) internal virtual override {\n uint16 packetType;\n assembly {\n packetType := mload(add(_payload, 32))\n }\n\n if (packetType == PT_SEND) {\n _sendAck(_srcChainId, _srcAddress, _nonce, _payload);\n } else {\n revert('OFTCore: unknown packet type');\n }\n }\n\n function _send(\n address _from,\n uint16 _dstChainId,\n bytes memory _toAddress,\n uint256 _amount,\n address payable _refundAddress,\n address _zroPaymentAddress,\n bytes memory _adapterParams\n ) internal virtual {\n _checkAdapterParams(_dstChainId, PT_SEND, _adapterParams, NO_EXTRA_GAS);\n\n uint256 amount = _debitFrom(_from, _dstChainId, _toAddress, _amount);\n\n bytes memory lzPayload = abi.encode(PT_SEND, _toAddress, amount);\n _lzSend(_dstChainId, lzPayload, _refundAddress, _zroPaymentAddress, _adapterParams, msg.value);\n\n emit SendToChain(_dstChainId, _from, _toAddress, amount);\n }\n\n function _sendAck(uint16 _srcChainId, bytes memory, uint64, bytes memory _payload) internal virtual {\n (, bytes memory toAddressBytes, uint256 amount) = abi.decode(_payload, (uint16, bytes, uint256));\n\n address to = toAddressBytes.toAddress(0);\n\n amount = _creditTo(_srcChainId, to, amount);\n emit ReceiveFromChain(_srcChainId, to, amount);\n }\n\n function _checkAdapterParams(\n uint16 _dstChainId,\n uint16 _pkType,\n bytes memory _adapterParams,\n uint256 _extraGas\n ) internal virtual {\n if (useCustomAdapterParams) {\n _checkGasLimit(_dstChainId, _pkType, _adapterParams, _extraGas);\n } else {\n require(_adapterParams.length == 0, 'OFTCore: _adapterParams must be empty.');\n }\n }\n\n function _debitFrom(\n address _from,\n uint16 _dstChainId,\n bytes memory _toAddress,\n uint256 _amount\n ) internal virtual returns (uint256);\n\n function _creditTo(uint16 _srcChainId, address _toAddress, uint256 _amount) internal virtual returns (uint256);\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" }, "contracts/OFT/interfaces/IOFTCore.sol": { "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\n\n/**\n * @dev Interface of the IOFT core standard\n */\ninterface IOFTCore is IERC165 {\n /**\n * @dev estimate send token `_tokenId` to (`_dstChainId`, `_toAddress`)\n * _dstChainId - L0 defined chain id to send tokens too\n * _toAddress - dynamic bytes array which contains the address to whom you are sending tokens to on the dstChain\n * _amount - amount of the tokens to transfer\n * _useZro - indicates to use zro to pay L0 fees\n * _adapterParam - flexible bytes array to indicate messaging adapter services in L0\n */\n function estimateSendFee(\n uint16 _dstChainId,\n bytes calldata _toAddress,\n uint256 _amount,\n bool _useZro,\n bytes calldata _adapterParams\n ) external view returns (uint256 nativeFee, uint256 zroFee);\n\n /**\n * @dev send `_amount` amount of token to (`_dstChainId`, `_toAddress`) from `_from`\n * `_from` the owner of token\n * `_dstChainId` the destination chain identifier\n * `_toAddress` can be any size depending on the `dstChainId`.\n * `_amount` the quantity of tokens in wei\n * `_refundAddress` the address LayerZero refunds if too much message fee is sent\n * `_zroPaymentAddress` set to address(0x0) if not paying in ZRO (LayerZero Token)\n * `_adapterParams` is a flexible bytes array to indicate messaging adapter services\n */\n function sendFrom(\n address _from,\n uint16 _dstChainId,\n bytes calldata _toAddress,\n uint256 _amount,\n address payable _refundAddress,\n address _zroPaymentAddress,\n bytes calldata _adapterParams\n ) external payable;\n\n /**\n * @dev returns the circulating amount of tokens on current chain\n */\n function circulatingSupply() external view returns (uint256);\n\n /**\n * @dev returns the address of the ERC20 token\n */\n function token() external view returns (address);\n\n /**\n * @dev Emitted when `_amount` tokens are moved from the `_sender` to (`_dstChainId`, `_toAddress`)\n * `_nonce` is the outbound nonce\n */\n event SendToChain(uint16 indexed _dstChainId, address indexed _from, bytes _toAddress, uint256 _amount);\n\n /**\n * @dev Emitted when `_amount` tokens are received from `_srcChainId` into the `_toAddress` on the local chain.\n * `_nonce` is the inbound nonce.\n */\n event ReceiveFromChain(uint16 indexed _srcChainId, address indexed _to, uint256 _amount);\n\n event SetUseCustomAdapterParams(bool _useCustomAdapterParams);\n}\n" }, "contracts/OFT/lzApp/NonblockingLzApp.sol": { "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport './LzApp.sol';\nimport '../util/ExcessivelySafeCall.sol';\n\n/*\n * the default LayerZero messaging behaviour is blocking, i.e. any failed message will block the channel\n * this abstract class try-catch all fail messages and store locally for future retry. hence, non-blocking\n * NOTE: if the srcAddress is not configured properly, it will still block the message pathway from (srcChainId, srcAddress)\n */\nabstract contract NonblockingLzApp is LzApp {\n using ExcessivelySafeCall for address;\n\n constructor(address _endpoint) LzApp(_endpoint) {}\n\n mapping(uint16 => mapping(bytes => mapping(uint64 => bytes32))) public failedMessages;\n\n event MessageFailed(uint16 _srcChainId, bytes _srcAddress, uint64 _nonce, bytes _payload, bytes _reason);\n event RetryMessageSuccess(uint16 _srcChainId, bytes _srcAddress, uint64 _nonce, bytes32 _payloadHash);\n\n // overriding the virtual function in LzReceiver\n function _blockingLzReceive(\n uint16 _srcChainId,\n bytes memory _srcAddress,\n uint64 _nonce,\n bytes memory _payload\n ) internal virtual override {\n (bool success, bytes memory reason) = address(this).excessivelySafeCall(\n gasleft(),\n 150,\n abi.encodeWithSelector(this.nonblockingLzReceive.selector, _srcChainId, _srcAddress, _nonce, _payload)\n );\n // try-catch all errors/exceptions\n if (!success) {\n _storeFailedMessage(_srcChainId, _srcAddress, _nonce, _payload, reason);\n }\n }\n\n function _storeFailedMessage(\n uint16 _srcChainId,\n bytes memory _srcAddress,\n uint64 _nonce,\n bytes memory _payload,\n bytes memory _reason\n ) internal virtual {\n failedMessages[_srcChainId][_srcAddress][_nonce] = keccak256(_payload);\n emit MessageFailed(_srcChainId, _srcAddress, _nonce, _payload, _reason);\n }\n\n function nonblockingLzReceive(\n uint16 _srcChainId,\n bytes calldata _srcAddress,\n uint64 _nonce,\n bytes calldata _payload\n ) public virtual {\n // only internal transaction\n require(_msgSender() == address(this), 'NonblockingLzApp: caller must be LzApp');\n _nonblockingLzReceive(_srcChainId, _srcAddress, _nonce, _payload);\n }\n\n //@notice override this function\n function _nonblockingLzReceive(\n uint16 _srcChainId,\n bytes memory _srcAddress,\n uint64 _nonce,\n bytes memory _payload\n ) internal virtual;\n\n function retryMessage(\n uint16 _srcChainId,\n bytes calldata _srcAddress,\n uint64 _nonce,\n bytes calldata _payload\n ) public payable virtual {\n // assert there is message to retry\n bytes32 payloadHash = failedMessages[_srcChainId][_srcAddress][_nonce];\n require(payloadHash != bytes32(0), 'NonblockingLzApp: no stored message');\n require(keccak256(_payload) == payloadHash, 'NonblockingLzApp: invalid payload');\n // clear the stored message\n failedMessages[_srcChainId][_srcAddress][_nonce] = bytes32(0);\n // execute the message. revert if it fails again\n _nonblockingLzReceive(_srcChainId, _srcAddress, _nonce, _payload);\n emit RetryMessageSuccess(_srcChainId, _srcAddress, _nonce, payloadHash);\n }\n}\n" }, "contracts/OFT/util/ExcessivelySafeCall.sol": { "content": "// SPDX-License-Identifier: MIT OR Apache-2.0\npragma solidity >=0.7.6;\n\nlibrary ExcessivelySafeCall {\n uint256 constant LOW_28_MASK = 0x00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff;\n\n /// @notice Use when you _really_ really _really_ don't trust the called\n /// contract. This prevents the called contract from causing reversion of\n /// the caller in as many ways as we can.\n /// @dev The main difference between this and a solidity low-level call is\n /// that we limit the number of bytes that the callee can cause to be\n /// copied to caller memory. This prevents stupid things like malicious\n /// contracts returning 10,000,000 bytes causing a local OOG when copying\n /// to memory.\n /// @param _target The address to call\n /// @param _gas The amount of gas to forward to the remote contract\n /// @param _maxCopy The maximum number of bytes of returndata to copy\n /// to memory.\n /// @param _calldata The data to send to the remote contract\n /// @return success and returndata, as `.call()`. Returndata is capped to\n /// `_maxCopy` bytes.\n function excessivelySafeCall(\n address _target,\n uint256 _gas,\n uint16 _maxCopy,\n bytes memory _calldata\n ) internal returns (bool, bytes memory) {\n // set up for assembly call\n uint256 _toCopy;\n bool _success;\n bytes memory _returnData = new bytes(_maxCopy);\n // dispatch message to recipient\n // by assembly calling \"handle\" function\n // we call via assembly to avoid memcopying a very large returndata\n // returned by a malicious contract\n assembly {\n _success := call(\n _gas, // gas\n _target, // recipient\n 0, // ether value\n add(_calldata, 0x20), // inloc\n mload(_calldata), // inlen\n 0, // outloc\n 0 // outlen\n )\n // limit our copy to 256 bytes\n _toCopy := returndatasize()\n if gt(_toCopy, _maxCopy) {\n _toCopy := _maxCopy\n }\n // Store the length of the copied bytes\n mstore(_returnData, _toCopy)\n // copy the bytes from returndata[0:_toCopy]\n returndatacopy(add(_returnData, 0x20), 0, _toCopy)\n }\n return (_success, _returnData);\n }\n\n /// @notice Use when you _really_ really _really_ don't trust the called\n /// contract. This prevents the called contract from causing reversion of\n /// the caller in as many ways as we can.\n /// @dev The main difference between this and a solidity low-level call is\n /// that we limit the number of bytes that the callee can cause to be\n /// copied to caller memory. This prevents stupid things like malicious\n /// contracts returning 10,000,000 bytes causing a local OOG when copying\n /// to memory.\n /// @param _target The address to call\n /// @param _gas The amount of gas to forward to the remote contract\n /// @param _maxCopy The maximum number of bytes of returndata to copy\n /// to memory.\n /// @param _calldata The data to send to the remote contract\n /// @return success and returndata, as `.call()`. Returndata is capped to\n /// `_maxCopy` bytes.\n function excessivelySafeStaticCall(\n address _target,\n uint256 _gas,\n uint16 _maxCopy,\n bytes memory _calldata\n ) internal view returns (bool, bytes memory) {\n // set up for assembly call\n uint256 _toCopy;\n bool _success;\n bytes memory _returnData = new bytes(_maxCopy);\n // dispatch message to recipient\n // by assembly calling \"handle\" function\n // we call via assembly to avoid memcopying a very large returndata\n // returned by a malicious contract\n assembly {\n _success := staticcall(\n _gas, // gas\n _target, // recipient\n add(_calldata, 0x20), // inloc\n mload(_calldata), // inlen\n 0, // outloc\n 0 // outlen\n )\n // limit our copy to 256 bytes\n _toCopy := returndatasize()\n if gt(_toCopy, _maxCopy) {\n _toCopy := _maxCopy\n }\n // Store the length of the copied bytes\n mstore(_returnData, _toCopy)\n // copy the bytes from returndata[0:_toCopy]\n returndatacopy(add(_returnData, 0x20), 0, _toCopy)\n }\n return (_success, _returnData);\n }\n\n /**\n * @notice Swaps function selectors in encoded contract calls\n * @dev Allows reuse of encoded calldata for functions with identical\n * argument types but different names. It simply swaps out the first 4 bytes\n * for the new selector. This function modifies memory in place, and should\n * only be used with caution.\n * @param _newSelector The new 4-byte selector\n * @param _buf The encoded contract args\n */\n function swapSelector(bytes4 _newSelector, bytes memory _buf) internal pure {\n require(_buf.length >= 4);\n uint256 _mask = LOW_28_MASK;\n assembly {\n // load the first word of\n let _word := mload(add(_buf, 0x20))\n // mask out the top 4 bytes\n // /x\n _word := and(_word, _mask)\n _word := or(_newSelector, _word)\n mstore(add(_buf, 0x20), _word)\n }\n }\n}\n" }, "contracts/OFT/lzApp/LzApp.sol": { "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport '../OFTAccessControl.sol';\nimport '../interfaces/ILayerZeroReceiver.sol';\nimport '../interfaces/ILayerZeroUserApplicationConfig.sol';\nimport '../interfaces/ILayerZeroEndpoint.sol';\nimport '../util/BytesLib.sol';\n\n/*\n * a generic LzReceiver implementation\n */\nabstract contract LzApp is OFTAccessControl, ILayerZeroReceiver, ILayerZeroUserApplicationConfig {\n using BytesLib for bytes;\n\n // ua can not send payload larger than this by default, but it can be changed by the ua owner\n uint256 public constant DEFAULT_PAYLOAD_SIZE_LIMIT = 10000;\n\n ILayerZeroEndpoint public immutable lzEndpoint;\n mapping(uint16 => bytes) public trustedRemoteLookup;\n mapping(uint16 => mapping(uint16 => uint256)) public minDstGasLookup;\n mapping(uint16 => uint256) public payloadSizeLimitLookup;\n address public precrime;\n\n event SetPrecrime(address precrime);\n event SetTrustedRemote(uint16 _remoteChainId, bytes _path);\n event SetTrustedRemoteAddress(uint16 _remoteChainId, bytes _remoteAddress);\n event SetMinDstGas(uint16 _dstChainId, uint16 _type, uint256 _minDstGas);\n\n constructor(address _endpoint) {\n lzEndpoint = ILayerZeroEndpoint(_endpoint);\n }\n\n function lzReceive(\n uint16 _srcChainId,\n bytes calldata _srcAddress,\n uint64 _nonce,\n bytes calldata _payload\n ) public virtual override {\n // lzReceive must be called by the endpoint for security\n require(_msgSender() == address(lzEndpoint), 'LzApp: invalid endpoint caller');\n\n bytes memory trustedRemote = trustedRemoteLookup[_srcChainId];\n // if will still block the message pathway from (srcChainId, srcAddress). should not receive message from untrusted remote.\n require(\n _srcAddress.length == trustedRemote.length &&\n trustedRemote.length > 0 &&\n keccak256(_srcAddress) == keccak256(trustedRemote),\n 'LzApp: invalid source sending contract'\n );\n\n _blockingLzReceive(_srcChainId, _srcAddress, _nonce, _payload);\n }\n\n // abstract function - the default behaviour of LayerZero is blocking. See: NonblockingLzApp if you dont need to enforce ordered messaging\n function _blockingLzReceive(\n uint16 _srcChainId,\n bytes memory _srcAddress,\n uint64 _nonce,\n bytes memory _payload\n ) internal virtual;\n\n function _lzSend(\n uint16 _dstChainId,\n bytes memory _payload,\n address payable _refundAddress,\n address _zroPaymentAddress,\n bytes memory _adapterParams,\n uint256 _nativeFee\n ) internal virtual {\n bytes memory trustedRemote = trustedRemoteLookup[_dstChainId];\n require(trustedRemote.length != 0, 'LzApp: destination chain is not a trusted source');\n _checkPayloadSize(_dstChainId, _payload.length);\n lzEndpoint.send{value: _nativeFee}(\n _dstChainId,\n trustedRemote,\n _payload,\n _refundAddress,\n _zroPaymentAddress,\n _adapterParams\n );\n }\n\n function _checkGasLimit(\n uint16 _dstChainId,\n uint16 _type,\n bytes memory _adapterParams,\n uint256 _extraGas\n ) internal view virtual {\n uint256 providedGasLimit = _getGasLimit(_adapterParams);\n uint256 minGasLimit = minDstGasLookup[_dstChainId][_type] + _extraGas;\n require(minGasLimit > 0, 'LzApp: minGasLimit not set');\n require(providedGasLimit >= minGasLimit, 'LzApp: gas limit is too low');\n }\n\n function _getGasLimit(bytes memory _adapterParams) internal pure virtual returns (uint256 gasLimit) {\n require(_adapterParams.length >= 34, 'LzApp: invalid adapterParams');\n assembly {\n gasLimit := mload(add(_adapterParams, 34))\n }\n }\n\n function _checkPayloadSize(uint16 _dstChainId, uint256 _payloadSize) internal view virtual {\n uint256 payloadSizeLimit = payloadSizeLimitLookup[_dstChainId];\n if (payloadSizeLimit == 0) {\n // use default if not set\n payloadSizeLimit = DEFAULT_PAYLOAD_SIZE_LIMIT;\n }\n require(_payloadSize <= payloadSizeLimit, 'LzApp: payload size is too large');\n }\n\n //---------------------------UserApplication config----------------------------------------\n function getConfig(\n uint16 _version,\n uint16 _chainId,\n address,\n uint256 _configType\n ) external view returns (bytes memory) {\n return lzEndpoint.getConfig(_version, _chainId, address(this), _configType);\n }\n\n // generic config for LayerZero user Application\n function setConfig(\n uint16 _version,\n uint16 _chainId,\n uint256 _configType,\n bytes calldata _config\n ) external override onlyAdmin {\n lzEndpoint.setConfig(_version, _chainId, _configType, _config);\n }\n\n function setSendVersion(uint16 _version) external override onlyAdmin {\n lzEndpoint.setSendVersion(_version);\n }\n\n function setReceiveVersion(uint16 _version) external override onlyAdmin {\n lzEndpoint.setReceiveVersion(_version);\n }\n\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external override onlyAdmin {\n lzEndpoint.forceResumeReceive(_srcChainId, _srcAddress);\n }\n\n // _path = abi.encodePacked(remoteAddress, localAddress)\n // this function set the trusted path for the cross-chain communication\n function setTrustedRemote(uint16 _srcChainId, bytes calldata _path) external onlyAdmin {\n trustedRemoteLookup[_srcChainId] = _path;\n emit SetTrustedRemote(_srcChainId, _path);\n }\n\n function setTrustedRemoteAddress(uint16 _remoteChainId, bytes calldata _remoteAddress) external onlyAdmin {\n trustedRemoteLookup[_remoteChainId] = abi.encodePacked(_remoteAddress, address(this));\n emit SetTrustedRemoteAddress(_remoteChainId, _remoteAddress);\n }\n\n function getTrustedRemoteAddress(uint16 _remoteChainId) external view returns (bytes memory) {\n bytes memory path = trustedRemoteLookup[_remoteChainId];\n require(path.length != 0, 'LzApp: no trusted path record');\n return path.slice(0, path.length - 20); // the last 20 bytes should be address(this)\n }\n\n function setPrecrime(address _precrime) external onlyAdmin {\n precrime = _precrime;\n emit SetPrecrime(_precrime);\n }\n\n function setMinDstGas(uint16 _dstChainId, uint16 _packetType, uint256 _minGas) external onlyAdmin {\n require(_minGas > 0, 'LzApp: invalid minGas');\n minDstGasLookup[_dstChainId][_packetType] = _minGas;\n emit SetMinDstGas(_dstChainId, _packetType, _minGas);\n }\n\n // if the size is 0, it means default size limit\n function setPayloadSizeLimit(uint16 _dstChainId, uint256 _size) external onlyAdmin {\n payloadSizeLimitLookup[_dstChainId] = _size;\n }\n\n //--------------------------- VIEW FUNCTION ----------------------------------------\n function isTrustedRemote(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool) {\n bytes memory trustedSource = trustedRemoteLookup[_srcChainId];\n return keccak256(trustedSource) == keccak256(_srcAddress);\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" }, "contracts/OFT/util/BytesLib.sol": { "content": "// SPDX-License-Identifier: Unlicense\n/*\n * @title Solidity Bytes Arrays Utils\n * @author Gonçalo Sá \n *\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\n * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\n */\npragma solidity >=0.8.0 <0.9.0;\n\nlibrary BytesLib {\n function concat(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bytes memory) {\n bytes memory tempBytes;\n\n assembly {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // Store the length of the first bytes array at the beginning of\n // the memory for tempBytes.\n let length := mload(_preBytes)\n mstore(tempBytes, length)\n\n // Maintain a memory counter for the current write location in the\n // temp bytes array by adding the 32 bytes for the array length to\n // the starting location.\n let mc := add(tempBytes, 0x20)\n // Stop copying when the memory counter reaches the length of the\n // first bytes array.\n let end := add(mc, length)\n\n for {\n // Initialize a copy counter to the start of the _preBytes data,\n // 32 bytes into its memory.\n let cc := add(_preBytes, 0x20)\n } lt(mc, end) {\n // Increase both counters by 32 bytes each iteration.\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n // Write the _preBytes data into the tempBytes memory 32 bytes\n // at a time.\n mstore(mc, mload(cc))\n }\n\n // Add the length of _postBytes to the current length of tempBytes\n // and store it as the new length in the first 32 bytes of the\n // tempBytes memory.\n length := mload(_postBytes)\n mstore(tempBytes, add(length, mload(tempBytes)))\n\n // Move the memory counter back from a multiple of 0x20 to the\n // actual end of the _preBytes data.\n mc := end\n // Stop copying when the memory counter reaches the new combined\n // length of the arrays.\n end := add(mc, length)\n\n for {\n let cc := add(_postBytes, 0x20)\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n // Update the free-memory pointer by padding our last write location\n // to 32 bytes: add 31 bytes to the end of tempBytes to move to the\n // next 32 byte block, then round down to the nearest multiple of\n // 32. If the sum of the length of the two arrays is zero then add\n // one before rounding down to leave a blank 32 bytes (the length block with 0).\n mstore(\n 0x40,\n and(\n add(add(end, iszero(add(length, mload(_preBytes)))), 31),\n not(31) // Round down to the nearest 32 bytes.\n )\n )\n }\n\n return tempBytes;\n }\n\n function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal {\n assembly {\n // Read the first 32 bytes of _preBytes storage, which is the length\n // of the array. (We don't need to use the offset into the slot\n // because arrays use the entire slot.)\n let fslot := sload(_preBytes.slot)\n // Arrays of 31 bytes or less have an even value in their slot,\n // while longer arrays have an odd value. The actual length is\n // the slot divided by two for odd values, and the lowest order\n // byte divided by two for even values.\n // If the slot is even, bitwise and the slot with 255 and divide by\n // two to get the length. If the slot is odd, bitwise and the slot\n // with -1 and divide by two.\n let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)\n let mlength := mload(_postBytes)\n let newlength := add(slength, mlength)\n // slength can contain both the length and contents of the array\n // if length < 32 bytes so let's prepare for that\n // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage\n switch add(lt(slength, 32), lt(newlength, 32))\n case 2 {\n // Since the new array still fits in the slot, we just need to\n // update the contents of the slot.\n // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length\n sstore(\n _preBytes.slot,\n // all the modifications to the slot are inside this\n // next block\n add(\n // we can just add to the slot contents because the\n // bytes we want to change are the LSBs\n fslot,\n add(\n mul(\n div(\n // load the bytes from memory\n mload(add(_postBytes, 0x20)),\n // zero all bytes to the right\n exp(0x100, sub(32, mlength))\n ),\n // and now shift left the number of bytes to\n // leave space for the length in the slot\n exp(0x100, sub(32, newlength))\n ),\n // increase length by the double of the memory\n // bytes length\n mul(mlength, 2)\n )\n )\n )\n }\n case 1 {\n // The stored value fits in the slot, but the combined value\n // will exceed it.\n // get the keccak hash to get the contents of the array\n mstore(0x0, _preBytes.slot)\n let sc := add(keccak256(0x0, 0x20), div(slength, 32))\n\n // save new length\n sstore(_preBytes.slot, add(mul(newlength, 2), 1))\n\n // The contents of the _postBytes array start 32 bytes into\n // the structure. Our first read should obtain the `submod`\n // bytes that can fit into the unused space in the last word\n // of the stored array. To get this, we read 32 bytes starting\n // from `submod`, so the data we read overlaps with the array\n // contents by `submod` bytes. Masking the lowest-order\n // `submod` bytes allows us to add that value directly to the\n // stored value.\n\n let submod := sub(32, slength)\n let mc := add(_postBytes, submod)\n let end := add(_postBytes, mlength)\n let mask := sub(exp(0x100, submod), 1)\n\n sstore(\n sc,\n add(and(fslot, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00), and(mload(mc), mask))\n )\n\n for {\n mc := add(mc, 0x20)\n sc := add(sc, 1)\n } lt(mc, end) {\n sc := add(sc, 1)\n mc := add(mc, 0x20)\n } {\n sstore(sc, mload(mc))\n }\n\n mask := exp(0x100, sub(mc, end))\n\n sstore(sc, mul(div(mload(mc), mask), mask))\n }\n default {\n // get the keccak hash to get the contents of the array\n mstore(0x0, _preBytes.slot)\n // Start copying to the last used word of the stored array.\n let sc := add(keccak256(0x0, 0x20), div(slength, 32))\n\n // save new length\n sstore(_preBytes.slot, add(mul(newlength, 2), 1))\n\n // Copy over the first `submod` bytes of the new data as in\n // case 1 above.\n let slengthmod := mod(slength, 32)\n let mlengthmod := mod(mlength, 32)\n let submod := sub(32, slengthmod)\n let mc := add(_postBytes, submod)\n let end := add(_postBytes, mlength)\n let mask := sub(exp(0x100, submod), 1)\n\n sstore(sc, add(sload(sc), and(mload(mc), mask)))\n\n for {\n sc := add(sc, 1)\n mc := add(mc, 0x20)\n } lt(mc, end) {\n sc := add(sc, 1)\n mc := add(mc, 0x20)\n } {\n sstore(sc, mload(mc))\n }\n\n mask := exp(0x100, sub(mc, end))\n\n sstore(sc, mul(div(mload(mc), mask), mask))\n }\n }\n }\n\n function slice(\n bytes memory _bytes,\n uint256 _start,\n uint256 _length\n ) internal pure returns (bytes memory) {\n require(_length + 31 >= _length, 'slice_overflow');\n require(_bytes.length >= _start + _length, 'slice_outOfBounds');\n\n bytes memory tempBytes;\n\n assembly {\n switch iszero(_length)\n case 0 {\n // Get a location of some free memory and store it in tempBytes as\n // Solidity does for memory variables.\n tempBytes := mload(0x40)\n\n // The first word of the slice result is potentially a partial\n // word read from the original array. To read it, we calculate\n // the length of that partial word and start copying that many\n // bytes into the array. The first word we copy will start with\n // data we don't care about, but the last `lengthmod` bytes will\n // land at the beginning of the contents of the new array. When\n // we're done copying, we overwrite the full first word with\n // the actual length of the slice.\n let lengthmod := and(_length, 31)\n\n // The multiplication in the next line is necessary\n // because when slicing multiples of 32 bytes (lengthmod == 0)\n // the following copy loop was copying the origin's length\n // and then ending prematurely not copying everything it should.\n let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\n let end := add(mc, _length)\n\n for {\n // The multiplication in the next line has the same exact purpose\n // as the one above.\n let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\n } lt(mc, end) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n mstore(mc, mload(cc))\n }\n\n mstore(tempBytes, _length)\n\n //update free-memory pointer\n //allocating the array padded to 32 bytes like the compiler does now\n mstore(0x40, and(add(mc, 31), not(31)))\n }\n //if we want a zero-length slice let's just return a zero-length array\n default {\n tempBytes := mload(0x40)\n //zero out the 32 bytes slice we are about to return\n //we need to do it because Solidity does not garbage collect\n mstore(tempBytes, 0)\n\n mstore(0x40, add(tempBytes, 0x20))\n }\n }\n\n return tempBytes;\n }\n\n function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\n require(_bytes.length >= _start + 20, 'toAddress_outOfBounds');\n address tempAddress;\n\n assembly {\n tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\n }\n\n return tempAddress;\n }\n\n function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {\n require(_bytes.length >= _start + 1, 'toUint8_outOfBounds');\n uint8 tempUint;\n\n assembly {\n tempUint := mload(add(add(_bytes, 0x1), _start))\n }\n\n return tempUint;\n }\n\n function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) {\n require(_bytes.length >= _start + 2, 'toUint16_outOfBounds');\n uint16 tempUint;\n\n assembly {\n tempUint := mload(add(add(_bytes, 0x2), _start))\n }\n\n return tempUint;\n }\n\n function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) {\n require(_bytes.length >= _start + 4, 'toUint32_outOfBounds');\n uint32 tempUint;\n\n assembly {\n tempUint := mload(add(add(_bytes, 0x4), _start))\n }\n\n return tempUint;\n }\n\n function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) {\n require(_bytes.length >= _start + 8, 'toUint64_outOfBounds');\n uint64 tempUint;\n\n assembly {\n tempUint := mload(add(add(_bytes, 0x8), _start))\n }\n\n return tempUint;\n }\n\n function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) {\n require(_bytes.length >= _start + 12, 'toUint96_outOfBounds');\n uint96 tempUint;\n\n assembly {\n tempUint := mload(add(add(_bytes, 0xc), _start))\n }\n\n return tempUint;\n }\n\n function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) {\n require(_bytes.length >= _start + 16, 'toUint128_outOfBounds');\n uint128 tempUint;\n\n assembly {\n tempUint := mload(add(add(_bytes, 0x10), _start))\n }\n\n return tempUint;\n }\n\n function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {\n require(_bytes.length >= _start + 32, 'toUint256_outOfBounds');\n uint256 tempUint;\n\n assembly {\n tempUint := mload(add(add(_bytes, 0x20), _start))\n }\n\n return tempUint;\n }\n\n function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) {\n require(_bytes.length >= _start + 32, 'toBytes32_outOfBounds');\n bytes32 tempBytes32;\n\n assembly {\n tempBytes32 := mload(add(add(_bytes, 0x20), _start))\n }\n\n return tempBytes32;\n }\n\n function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) {\n bool success = true;\n\n assembly {\n let length := mload(_preBytes)\n\n // if lengths don't match the arrays are not equal\n switch eq(length, mload(_postBytes))\n case 1 {\n // cb is a circuit breaker in the for loop since there's\n // no said feature for inline assembly loops\n // cb = 1 - don't breaker\n // cb = 0 - break\n let cb := 1\n\n let mc := add(_preBytes, 0x20)\n let end := add(mc, length)\n\n for {\n let cc := add(_postBytes, 0x20)\n // the next line is the loop condition:\n // while(uint256(mc < end) + cb == 2)\n } eq(add(lt(mc, end), cb), 2) {\n mc := add(mc, 0x20)\n cc := add(cc, 0x20)\n } {\n // if any of these checks fails then arrays are not equal\n if iszero(eq(mload(mc), mload(cc))) {\n // unsuccess:\n success := 0\n cb := 0\n }\n }\n }\n default {\n // unsuccess:\n success := 0\n }\n }\n\n return success;\n }\n\n function equalStorage(bytes storage _preBytes, bytes memory _postBytes) internal view returns (bool) {\n bool success = true;\n\n assembly {\n // we know _preBytes_offset is 0\n let fslot := sload(_preBytes.slot)\n // Decode the length of the stored array like in concatStorage().\n let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)\n let mlength := mload(_postBytes)\n\n // if lengths don't match the arrays are not equal\n switch eq(slength, mlength)\n case 1 {\n // slength can contain both the length and contents of the array\n // if length < 32 bytes so let's prepare for that\n // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage\n if iszero(iszero(slength)) {\n switch lt(slength, 32)\n case 1 {\n // blank the last byte which is the length\n fslot := mul(div(fslot, 0x100), 0x100)\n\n if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) {\n // unsuccess:\n success := 0\n }\n }\n default {\n // cb is a circuit breaker in the for loop since there's\n // no said feature for inline assembly loops\n // cb = 1 - don't breaker\n // cb = 0 - break\n let cb := 1\n\n // get the keccak hash to get the contents of the array\n mstore(0x0, _preBytes.slot)\n let sc := keccak256(0x0, 0x20)\n\n let mc := add(_postBytes, 0x20)\n let end := add(mc, mlength)\n\n // the next line is the loop condition:\n // while(uint256(mc < end) + cb == 2)\n for {\n\n } eq(add(lt(mc, end), cb), 2) {\n sc := add(sc, 1)\n mc := add(mc, 0x20)\n } {\n if iszero(eq(sload(sc), mload(mc))) {\n // unsuccess:\n success := 0\n cb := 0\n }\n }\n }\n }\n }\n default {\n // unsuccess:\n success := 0\n }\n }\n\n return success;\n }\n}\n" }, "contracts/OFT/interfaces/ILayerZeroEndpoint.sol": { "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\n\nimport './ILayerZeroUserApplicationConfig.sol';\n\ninterface ILayerZeroEndpoint is ILayerZeroUserApplicationConfig {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(\n uint16 _dstChainId,\n bytes calldata _destination,\n bytes calldata _payload,\n address payable _refundAddress,\n address _zroPaymentAddress,\n bytes calldata _adapterParams\n ) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(\n uint16 _srcChainId,\n bytes calldata _srcAddress,\n address _dstAddress,\n uint64 _nonce,\n uint256 _gasLimit,\n bytes calldata _payload\n ) external;\n\n // @notice get the inboundNonce of a lzApp from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(\n uint16 _dstChainId,\n address _userApplication,\n bytes calldata _payload,\n bool _payInZRO,\n bytes calldata _adapterParam\n ) external view returns (uint256 nativeFee, uint256 zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(\n uint16 _srcChainId,\n bytes calldata _srcAddress,\n bytes calldata _payload\n ) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(\n uint16 _version,\n uint16 _chainId,\n address _userApplication,\n uint256 _configType\n ) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" }, "contracts/OFT/interfaces/ILayerZeroUserApplicationConfig.sol": { "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroUserApplicationConfig {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(\n uint16 _version,\n uint16 _chainId,\n uint256 _configType,\n bytes calldata _config\n ) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" }, "contracts/OFT/interfaces/ILayerZeroReceiver.sol": { "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(\n uint16 _srcChainId,\n bytes calldata _srcAddress,\n uint64 _nonce,\n bytes calldata _payload\n ) external;\n}\n" }, "contracts/OFT/OFTAccessControl.sol": { "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\nimport '@openzeppelin/contracts/access/AccessControlEnumerable.sol';\n\ncontract OFTAccessControl is AccessControlEnumerable {\n bytes32 public constant MINTER_ROLE = keccak256('MINTER_ROLE');\n bytes32 public constant PAUSER_ROLE = keccak256('PAUSER_ROLE');\n\n constructor() {\n _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());\n\n _setupRole(MINTER_ROLE, _msgSender());\n _setupRole(PAUSER_ROLE, _msgSender());\n }\n\n modifier onlyAdmin() {\n _checkRole(DEFAULT_ADMIN_ROLE);\n _;\n }\n}\n" }, "@openzeppelin/contracts/access/AccessControlEnumerable.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControlEnumerable.sol\";\nimport \"./AccessControl.sol\";\nimport \"../utils/structs/EnumerableSet.sol\";\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers;\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) {\n return _roleMembers[role].at(index);\n }\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) {\n return _roleMembers[role].length();\n }\n\n /**\n * @dev Overload {_grantRole} to track enumerable memberships\n */\n function _grantRole(bytes32 role, address account) internal virtual override {\n super._grantRole(role, account);\n _roleMembers[role].add(account);\n }\n\n /**\n * @dev Overload {_revokeRole} to track enumerable memberships\n */\n function _revokeRole(bytes32 role, address account) internal virtual override {\n super._revokeRole(role, account);\n _roleMembers[role].remove(account);\n }\n}\n" }, "@openzeppelin/contracts/utils/structs/EnumerableSet.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position of the value in the `values` array, plus 1 because index 0\n // means a value is not in the set.\n mapping(bytes32 => uint256) _indexes;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._indexes[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We read and store the value's index to prevent multiple reads from the same storage slot\n uint256 valueIndex = set._indexes[value];\n\n if (valueIndex != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 toDeleteIndex = valueIndex - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (lastIndex != toDeleteIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the last value to the index where the value to delete is\n set._values[toDeleteIndex] = lastValue;\n // Update the index for the moved value\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the index for the deleted slot\n delete set._indexes[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._indexes[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n" }, "@openzeppelin/contracts/access/AccessControl.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.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 * ```\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 * ```\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.\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/IAccessControlEnumerable.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n /**\n * @dev Returns one of the accounts that have `role`. `index` must be a\n * value between 0 and {getRoleMemberCount}, non-inclusive.\n *\n * Role bearers are not sorted in any particular way, and their ordering may\n * change at any point.\n *\n * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n * you perform all queries on the same block. See the following\n * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n * for more information.\n */\n function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n /**\n * @dev Returns the number of accounts that have `role`. Can be used\n * together with {getRoleMember} to enumerate all bearers of a role.\n */\n function getRoleMemberCount(bytes32 role) external view returns (uint256);\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/utils/Strings.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.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 `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" }, "@openzeppelin/contracts/utils/Context.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" }, "@openzeppelin/contracts/utils/math/Math.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.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(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) 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 return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1);\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(\n uint256 x,\n uint256 y,\n uint256 denominator,\n Rounding rounding\n ) 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 10, 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 * 8) < value ? 1 : 0);\n }\n }\n}\n" }, "contracts/Oracle/PriceOracle.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\nabstract contract PriceOracle {\n /// @notice Indicator that this is a PriceOracle contract (for inspection)\n bool public constant isPriceOracle = true;\n\n /**\n * @notice Get the underlying price of a cToken asset\n * @param cToken The cToken to get the underlying price of\n * @return The underlying asset price mantissa (scaled by 1e18).\n * Zero means the price is unavailable.\n */\n function getUnderlyingPrice(address cToken) external view virtual returns (uint256);\n}\n" }, "contracts/Oracle/FeedPriceOracle.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\nimport './PriceOracle.sol';\nimport './Interfaces/IStdReference.sol';\nimport './Interfaces/IWitnetFeed.sol';\nimport './Interfaces/IChainlinkFeed.sol';\n\ncontract FeedPriceOracle is PriceOracle {\n struct FeedData {\n uint8 source; // 1 - chainlink feed, 2 - witnet router, 3 - Band\n address addr; // feed address\n uint8 tokenDecimals; // token decimals\n uint8 feedDecimals; // feed decimals (only used in witnet)\n string name;\n }\n\n address public owner;\n mapping(address => FeedData) public feeds; // cToken -> feed data\n mapping(address => uint256) public fixedPrices; // cToken -> price\n uint8 constant DECIMALS = 36;\n\n event SetFeed(\n address indexed cToken_,\n uint8 source,\n address addr,\n uint8 tokenDecimals,\n uint8 feedDecimals,\n string name\n );\n\n modifier onlyOwner() {\n require(msg.sender == owner, 'ONLY OWNER');\n _;\n }\n\n constructor() {\n owner = msg.sender;\n }\n\n function changeOwner(address owner_) public onlyOwner {\n require(owner_ != address(0), 'Address is Zero!');\n owner = owner_;\n }\n\n // TODO: name this setChainlinkFeed\n function setChainlinkFeed(\n address cToken_,\n address feed_,\n uint8 tokenDecimals_\n ) public onlyOwner {\n _setFeed(cToken_, uint8(1), feed_, tokenDecimals_, 8, '');\n }\n\n function setWitnetFeed(\n address cToken_,\n address feed_,\n uint8 tokenDecimals_,\n uint8 feedDecimals_\n ) public onlyOwner {\n _setFeed(cToken_, uint8(2), feed_, tokenDecimals_, feedDecimals_, '');\n }\n\n function setBandFeed(\n address cToken_,\n address feed_,\n uint8 tokenDecimals_,\n uint8 feedDecimals_,\n string memory name\n ) public onlyOwner {\n _setFeed(cToken_, uint8(3), feed_, tokenDecimals_, feedDecimals_, name);\n }\n\n function setFixedPrice(address cToken_, uint256 price) public onlyOwner {\n fixedPrices[cToken_] = price;\n }\n\n function _setFeed(\n address cToken_,\n uint8 source,\n address addr,\n uint8 tokenDecimals,\n uint8 feedDecimals,\n string memory name\n ) private {\n require(addr != address(0), 'Address is Zero!');\n if (feeds[cToken_].source != 0) {\n delete fixedPrices[cToken_];\n }\n FeedData memory feedData = FeedData({\n source: source,\n addr: addr,\n tokenDecimals: tokenDecimals,\n feedDecimals: feedDecimals,\n name: name\n });\n feeds[cToken_] = feedData;\n emit SetFeed(cToken_, source, addr, tokenDecimals, feedDecimals, name);\n }\n\n function removeFeed(address cToken_) public onlyOwner {\n delete feeds[cToken_];\n }\n\n function getFeed(address cToken_) public view returns (FeedData memory) {\n return feeds[cToken_];\n }\n\n function removeFixedPrice(address cToken_) public onlyOwner {\n delete fixedPrices[cToken_];\n }\n\n function getFixedPrice(address cToken_) public view returns (uint256) {\n return fixedPrices[cToken_];\n }\n\n function getUnderlyingPrice(address cToken_) public view override returns (uint256) {\n FeedData memory feed = feeds[cToken_]; // gas savings\n if (feed.addr != address(0)) {\n if (feed.source == uint8(1)) {\n uint256 decimals = uint256(DECIMALS - feed.tokenDecimals - IChainlinkFeed(feed.addr).decimals());\n require(decimals <= DECIMALS, 'DECIMAL UNDERFLOW');\n return IChainlinkFeed(feed.addr).latestAnswer() * (10**decimals);\n }\n if (feed.source == uint8(2)) {\n uint256 decimals = uint256(DECIMALS - feed.tokenDecimals - feed.feedDecimals);\n require(decimals <= DECIMALS, 'DECIMAL UNDERFLOW');\n uint256 _temp = uint256(IWitnetFeed(feed.addr).lastPrice());\n return _temp * (10**decimals);\n }\n if (feed.source == uint8(3)) {\n uint256 decimals = uint256(DECIMALS - feed.tokenDecimals - feed.feedDecimals);\n require(decimals <= DECIMALS, 'DECIMAL UNDERFLOW');\n IStdReference.ReferenceData memory refData = IStdReference(feed.addr).getReferenceData(feed.name, 'USD');\n return refData.rate * (10**decimals);\n }\n }\n return fixedPrices[cToken_];\n }\n\n function getUnderlyingPrices(address[] memory cTokens) public view returns (uint256[] memory) {\n uint256 length = cTokens.length;\n uint256[] memory results = new uint256[](length);\n for (uint256 i; i < length; ++i) {\n results[i] = getUnderlyingPrice(cTokens[i]);\n }\n return results;\n }\n}\n" }, "contracts/Oracle/Interfaces/IChainlinkFeed.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\ninterface IChainlinkFeed {\n function decimals() external view returns (uint8);\n\n function latestAnswer() external view returns (uint256);\n}\n" }, "contracts/Oracle/Interfaces/IWitnetFeed.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\ninterface IWitnetFeed {\n function lastPrice() external view returns (int256);\n}\n" }, "contracts/Oracle/Interfaces/IStdReference.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\ninterface IStdReference {\n /// A structure returned whenever someone requests for standard reference data.\n struct ReferenceData {\n uint256 rate; // base/quote exchange rate, multiplied by 1e18.\n uint256 lastUpdatedBase; // UNIX epoch of the last time when base price gets updated.\n uint256 lastUpdatedQuote; // UNIX epoch of the last time when quote price gets updated.\n }\n\n /// Returns the price data for the given base/quote pair. Revert if not available.\n function getReferenceData(string calldata _base, string calldata _quote) external view returns (ReferenceData memory);\n\n /// Similar to getReferenceData, but with multiple base/quote pairs at once.\n function getReferenceDataBulk(string[] calldata _bases, string[] calldata _quotes)\n external\n view\n returns (ReferenceData[] memory);\n}\n" }, "contracts/Oracle/PythOracle.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\nimport \"@pythnetwork/pyth-sdk-solidity/IPyth.sol\";\n\ncontract PythOracle {\n bool public constant isPriceOracle = true;\n struct FeedData {\n bytes32 feedId; // Pyth price feed ID\n uint8 tokenDecimals; // token decimals\n address addr; // feed address\n string name;\n }\n\n address public owner;\n mapping(address => FeedData) public feeds; // cToken -> feed data\n mapping(address => uint256) public fixedPrices; // cToken -> price\n uint8 constant DECIMALS = 36;\n\n event SetFeed(\n address indexed cToken_,\n bytes32 feedId,\n address addr,\n string name\n );\n\n modifier onlyOwner() {\n require(msg.sender == owner, \"ONLY OWNER\");\n _;\n }\n\n constructor() {\n owner = msg.sender;\n }\n\n function changeOwner(address owner_) public onlyOwner {\n require(owner_ != address(0), \"Address is Zero!\");\n owner = owner_;\n }\n\n function setFixedPrice(address cToken_, uint256 price) public onlyOwner {\n fixedPrices[cToken_] = price;\n }\n\n function setFeedId(\n address cToken_,\n bytes32 feedId,\n address addr,\n uint8 tokenDecimals,\n string memory name\n ) public onlyOwner {\n _setFeed(cToken_, feedId, addr, tokenDecimals, name);\n }\n\n function _setFeed(\n address cToken_,\n bytes32 feedId,\n address addr,\n uint8 tokenDecimals,\n string memory name\n ) private {\n require(addr != address(0), \"Address is Zero!\");\n require(feedId != bytes32(0), \"feedId is Zero!\");\n\n FeedData memory feedData = FeedData({\n feedId: feedId,\n addr: addr,\n tokenDecimals: tokenDecimals,\n name: name\n });\n feeds[cToken_] = feedData;\n emit SetFeed(cToken_, feedId, addr, name);\n }\n\n function removeFeed(address cToken_) public onlyOwner {\n delete feeds[cToken_];\n }\n\n function getFeed(address cToken_) public view returns (FeedData memory) {\n return feeds[cToken_];\n }\n\n function getFixedPrice(address cToken_) public view returns (uint256) {\n return fixedPrices[cToken_];\n }\n\n function removeFixedPrice(address cToken_) public onlyOwner {\n delete fixedPrices[cToken_];\n }\n\n function getUnderlyingPrice(address cToken_) public view returns (uint256) {\n if (fixedPrices[cToken_] > 0) {\n return fixedPrices[cToken_];\n } else {\n FeedData memory feed = feeds[cToken_]; // gas savings\n if (feed.feedId == bytes32(0)) {\n return 0;\n } else {\n PythStructs.Price memory price = IPyth(feed.addr)\n .getPriceUnsafe(feed.feedId);\n\n uint256 decimals = DECIMALS -\n feed.tokenDecimals -\n uint32(price.expo * -1);\n require(decimals <= DECIMALS, \"DECIMAL UNDERFLOW\");\n return uint64(price.price) * (10 ** decimals);\n }\n }\n }\n\n function getUnderlyingPrices(\n address[] memory cTokens\n ) public view returns (uint256[] memory) {\n uint256 length = cTokens.length;\n uint256[] memory results = new uint256[](length);\n for (uint256 i; i < length; ++i) {\n results[i] = getUnderlyingPrice(cTokens[i]);\n }\n return results;\n }\n}\n" }, "@pythnetwork/pyth-sdk-solidity/IPyth.sol": { "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.0;\n\nimport \"./PythStructs.sol\";\nimport \"./IPythEvents.sol\";\n\n/// @title Consume prices from the Pyth Network (https://pyth.network/).\n/// @dev Please refer to the guidance at https://docs.pyth.network/consumers/best-practices for how to consume prices safely.\n/// @author Pyth Data Association\ninterface IPyth is IPythEvents {\n /// @notice Returns the period (in seconds) that a price feed is considered valid since its publish time\n function getValidTimePeriod() external view returns (uint validTimePeriod);\n\n /// @notice Returns the price and confidence interval.\n /// @dev Reverts if the price has not been updated within the last `getValidTimePeriod()` seconds.\n /// @param id The Pyth Price Feed ID of which to fetch the price and confidence interval.\n /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.\n function getPrice(\n bytes32 id\n ) external view returns (PythStructs.Price memory price);\n\n /// @notice Returns the exponentially-weighted moving average price and confidence interval.\n /// @dev Reverts if the EMA price is not available.\n /// @param id The Pyth Price Feed ID of which to fetch the EMA price and confidence interval.\n /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.\n function getEmaPrice(\n bytes32 id\n ) external view returns (PythStructs.Price memory price);\n\n /// @notice Returns the price of a price feed without any sanity checks.\n /// @dev This function returns the most recent price update in this contract without any recency checks.\n /// This function is unsafe as the returned price update may be arbitrarily far in the past.\n ///\n /// Users of this function should check the `publishTime` in the price to ensure that the returned price is\n /// sufficiently recent for their application. If you are considering using this function, it may be\n /// safer / easier to use either `getPrice` or `getPriceNoOlderThan`.\n /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.\n function getPriceUnsafe(\n bytes32 id\n ) external view returns (PythStructs.Price memory price);\n\n /// @notice Returns the price that is no older than `age` seconds of the current time.\n /// @dev This function is a sanity-checked version of `getPriceUnsafe` which is useful in\n /// applications that require a sufficiently-recent price. Reverts if the price wasn't updated sufficiently\n /// recently.\n /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.\n function getPriceNoOlderThan(\n bytes32 id,\n uint age\n ) external view returns (PythStructs.Price memory price);\n\n /// @notice Returns the exponentially-weighted moving average price of a price feed without any sanity checks.\n /// @dev This function returns the same price as `getEmaPrice` in the case where the price is available.\n /// However, if the price is not recent this function returns the latest available price.\n ///\n /// The returned price can be from arbitrarily far in the past; this function makes no guarantees that\n /// the returned price is recent or useful for any particular application.\n ///\n /// Users of this function should check the `publishTime` in the price to ensure that the returned price is\n /// sufficiently recent for their application. If you are considering using this function, it may be\n /// safer / easier to use either `getEmaPrice` or `getEmaPriceNoOlderThan`.\n /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.\n function getEmaPriceUnsafe(\n bytes32 id\n ) external view returns (PythStructs.Price memory price);\n\n /// @notice Returns the exponentially-weighted moving average price that is no older than `age` seconds\n /// of the current time.\n /// @dev This function is a sanity-checked version of `getEmaPriceUnsafe` which is useful in\n /// applications that require a sufficiently-recent price. Reverts if the price wasn't updated sufficiently\n /// recently.\n /// @return price - please read the documentation of PythStructs.Price to understand how to use this safely.\n function getEmaPriceNoOlderThan(\n bytes32 id,\n uint age\n ) external view returns (PythStructs.Price memory price);\n\n /// @notice Update price feeds with given update messages.\n /// This method requires the caller to pay a fee in wei; the required fee can be computed by calling\n /// `getUpdateFee` with the length of the `updateData` array.\n /// Prices will be updated if they are more recent than the current stored prices.\n /// The call will succeed even if the update is not the most recent.\n /// @dev Reverts if the transferred fee is not sufficient or the updateData is invalid.\n /// @param updateData Array of price update data.\n function updatePriceFeeds(bytes[] calldata updateData) external payable;\n\n /// @notice Wrapper around updatePriceFeeds that rejects fast if a price update is not necessary. A price update is\n /// necessary if the current on-chain publishTime is older than the given publishTime. It relies solely on the\n /// given `publishTimes` for the price feeds and does not read the actual price update publish time within `updateData`.\n ///\n /// This method requires the caller to pay a fee in wei; the required fee can be computed by calling\n /// `getUpdateFee` with the length of the `updateData` array.\n ///\n /// `priceIds` and `publishTimes` are two arrays with the same size that correspond to senders known publishTime\n /// of each priceId when calling this method. If all of price feeds within `priceIds` have updated and have\n /// a newer or equal publish time than the given publish time, it will reject the transaction to save gas.\n /// Otherwise, it calls updatePriceFeeds method to update the prices.\n ///\n /// @dev Reverts if update is not needed or the transferred fee is not sufficient or the updateData is invalid.\n /// @param updateData Array of price update data.\n /// @param priceIds Array of price ids.\n /// @param publishTimes Array of publishTimes. `publishTimes[i]` corresponds to known `publishTime` of `priceIds[i]`\n function updatePriceFeedsIfNecessary(\n bytes[] calldata updateData,\n bytes32[] calldata priceIds,\n uint64[] calldata publishTimes\n ) external payable;\n\n /// @notice Returns the required fee to update an array of price updates.\n /// @param updateData Array of price update data.\n /// @return feeAmount The required fee in Wei.\n function getUpdateFee(\n bytes[] calldata updateData\n ) external view returns (uint feeAmount);\n\n /// @notice Parse `updateData` and return price feeds of the given `priceIds` if they are all published\n /// within `minPublishTime` and `maxPublishTime`.\n ///\n /// You can use this method if you want to use a Pyth price at a fixed time and not the most recent price;\n /// otherwise, please consider using `updatePriceFeeds`. This method does not store the price updates on-chain.\n ///\n /// This method requires the caller to pay a fee in wei; the required fee can be computed by calling\n /// `getUpdateFee` with the length of the `updateData` array.\n ///\n ///\n /// @dev Reverts if the transferred fee is not sufficient or the updateData is invalid or there is\n /// no update for any of the given `priceIds` within the given time range.\n /// @param updateData Array of price update data.\n /// @param priceIds Array of price ids.\n /// @param minPublishTime minimum acceptable publishTime for the given `priceIds`.\n /// @param maxPublishTime maximum acceptable publishTime for the given `priceIds`.\n /// @return priceFeeds Array of the price feeds corresponding to the given `priceIds` (with the same order).\n function parsePriceFeedUpdates(\n bytes[] calldata updateData,\n bytes32[] calldata priceIds,\n uint64 minPublishTime,\n uint64 maxPublishTime\n ) external payable returns (PythStructs.PriceFeed[] memory priceFeeds);\n}\n" }, "@pythnetwork/pyth-sdk-solidity/IPythEvents.sol": { "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.0;\n\n/// @title IPythEvents contains the events that Pyth contract emits.\n/// @dev This interface can be used for listening to the updates for off-chain and testing purposes.\ninterface IPythEvents {\n /// @dev Emitted when the price feed with `id` has received a fresh update.\n /// @param id The Pyth Price Feed ID.\n /// @param publishTime Publish time of the given price update.\n /// @param price Price of the given price update.\n /// @param conf Confidence interval of the given price update.\n event PriceFeedUpdate(\n bytes32 indexed id,\n uint64 publishTime,\n int64 price,\n uint64 conf\n );\n\n /// @dev Emitted when a batch price update is processed successfully.\n /// @param chainId ID of the source chain that the batch price update comes from.\n /// @param sequenceNumber Sequence number of the batch price update.\n event BatchPriceFeedUpdate(uint16 chainId, uint64 sequenceNumber);\n}\n" }, "@pythnetwork/pyth-sdk-solidity/PythStructs.sol": { "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.0;\n\ncontract PythStructs {\n // A price with a degree of uncertainty, represented as a price +- a confidence interval.\n //\n // The confidence interval roughly corresponds to the standard error of a normal distribution.\n // Both the price and confidence are stored in a fixed-point numeric representation,\n // `x * (10^expo)`, where `expo` is the exponent.\n //\n // Please refer to the documentation at https://docs.pyth.network/consumers/best-practices for how\n // to how this price safely.\n struct Price {\n // Price\n int64 price;\n // Confidence interval around the price\n uint64 conf;\n // Price exponent\n int32 expo;\n // Unix timestamp describing when the price was published\n uint publishTime;\n }\n\n // PriceFeed represents a current aggregate price from pyth publisher feeds.\n struct PriceFeed {\n // The price ID.\n bytes32 id;\n // Latest available price\n Price price;\n // Latest available exponentially-weighted moving average price\n Price emaPrice;\n }\n}\n" }, "contracts/OFT/OFT.sol": { "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/token/ERC20/ERC20.sol';\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './interfaces/IOFT.sol';\nimport './OFTCore.sol';\n\n// override decimal() function is needed\ncontract OFT is OFTCore, ERC20, IOFT {\n constructor(\n string memory _name,\n string memory _symbol,\n address _lzEndpoint\n ) ERC20(_name, _symbol) OFTCore(_lzEndpoint) {}\n\n function token() public view virtual override returns (address) {\n return address(this);\n }\n\n function circulatingSupply() public view virtual override returns (uint256) {\n return totalSupply();\n }\n\n function _debitFrom(\n address _from,\n uint16,\n bytes memory,\n uint256 _amount\n ) internal virtual override returns (uint256) {\n address spender = _msgSender();\n if (_from != spender) _spendAllowance(_from, spender, _amount);\n _burn(_from, _amount);\n return _amount;\n }\n\n function _creditTo(uint16, address _toAddress, uint256 _amount) internal virtual override returns (uint256) {\n _mint(_toAddress, _amount);\n return _amount;\n }\n}\n" }, "contracts/OFT/interfaces/IOFT.sol": { "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.5.0;\n\nimport './IOFTCore.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\n\n/**\n * @dev Interface of the OFT standard\n */\ninterface IOFT is IOFTCore, IERC20 {\n\n}\n" }, "@openzeppelin/contracts/token/ERC20/ERC20.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `from` to `to`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n // decrementing then incrementing.\n _balances[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n unchecked {\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n _balances[account] += amount;\n }\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n // Overflow not possible: amount <= accountBalance <= totalSupply.\n _totalSupply -= amount;\n }\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n}\n" }, "@openzeppelin/contracts/token/ERC20/IERC20.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.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(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\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" }, "contracts/OFT/SumerOFT.sol": { "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport './OFT.sol';\nimport '@openzeppelin/contracts/security/Pausable.sol';\nimport '@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol';\n\ncontract SumerOFT is OFT, EIP712, Pausable {\n uint256 private _cap;\n mapping(address => bool) private _blackList;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n // upgradeable\n\n constructor(\n string memory _name,\n string memory _symbol,\n uint256 _initialSupply,\n address _layerZeroEndpoint\n ) OFT(_name, _symbol, _layerZeroEndpoint) EIP712(_name, 'v1.0') {\n _mint(_msgSender(), _initialSupply);\n }\n\n /**\n * @dev Returns the cap on the token's total supply.\n */\n function cap() public view virtual returns (uint256) {\n return _cap;\n }\n\n /**\n * @dev Creates `amount` new tokens for `to`.\n *\n * See {ERC20-_mint}.\n *\n * Requirements:\n *\n * - the caller must have the `MINTER_ROLE`.\n */\n function mint(address to, uint256 amount) public onlyRole(MINTER_ROLE) {\n if (_cap > 0) {\n require(totalSupply() + amount <= _cap, 'ERC20Capped: cap exceeded');\n }\n _mint(to, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n _spendAllowance(account, _msgSender(), amount);\n _burn(account, amount);\n }\n\n /**\n * @dev Pauses all token transfers.\n *\n * See {ERC20Pausable} and {Pausable-_pause}.\n *\n * Requirements:\n *\n * - the caller must have the `PAUSER_ROLE`.\n */\n function pause() public onlyRole(PAUSER_ROLE) {\n _pause();\n }\n\n /**\n * @dev Unpauses all token transfers.\n *\n * See {ERC20Pausable} and {Pausable-_unpause}.\n *\n * Requirements:\n *\n * - the caller must have the `PAUSER_ROLE`.\n */\n function unpause() public virtual onlyRole(PAUSER_ROLE) {\n _unpause();\n }\n\n function setCap(uint256 cap_) public onlyAdmin {\n _cap = cap_;\n }\n\n function setBlackList(address account) public onlyAdmin {\n _blackList[account] = !_blackList[account];\n }\n\n /**\n * @dev See {ERC20-_beforeTokenTransfer}.\n *\n * Requirements:\n *\n * - the contract must not be paused.\n */\n\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal override {\n super._beforeTokenTransfer(from, to, amount);\n require(!_blackList[from] && !_blackList[to], 'ERC20Pausable: account is in black list');\n require(!paused(), 'ERC20Pausable: token transfer while paused');\n }\n\n function permit(\n address signer,\n address spender,\n uint256 value,\n uint256 deadline,\n bytes memory signature\n ) external returns (bool) {\n require(deadline >= block.timestamp, 'expired!');\n bytes32 structHash = keccak256(abi.encode(PERMIT_TYPEHASH, signer, spender, value, nonces[signer]++, deadline));\n bytes32 hash = _hashTypedDataV4(structHash);\n require(ECDSA.recover(hash, signature) == signer, 'Permit: invalid signature');\n _spendAllowance(signer, spender, value);\n return true;\n }\n}\n" }, "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\n// EIP-712 is Final as of 2022-08-11. This file is deprecated.\n\nimport \"./EIP712.sol\";\n" }, "@openzeppelin/contracts/security/Pausable.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract Pausable is Context {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n constructor() {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n}\n" }, "@openzeppelin/contracts/utils/cryptography/EIP712.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" }, "@openzeppelin/contracts/utils/cryptography/ECDSA.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" }, "contracts/OFT-upgradable/SumerOFTUpgradeable.sol": { "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport './OFTUpgradeable.sol';\nimport '@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol';\nimport '@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol';\n\ncontract SumerOFTUpgradeable is OFTUpgradeable, EIP712Upgradeable, PausableUpgradeable {\n uint256 private _cap;\n mapping(address => bool) private _blackList;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint256) public nonces;\n\n function initialize(\n string memory _name,\n string memory _symbol,\n uint256 _initialSupply,\n address _lzEndpoint\n ) public initializer {\n __ExampleOFTUpgradeable_init(_name, _symbol, _initialSupply, _lzEndpoint);\n }\n\n function __ExampleOFTUpgradeable_init(\n string memory _name,\n string memory _symbol,\n uint256 _initialSupply,\n address _lzEndpoint\n ) internal onlyInitializing {\n __OFTUpgradeable_init(_name, _symbol, _lzEndpoint);\n __EIP712_init(_name, 'v1.0');\n __ExampleOFTUpgradeable_init_unchained(_name, _symbol, _initialSupply, _lzEndpoint);\n }\n\n function __ExampleOFTUpgradeable_init_unchained(\n string memory,\n string memory,\n uint256 _initialSupply,\n address\n ) internal onlyInitializing {\n _mint(_msgSender(), _initialSupply);\n }\n\n /**\n * @dev Returns the cap on the token's total supply.\n */\n function cap() public view virtual returns (uint256) {\n return _cap;\n }\n\n /**\n * @dev Creates `amount` new tokens for `to`.\n *\n * See {ERC20-_mint}.\n *\n * Requirements:\n *\n * - the caller must have the `MINTER_ROLE`.\n */\n function mint(address to, uint256 amount) public {\n require(hasRole(MINTER_ROLE, _msgSender()), 'ERC20PresetMinterPauser: must have minter role to mint');\n if (_cap > 0) {\n require(totalSupply() + amount <= _cap, 'ERC20Capped: cap exceeded');\n }\n _mint(to, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n _spendAllowance(account, _msgSender(), amount);\n _burn(account, amount);\n }\n\n /**\n * @dev Pauses all token transfers.\n *\n * See {ERC20Pausable} and {Pausable-_pause}.\n *\n * Requirements:\n *\n * - the caller must have the `PAUSER_ROLE`.\n */\n function pause() public {\n require(hasRole(PAUSER_ROLE, _msgSender()), 'ERC20PresetMinterPauser: must have pauser role to pause');\n _pause();\n }\n\n /**\n * @dev Unpauses all token transfers.\n *\n * See {ERC20Pausable} and {Pausable-_unpause}.\n *\n * Requirements:\n *\n * - the caller must have the `PAUSER_ROLE`.\n */\n function unpause() public virtual {\n require(hasRole(PAUSER_ROLE, _msgSender()), 'ERC20PresetMinterPauser: must have pauser role to unpause');\n _unpause();\n }\n\n function setCap(uint256 cap_) public {\n require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), 'ERC20PresetMinterPauser: must have adfmin role to set cap');\n _cap = cap_;\n }\n\n function setBlackList(address account) public {\n require(\n hasRole(DEFAULT_ADMIN_ROLE, _msgSender()),\n 'ERC20PresetMinterPauser: must have adfmin role to set black list'\n );\n _blackList[account] = !_blackList[account];\n }\n\n /**\n * @dev See {ERC20-_beforeTokenTransfer}.\n *\n * Requirements:\n *\n * - the contract must not be paused.\n */\n\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal override {\n super._beforeTokenTransfer(from, to, amount);\n require(!_blackList[from] && !_blackList[to], 'ERC20Pausable: account is in black list');\n require(!paused(), 'ERC20Pausable: token transfer while paused');\n }\n\n function permit(\n address signer,\n address spender,\n uint256 value,\n uint256 deadline,\n bytes memory signature\n ) external returns (bool) {\n require(deadline >= block.timestamp, 'expired!');\n bytes32 structHash = keccak256(abi.encode(PERMIT_TYPEHASH, signer, spender, value, nonces[signer]++, deadline));\n bytes32 hash = _hashTypedDataV4(structHash);\n require(ECDSAUpgradeable.recover(hash, signature) == signer, 'Permit: invalid signature');\n _spendAllowance(signer, spender, value);\n return true;\n }\n}\n" }, "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSAUpgradeable.sol\";\nimport \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n *\n * @custom:storage-size 52\n */\nabstract contract EIP712Upgradeable is Initializable {\n /* solhint-disable var-name-mixedcase */\n bytes32 private _HASHED_NAME;\n bytes32 private _HASHED_VERSION;\n bytes32 private constant _TYPE_HASH = keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n function __EIP712_init(string memory name, string memory version) internal onlyInitializing {\n __EIP712_init_unchained(name, version);\n }\n\n function __EIP712_init_unchained(string memory name, string memory version) internal onlyInitializing {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n return _buildDomainSeparator(_TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash());\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSAUpgradeable.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n\n /**\n * @dev The hash of the name parameter for the EIP712 domain.\n *\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\n * are a concern.\n */\n function _EIP712NameHash() internal virtual view returns (bytes32) {\n return _HASHED_NAME;\n }\n\n /**\n * @dev The hash of the version parameter for the EIP712 domain.\n *\n * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs\n * are a concern.\n */\n function _EIP712VersionHash() internal virtual view returns (bytes32) {\n return _HASHED_VERSION;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" }, "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal onlyInitializing {\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal onlyInitializing {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" }, "contracts/OFT-upgradable/OFTUpgradeable.sol": { "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.2;\n\nimport '@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol';\nimport '@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol';\nimport '@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol';\nimport './OFTCoreUpgradeable.sol';\nimport './interfaces/IOFTUpgradeable.sol';\n\n// override decimal() function is needed\ncontract OFTUpgradeable is Initializable, OFTCoreUpgradeable, ERC20Upgradeable, IOFTUpgradeable {\n function __OFTUpgradeable_init(\n string memory _name,\n string memory _symbol,\n address _lzEndpoint\n ) internal onlyInitializing {\n __ERC20_init_unchained(_name, _symbol);\n __OFTCoreUpgradeable_init_unchained(_lzEndpoint);\n }\n\n function __OFTUpgradeable_init_unchained(\n string memory _name,\n string memory _symbol,\n address _lzEndpoint\n ) internal onlyInitializing {}\n\n function token() public view virtual override returns (address) {\n return address(this);\n }\n\n function supportsInterface(\n bytes4 interfaceId\n ) public view virtual override(AccessControlEnumerableUpgradeable, IERC165Upgradeable) returns (bool) {\n return\n interfaceId == type(IOFTUpgradeable).interfaceId ||\n interfaceId == type(IERC20Upgradeable).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n function circulatingSupply() public view virtual override returns (uint256) {\n return totalSupply();\n }\n\n function _debitFrom(\n address _from,\n uint16,\n bytes memory,\n uint256 _amount\n ) internal virtual override returns (uint256) {\n address spender = _msgSender();\n if (_from != spender) _spendAllowance(_from, spender, _amount);\n _burn(_from, _amount);\n return _amount;\n }\n\n function _creditTo(uint16, address _toAddress, uint256 _amount) internal virtual override returns (uint256) {\n _mint(_toAddress, _amount);\n return _amount;\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" }, "contracts/OFT-upgradable/interfaces/IOFTUpgradeable.sol": { "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.2;\n\nimport \"./IOFTCoreUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\n/**\n * @dev Interface of the OFT standard\n */\ninterface IOFTUpgradeable is IOFTCoreUpgradeable, IERC20Upgradeable {\n\n}\n" }, "contracts/OFT-upgradable/OFTCoreUpgradeable.sol": { "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.2;\n\nimport './interfaces/IOFTCoreUpgradeable.sol';\nimport './lzApp/NonblockingLzAppUpgradeable.sol';\n\nabstract contract OFTCoreUpgradeable is Initializable, NonblockingLzAppUpgradeable, IOFTCoreUpgradeable {\n using BytesLib for bytes;\n\n uint256 public constant NO_EXTRA_GAS = 0;\n uint256 public constant FUNCTION_TYPE_SEND = 1;\n bool public useCustomAdapterParams;\n\n\n function __OFTCoreUpgradeable_init(address _endpoint) internal onlyInitializing {\n __OFTCoreUpgradeable_init_unchained(_endpoint);\n }\n\n function __OFTCoreUpgradeable_init_unchained(address _endpoint) internal onlyInitializing {\n __NonblockingLzAppUpgradeable_init_unchained(_endpoint);\n }\n\n function estimateSendFee(\n uint16 _dstChainId,\n bytes calldata _toAddress,\n uint256 _amount,\n bool _useZro,\n bytes calldata _adapterParams\n ) public view virtual override returns (uint256 nativeFee, uint256 zroFee) {\n // mock the payload for sendFrom()\n bytes memory payload = abi.encode(0, _toAddress, _amount);\n return lzEndpoint.estimateFees(_dstChainId, address(this), payload, _useZro, _adapterParams);\n }\n\n function sendFrom(\n address _from,\n uint16 _dstChainId,\n bytes calldata _toAddress,\n uint256 _amount,\n address payable _refundAddress,\n address _zroPaymentAddress,\n bytes calldata _adapterParams\n ) public payable virtual override {\n _send(_from, _dstChainId, _toAddress, _amount, _refundAddress, _zroPaymentAddress, _adapterParams);\n }\n\n function setUseCustomAdapterParams(bool _useCustomAdapterParams) public virtual onlyAdmin {\n useCustomAdapterParams = _useCustomAdapterParams;\n emit SetUseCustomAdapterParams(_useCustomAdapterParams);\n }\n\n function _nonblockingLzReceive(\n uint16 _srcChainId,\n bytes memory _srcAddress,\n uint64 _nonce,\n bytes memory _payload\n ) internal virtual override {\n uint16 packetType;\n assembly {\n packetType := mload(add(_payload, 32))\n }\n\n if (packetType == 0) {\n _sendAck(_srcChainId, _srcAddress, _nonce, _payload);\n } else {\n revert('OFTCore: unknown packet type');\n }\n }\n\n function _send(\n address _from,\n uint16 _dstChainId,\n bytes memory _toAddress,\n uint256 _amount,\n address payable _refundAddress,\n address _zroPaymentAddress,\n bytes memory _adapterParams\n ) internal virtual {\n _checkAdapterParams(_dstChainId, 0, _adapterParams, NO_EXTRA_GAS);\n\n uint256 amount = _debitFrom(_from, _dstChainId, _toAddress, _amount);\n\n bytes memory lzPayload = abi.encode(0, _toAddress, amount);\n _lzSend(_dstChainId, lzPayload, _refundAddress, _zroPaymentAddress, _adapterParams, msg.value);\n\n emit SendToChain(_dstChainId, _from, _toAddress, amount);\n }\n\n function _sendAck(uint16 _srcChainId, bytes memory, uint64, bytes memory _payload) internal virtual {\n (, bytes memory toAddressBytes, uint256 amount) = abi.decode(_payload, (uint16, bytes, uint256));\n\n address to = toAddressBytes.toAddress(0);\n\n amount = _creditTo(_srcChainId, to, amount);\n emit ReceiveFromChain(_srcChainId, to, amount);\n }\n\n function _checkAdapterParams(\n uint16 _dstChainId,\n uint16 _pkType,\n bytes memory _adapterParams,\n uint256 _extraGas\n ) internal virtual {\n if (useCustomAdapterParams) {\n _checkGasLimit(_dstChainId, _pkType, _adapterParams, _extraGas);\n } else {\n require(_adapterParams.length == 0, 'OFTCore: _adapterParams must be empty.');\n }\n }\n\n function _debitFrom(\n address _from,\n uint16 _dstChainId,\n bytes memory _toAddress,\n uint256 _amount\n ) internal virtual returns (uint256);\n\n function _creditTo(uint16 _srcChainId, address _toAddress, uint256 _amount) internal virtual returns (uint256);\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" }, "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.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(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" }, "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20Upgradeable.sol\";\nimport \"./extensions/IERC20MetadataUpgradeable.sol\";\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable, IERC20MetadataUpgradeable {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {\n __ERC20_init_unchained(name_, symbol_);\n }\n\n function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `from` to `to`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n // decrementing then incrementing.\n _balances[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n unchecked {\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n _balances[account] += amount;\n }\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n // Overflow not possible: amount <= accountBalance <= totalSupply.\n _totalSupply -= amount;\n }\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[45] private __gap;\n}\n" }, "@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../StringsUpgradeable.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSAUpgradeable {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV // Deprecated in v4.8\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n /// @solidity memory-safe-assembly\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address, RecoverError) {\n bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", StringsUpgradeable.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" }, "contracts/OFT-upgradable/interfaces/IOFTCoreUpgradeable.sol": { "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.2;\n\nimport '@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol';\n\n/**\n * @dev Interface of the IOFT core standard\n */\ninterface IOFTCoreUpgradeable is IERC165Upgradeable {\n /**\n * @dev estimate send token `_tokenId` to (`_dstChainId`, `_toAddress`)\n * _dstChainId - L0 defined chain id to send tokens too\n * _toAddress - dynamic bytes array which contains the address to whom you are sending tokens to on the dstChain\n * _amount - amount of the tokens to transfer\n * _useZro - indicates to use zro to pay L0 fees\n * _adapterParam - flexible bytes array to indicate messaging adapter services in L0\n */\n function estimateSendFee(\n uint16 _dstChainId,\n bytes calldata _toAddress,\n uint256 _amount,\n bool _useZro,\n bytes calldata _adapterParams\n ) external view returns (uint256 nativeFee, uint256 zroFee);\n\n /**\n * @dev send `_amount` amount of token to (`_dstChainId`, `_toAddress`) from `_from`\n * `_from` the owner of token\n * `_dstChainId` the destination chain identifier\n * `_toAddress` can be any size depending on the `dstChainId`.\n * `_amount` the quantity of tokens in wei\n * `_refundAddress` the address LayerZero refunds if too much message fee is sent\n * `_zroPaymentAddress` set to address(0x0) if not paying in ZRO (LayerZero Token)\n * `_adapterParams` is a flexible bytes array to indicate messaging adapter services\n */\n function sendFrom(\n address _from,\n uint16 _dstChainId,\n bytes calldata _toAddress,\n uint256 _amount,\n address payable _refundAddress,\n address _zroPaymentAddress,\n bytes calldata _adapterParams\n ) external payable;\n\n /**\n * @dev returns the circulating amount of tokens on current chain\n */\n function circulatingSupply() external view returns (uint256);\n\n /**\n * @dev returns the address of the ERC20 token\n */\n function token() external view returns (address);\n\n /**\n * @dev Emitted when `_amount` tokens are moved from the `_sender` to (`_dstChainId`, `_toAddress`)\n * `_nonce` is the outbound nonce\n */\n event SendToChain(uint16 indexed _dstChainId, address indexed _from, bytes _toAddress, uint256 _amount);\n\n /**\n * @dev Emitted when `_amount` tokens are received from `_srcChainId` into the `_toAddress` on the local chain.\n * `_nonce` is the inbound nonce.\n */\n event ReceiveFromChain(uint16 indexed _srcChainId, address indexed _to, uint256 _amount);\n\n event SetUseCustomAdapterParams(bool _useCustomAdapterParams);\n}\n" }, "contracts/OFT-upgradable/lzApp/NonblockingLzAppUpgradeable.sol": { "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.2;\n\nimport './LzAppUpgradeable.sol';\n\n/*\n * the default LayerZero messaging behaviour is blocking, i.e. any failed message will block the channel\n * this abstract class try-catch all fail messages and store locally for future retry. hence, non-blocking\n * NOTE: if the srcAddress is not configured properly, it will still block the message pathway from (srcChainId, srcAddress)\n */\nabstract contract NonblockingLzAppUpgradeable is Initializable, LzAppUpgradeable {\n function __NonblockingLzAppUpgradeable_init(address _endpoint) internal onlyInitializing {\n __NonblockingLzAppUpgradeable_init_unchained(_endpoint);\n }\n\n function __NonblockingLzAppUpgradeable_init_unchained(address _endpoint) internal onlyInitializing {\n __LzAppUpgradeable_init_unchained(_endpoint);\n }\n\n mapping(uint16 => mapping(bytes => mapping(uint64 => bytes32))) public failedMessages;\n\n event MessageFailed(uint16 _srcChainId, bytes _srcAddress, uint64 _nonce, bytes _payload);\n\n // overriding the virtual function in LzReceiver\n function _blockingLzReceive(\n uint16 _srcChainId,\n bytes memory _srcAddress,\n uint64 _nonce,\n bytes memory _payload\n ) internal virtual override {\n // try-catch all errors/exceptions\n try this.nonblockingLzReceive(_srcChainId, _srcAddress, _nonce, _payload) {\n // do nothing\n } catch {\n // error / exception\n failedMessages[_srcChainId][_srcAddress][_nonce] = keccak256(_payload);\n emit MessageFailed(_srcChainId, _srcAddress, _nonce, _payload);\n }\n }\n\n function nonblockingLzReceive(\n uint16 _srcChainId,\n bytes memory _srcAddress,\n uint64 _nonce,\n bytes memory _payload\n ) public virtual {\n // only internal transaction\n require(_msgSender() == address(this), 'NonblockingLzApp: caller must be LzApp');\n _nonblockingLzReceive(_srcChainId, _srcAddress, _nonce, _payload);\n }\n\n //@notice override this function\n function _nonblockingLzReceive(\n uint16 _srcChainId,\n bytes memory _srcAddress,\n uint64 _nonce,\n bytes memory _payload\n ) internal virtual;\n\n function retryMessage(\n uint16 _srcChainId,\n bytes memory _srcAddress,\n uint64 _nonce,\n bytes memory _payload\n ) public payable virtual {\n // assert there is message to retry\n bytes32 payloadHash = failedMessages[_srcChainId][_srcAddress][_nonce];\n require(payloadHash != bytes32(0), 'NonblockingLzApp: no stored message');\n require(keccak256(_payload) == payloadHash, 'NonblockingLzApp: invalid payload');\n // clear the stored message\n failedMessages[_srcChainId][_srcAddress][_nonce] = bytes32(0);\n // execute the message. revert if it fails again\n _nonblockingLzReceive(_srcChainId, _srcAddress, _nonce, _payload);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" }, "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20MetadataUpgradeable is IERC20Upgradeable {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" }, "contracts/OFT-upgradable/lzApp/LzAppUpgradeable.sol": { "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.2;\n\nimport '../OFTAccessControlUpgradeable.sol';\nimport '../interfaces/ILayerZeroReceiverUpgradeable.sol';\nimport '../interfaces/ILayerZeroUserApplicationConfigUpgradeable.sol';\nimport '../interfaces/ILayerZeroEndpointUpgradeable.sol';\nimport '../../OFT/util/BytesLib.sol';\n\n/*\n * a generic LzReceiver implementation\n */\nabstract contract LzAppUpgradeable is\n Initializable,\n OFTAccessControlUpgradeable,\n ILayerZeroReceiverUpgradeable,\n ILayerZeroUserApplicationConfigUpgradeable\n{\n using BytesLib for bytes;\n ILayerZeroEndpointUpgradeable public lzEndpoint;\n mapping(uint16 => bytes) public trustedRemoteLookup;\n mapping(uint16 => mapping(uint256 => uint256)) public minDstGasLookup;\n\n event SetTrustedRemote(uint16 _srcChainId, bytes _srcAddress);\n event SetMinDstGasLookup(uint16 _dstChainId, uint256 _type, uint256 _dstGasAmount);\n\n function __LzAppUpgradeable_init(address _endpoint) internal onlyInitializing {\n __LzAppUpgradeable_init_unchained(_endpoint);\n }\n\n function __LzAppUpgradeable_init_unchained(address _endpoint) internal onlyInitializing {\n lzEndpoint = ILayerZeroEndpointUpgradeable(_endpoint);\n __OFTAccessControlUpgradeable_init();\n }\n\n function lzReceive(\n uint16 _srcChainId,\n bytes calldata _srcAddress,\n uint64 _nonce,\n bytes calldata _payload\n ) public virtual override {\n // lzReceive must be called by the endpoint for security\n require(_msgSender() == address(lzEndpoint), 'LzApp: invalid endpoint caller');\n\n bytes memory trustedRemote = trustedRemoteLookup[_srcChainId];\n // if will still block the message pathway from (srcChainId, srcAddress). should not receive message from untrusted remote.\n require(\n _srcAddress.length == trustedRemote.length &&\n trustedRemote.length > 0 &&\n keccak256(_srcAddress) == keccak256(trustedRemote),\n 'LzApp: invalid source sending contract'\n );\n\n _blockingLzReceive(_srcChainId, _srcAddress, _nonce, _payload);\n }\n\n // abstract function - the default behaviour of LayerZero is blocking. See: NonblockingLzApp if you dont need to enforce ordered messaging\n function _blockingLzReceive(\n uint16 _srcChainId,\n bytes memory _srcAddress,\n uint64 _nonce,\n bytes memory _payload\n ) internal virtual;\n\n function _lzSend(\n uint16 _dstChainId,\n bytes memory _payload,\n address payable _refundAddress,\n address _zroPaymentAddress,\n bytes memory _adapterParams,\n uint256 _nativeFee\n ) internal virtual {\n bytes memory trustedRemote = trustedRemoteLookup[_dstChainId];\n require(trustedRemote.length != 0, 'LzApp: destination chain is not a trusted source');\n // _checkPayloadSize(_dstChainId, _payload.length);\n lzEndpoint.send{value: _nativeFee}(\n _dstChainId,\n trustedRemote,\n _payload,\n _refundAddress,\n _zroPaymentAddress,\n _adapterParams\n );\n }\n\n function _checkGasLimit(\n uint16 _dstChainId,\n uint16 _type,\n bytes memory _adapterParams,\n uint256 _extraGas\n ) internal view virtual {\n uint256 providedGasLimit = _getGasLimit(_adapterParams);\n uint256 minGasLimit = minDstGasLookup[_dstChainId][_type] + _extraGas;\n require(minGasLimit > 0, 'LzApp: minGasLimit not set');\n require(providedGasLimit >= minGasLimit, 'LzApp: gas limit is too low');\n }\n\n function _getGasLimit(bytes memory _adapterParams) internal pure virtual returns (uint256 gasLimit) {\n require(_adapterParams.length >= 34, 'LzApp: invalid adapterParams');\n assembly {\n gasLimit := mload(add(_adapterParams, 34))\n }\n }\n\n // function _checkPayloadSize(uint16 _dstChainId, uint256 _payloadSize) internal view virtual {\n // uint256 payloadSizeLimit = payloadSizeLimitLookup[_dstChainId];\n // if (payloadSizeLimit == 0) {\n // // use default if not set\n // payloadSizeLimit = DEFAULT_PAYLOAD_SIZE_LIMIT;\n // }\n // require(_payloadSize <= payloadSizeLimit, 'LzApp: payload size is too large');\n // }\n\n //---------------------------UserApplication config----------------------------------------\n function getConfig(\n uint16 _version,\n uint16 _chainId,\n address,\n uint256 _configType\n ) external view returns (bytes memory) {\n return lzEndpoint.getConfig(_version, _chainId, address(this), _configType);\n }\n\n // generic config for LayerZero user Application\n function setConfig(\n uint16 _version,\n uint16 _chainId,\n uint256 _configType,\n bytes calldata _config\n ) external override onlyAdmin {\n lzEndpoint.setConfig(_version, _chainId, _configType, _config);\n }\n\n function setSendVersion(uint16 _version) external override onlyAdmin {\n lzEndpoint.setSendVersion(_version);\n }\n\n function setReceiveVersion(uint16 _version) external override onlyAdmin {\n lzEndpoint.setReceiveVersion(_version);\n }\n\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external override onlyAdmin {\n lzEndpoint.forceResumeReceive(_srcChainId, _srcAddress);\n }\n\n // _path = abi.encodePacked(remoteAddress, localAddress)\n // this function set the trusted path for the cross-chain communication\n function setTrustedRemote(uint16 _srcChainId, bytes calldata _path) external onlyAdmin {\n trustedRemoteLookup[_srcChainId] = _path;\n emit SetTrustedRemote(_srcChainId, _path);\n }\n\n function setTrustedRemoteAddress(uint16 _remoteChainId, bytes calldata _remoteAddress) external onlyAdmin {\n trustedRemoteLookup[_remoteChainId] = abi.encodePacked(_remoteAddress, address(this));\n emit SetTrustedRemoteAddress(_remoteChainId, _remoteAddress);\n }\n\n function getTrustedRemoteAddress(uint16 _remoteChainId) external view returns (bytes memory) {\n bytes memory path = trustedRemoteLookup[_remoteChainId];\n require(path.length != 0, 'LzApp: no trusted path record');\n return path.slice(0, path.length - 20); // the last 20 bytes should be address(this)\n }\n\n function setPrecrime(address _precrime) external onlyAdmin {\n precrime = _precrime;\n emit SetPrecrime(_precrime);\n }\n\n function setMinDstGas(uint16 _dstChainId, uint16 _packetType, uint256 _minGas) external onlyAdmin {\n require(_minGas > 0, 'LzApp: invalid minGas');\n minDstGasLookup[_dstChainId][_packetType] = _minGas;\n emit SetMinDstGas(_dstChainId, _packetType, _minGas);\n }\n\n // // if the size is 0, it means default size limit\n // function setPayloadSizeLimit(uint16 _dstChainId, uint256 _size) external onlyAdmin {\n // payloadSizeLimitLookup[_dstChainId] = _size;\n // }\n \n //--------------------------- VIEW FUNCTION ----------------------------------------\n function isTrustedRemote(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool) {\n bytes memory trustedSource = trustedRemoteLookup[_srcChainId];\n return keccak256(trustedSource) == keccak256(_srcAddress);\n }\n event SetTrustedRemoteAddress(uint16 _remoteChainId, bytes _remoteAddress);\n event SetPrecrime(address precrime);\n event SetMinDstGas(uint16 _dstChainId, uint16 _type, uint256 _minDstGas);\n\n\n // ua can not send payload larger than this by default, but it can be changed by the ua owner\n uint256 public constant DEFAULT_PAYLOAD_SIZE_LIMIT = 10000;\n\n address public precrime;\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" }, "contracts/OFT-upgradable/interfaces/ILayerZeroEndpointUpgradeable.sol": { "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.2;\n\nimport \"./ILayerZeroUserApplicationConfigUpgradeable.sol\";\n\ninterface ILayerZeroEndpointUpgradeable is ILayerZeroUserApplicationConfigUpgradeable {\n // @notice send a LayerZero message to the specified address at a LayerZero endpoint.\n // @param _dstChainId - the destination chain identifier\n // @param _destination - the address on destination chain (in bytes). address length/format may vary by chains\n // @param _payload - a custom bytes payload to send to the destination contract\n // @param _refundAddress - if the source transaction is cheaper than the amount of value passed, refund the additional amount to this address\n // @param _zroPaymentAddress - the address of the ZRO token holder who would pay for the transaction\n // @param _adapterParams - parameters for custom functionality. e.g. receive airdropped native gas from the relayer on destination\n function send(uint16 _dstChainId, bytes calldata _destination, bytes calldata _payload, address payable _refundAddress, address _zroPaymentAddress, bytes calldata _adapterParams) external payable;\n\n // @notice used by the messaging library to publish verified payload\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source contract (as bytes) at the source chain\n // @param _dstAddress - the address on destination chain\n // @param _nonce - the unbound message ordering nonce\n // @param _gasLimit - the gas limit for external contract execution\n // @param _payload - verified payload to send to the destination contract\n function receivePayload(uint16 _srcChainId, bytes calldata _srcAddress, address _dstAddress, uint64 _nonce, uint _gasLimit, bytes calldata _payload) external;\n\n // @notice get the inboundNonce of a lzApp from a source chain which could be EVM or non-EVM chain\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function getInboundNonce(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (uint64);\n\n // @notice get the outboundNonce from this source chain which, consequently, is always an EVM\n // @param _srcAddress - the source chain contract address\n function getOutboundNonce(uint16 _dstChainId, address _srcAddress) external view returns (uint64);\n\n // @notice gets a quote in source native gas, for the amount that send() requires to pay for message delivery\n // @param _dstChainId - the destination chain identifier\n // @param _userApplication - the user app address on this EVM chain\n // @param _payload - the custom message to send over LayerZero\n // @param _payInZRO - if false, user app pays the protocol fee in native token\n // @param _adapterParam - parameters for the adapter service, e.g. send some dust native token to dstChain\n function estimateFees(uint16 _dstChainId, address _userApplication, bytes calldata _payload, bool _payInZRO, bytes calldata _adapterParam) external view returns (uint nativeFee, uint zroFee);\n\n // @notice get this Endpoint's immutable source identifier\n function getChainId() external view returns (uint16);\n\n // @notice the interface to retry failed message on this Endpoint destination\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n // @param _payload - the payload to be retried\n function retryPayload(uint16 _srcChainId, bytes calldata _srcAddress, bytes calldata _payload) external;\n\n // @notice query if any STORED payload (message blocking) at the endpoint.\n // @param _srcChainId - the source chain identifier\n // @param _srcAddress - the source chain contract address\n function hasStoredPayload(uint16 _srcChainId, bytes calldata _srcAddress) external view returns (bool);\n\n // @notice query if the _libraryAddress is valid for sending msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getSendLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the _libraryAddress is valid for receiving msgs.\n // @param _userApplication - the user app address on this EVM chain\n function getReceiveLibraryAddress(address _userApplication) external view returns (address);\n\n // @notice query if the non-reentrancy guard for send() is on\n // @return true if the guard is on. false otherwise\n function isSendingPayload() external view returns (bool);\n\n // @notice query if the non-reentrancy guard for receive() is on\n // @return true if the guard is on. false otherwise\n function isReceivingPayload() external view returns (bool);\n\n // @notice get the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _userApplication - the contract address of the user application\n // @param _configType - type of configuration. every messaging library has its own convention.\n function getConfig(uint16 _version, uint16 _chainId, address _userApplication, uint _configType) external view returns (bytes memory);\n\n // @notice get the send() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getSendVersion(address _userApplication) external view returns (uint16);\n\n // @notice get the lzReceive() LayerZero messaging library version\n // @param _userApplication - the contract address of the user application\n function getReceiveVersion(address _userApplication) external view returns (uint16);\n}\n" }, "contracts/OFT-upgradable/interfaces/ILayerZeroUserApplicationConfigUpgradeable.sol": { "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.2;\n\ninterface ILayerZeroUserApplicationConfigUpgradeable {\n // @notice set the configuration of the LayerZero messaging library of the specified version\n // @param _version - messaging library version\n // @param _chainId - the chainId for the pending config change\n // @param _configType - type of configuration. every messaging library has its own convention.\n // @param _config - configuration in the bytes. can encode arbitrary content.\n function setConfig(uint16 _version, uint16 _chainId, uint _configType, bytes calldata _config) external;\n\n // @notice set the send() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setSendVersion(uint16 _version) external;\n\n // @notice set the lzReceive() LayerZero messaging library version to _version\n // @param _version - new messaging library version\n function setReceiveVersion(uint16 _version) external;\n\n // @notice Only when the UA needs to resume the message flow in blocking mode and clear the stored payload\n // @param _srcChainId - the chainId of the source chain\n // @param _srcAddress - the contract address of the source contract at the source chain\n function forceResumeReceive(uint16 _srcChainId, bytes calldata _srcAddress) external;\n}\n" }, "contracts/OFT-upgradable/interfaces/ILayerZeroReceiverUpgradeable.sol": { "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.2;\n\ninterface ILayerZeroReceiverUpgradeable {\n // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n // @param _srcChainId - the source endpoint identifier\n // @param _srcAddress - the source sending contract address from the source chain\n // @param _nonce - the ordered message nonce\n // @param _payload - the signed payload is the UA bytes has encoded to be sent\n function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n" }, "contracts/OFT-upgradable/OFTAccessControlUpgradeable.sol": { "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\nimport '@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol';\n\ncontract OFTAccessControlUpgradeable is AccessControlEnumerableUpgradeable {\n bytes32 public constant MINTER_ROLE = keccak256('MINTER_ROLE');\n bytes32 public constant PAUSER_ROLE = keccak256('PAUSER_ROLE');\n\n function __OFTAccessControlUpgradeable_init() internal onlyInitializing {\n _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());\n\n _setupRole(MINTER_ROLE, _msgSender());\n _setupRole(PAUSER_ROLE, _msgSender());\n }\n\n modifier onlyAdmin() {\n _checkRole(DEFAULT_ADMIN_ROLE);\n _;\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" }, "contracts/OFT/BasedOFT.sol": { "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport './OFT.sol';\n\ncontract BasedOFT is OFT {\n constructor(\n string memory _name,\n string memory _symbol,\n address _lzEndpoint\n ) OFT(_name, _symbol, _lzEndpoint) {}\n\n function circulatingSupply() public view virtual override returns (uint256) {\n unchecked {\n return totalSupply() - balanceOf(address(this));\n }\n }\n\n function _debitFrom(\n address _from,\n uint16,\n bytes memory,\n uint256 _amount\n ) internal virtual override returns (uint256) {\n address spender = _msgSender();\n if (_from != spender) _spendAllowance(_from, spender, _amount);\n _transfer(_from, address(this), _amount);\n return _amount;\n }\n\n function _creditTo(\n uint16,\n address _toAddress,\n uint256 _amount\n ) internal virtual override returns (uint256) {\n _transfer(address(this), _toAddress, _amount);\n return _amount;\n }\n}\n" }, "contracts/stake/CommunalFarm.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/utils/math/SafeMath.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\n\nlibrary TransferHelper {\n function safeApprove(address token, address to, uint value) internal {\n // bytes4(keccak256(bytes('approve(address,uint256)')));\n (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED');\n }\n\n function safeTransfer(address token, address to, uint value) internal {\n // bytes4(keccak256(bytes('transfer(address,uint256)')));\n (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED');\n }\n\n function safeTransferFrom(address token, address from, address to, uint value) internal {\n // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));\n (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));\n require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED');\n }\n\n function safeTransferETH(address to, uint value) internal {\n (bool success, ) = to.call{value: value}(new bytes(0));\n require(success, 'TransferHelper: ETH_TRANSFER_FAILED');\n }\n}\n\ncontract CommunalFarm is Ownable, ReentrancyGuard {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n /* ========== STATE VARIABLES ========== */\n\n // Instances\n IERC20 public stakingToken;\n\n // Constant for various precisions\n uint256 private constant MULTIPLIER_PRECISION = 1e18;\n\n // Time tracking\n uint256 public periodFinish;\n uint256 public lastUpdateTime;\n\n // Lock time and multiplier settings\n uint256 public lock_max_multiplier = uint256(3e18); // E18. 1x = e18\n uint256 public lock_time_for_max_multiplier = 1 * 365 * 86400; // 1 year\n uint256 public lock_time_min = 86400; // 1 * 86400 (1 day)\n\n // Reward addresses, rates, and managers\n mapping(address => address) public rewardManagers; // token addr -> manager addr\n address[] public rewardTokens;\n uint256[] public rewardRates;\n string[] public rewardSymbols;\n mapping(address => uint256) public rewardTokenAddrToIdx; // token addr -> token index\n\n // Reward period\n uint256 public rewardsDuration = 604800; // 7 * 86400 (7 days)\n\n // Reward tracking\n uint256[] private rewardsPerTokenStored;\n mapping(address => mapping(uint256 => uint256)) private userRewardsPerTokenPaid; // staker addr -> token id -> paid amount\n mapping(address => mapping(uint256 => uint256)) private rewards; // staker addr -> token id -> reward amount\n mapping(address => uint256) private lastRewardClaimTime; // staker addr -> timestamp\n\n // Balance tracking\n uint256 private _total_liquidity_locked;\n uint256 private _total_combined_weight;\n mapping(address => uint256) private _locked_liquidity;\n mapping(address => uint256) private _combined_weights;\n\n // Stake tracking\n mapping(address => LockedStake[]) private lockedStakes;\n\n // Greylisting of bad addresses\n mapping(address => bool) public greylist;\n\n // Administrative booleans\n bool public stakesUnlocked; // Release locked stakes in case of emergency\n bool public withdrawalsPaused; // For emergencies\n bool public rewardsCollectionPaused; // For emergencies\n bool public stakingPaused; // For emergencies\n\n /* ========== STRUCTS ========== */\n\n struct LockedStake {\n bytes32 kek_id;\n uint256 start_timestamp;\n uint256 liquidity;\n uint256 ending_timestamp;\n uint256 lock_multiplier; // 6 decimals of precision. 1x = 1000000\n }\n\n /* ========== MODIFIERS ========== */\n\n modifier onlyTknMgrs(address reward_token_address) {\n require(msg.sender == owner() || isTokenManagerFor(msg.sender, reward_token_address), 'Not owner or tkn mgr');\n _;\n }\n\n modifier notStakingPaused() {\n require(stakingPaused == false, 'Staking paused');\n _;\n }\n\n modifier updateRewardAndBalance(address account, bool sync_too) {\n _updateRewardAndBalance(account, sync_too);\n _;\n }\n\n /* ========== CONSTRUCTOR ========== */\n constructor(\n address _stakingToken,\n string[] memory _rewardSymbols,\n address[] memory _rewardTokens,\n address[] memory _rewardManagers,\n uint256[] memory _rewardRates\n ) {\n stakingToken = IERC20(_stakingToken);\n\n rewardTokens = _rewardTokens;\n rewardRates = _rewardRates;\n rewardSymbols = _rewardSymbols;\n\n for (uint256 i = 0; i < _rewardTokens.length; i++) {\n // For fast token address -> token ID lookups later\n rewardTokenAddrToIdx[_rewardTokens[i]] = i;\n\n // Initialize the stored rewards\n rewardsPerTokenStored.push(0);\n\n // Initialize the reward managers\n rewardManagers[_rewardTokens[i]] = _rewardManagers[i];\n }\n\n // Other booleans\n stakesUnlocked = false;\n\n // Initialization\n lastUpdateTime = block.timestamp;\n periodFinish = block.timestamp.add(rewardsDuration);\n }\n\n /* ========== VIEWS ========== */\n\n // Total locked liquidity tokens\n function totalLiquidityLocked() external view returns (uint256) {\n return _total_liquidity_locked;\n }\n\n // Locked liquidity for a given account\n function lockedLiquidityOf(address account) external view returns (uint256) {\n return _locked_liquidity[account];\n }\n\n // Total 'balance' used for calculating the percent of the pool the account owns\n // Takes into account the locked stake time multiplier\n function totalCombinedWeight() external view returns (uint256) {\n return _total_combined_weight;\n }\n\n // Combined weight for a specific account\n function combinedWeightOf(address account) external view returns (uint256) {\n return _combined_weights[account];\n }\n\n // Calculated the combined weight for an account\n function calcCurCombinedWeight(\n address account\n ) public view returns (uint256 old_combined_weight, uint256 new_combined_weight) {\n // Get the old combined weight\n old_combined_weight = _combined_weights[account];\n\n // Loop through the locked stakes, first by getting the liquidity * lock_multiplier portion\n new_combined_weight = 0;\n for (uint256 i = 0; i < lockedStakes[account].length; i++) {\n LockedStake memory thisStake = lockedStakes[account][i];\n uint256 lock_multiplier = thisStake.lock_multiplier;\n\n // If the lock is expired\n if (thisStake.ending_timestamp <= block.timestamp) {\n // If the lock expired in the time since the last claim, the weight needs to be proportionately averaged this time\n if (lastRewardClaimTime[account] < thisStake.ending_timestamp) {\n uint256 time_before_expiry = (thisStake.ending_timestamp).sub(lastRewardClaimTime[account]);\n uint256 time_after_expiry = (block.timestamp).sub(thisStake.ending_timestamp);\n\n // Get the weighted-average lock_multiplier\n uint256 numerator = ((lock_multiplier).mul(time_before_expiry)).add(\n ((MULTIPLIER_PRECISION).mul(time_after_expiry))\n );\n lock_multiplier = numerator.div(time_before_expiry.add(time_after_expiry));\n }\n // Otherwise, it needs to just be 1x\n else {\n lock_multiplier = MULTIPLIER_PRECISION;\n }\n }\n\n uint256 liquidity = thisStake.liquidity;\n uint256 combined_boosted_amount = liquidity.mul(lock_multiplier).div(MULTIPLIER_PRECISION);\n new_combined_weight = new_combined_weight.add(combined_boosted_amount);\n }\n }\n\n // All the locked stakes for a given account\n function lockedStakesOf(address account) external view returns (LockedStake[] memory) {\n return lockedStakes[account];\n }\n\n // All the locked stakes for a given account\n function getRewardSymbols() external view returns (string[] memory) {\n return rewardSymbols;\n }\n\n // All the reward tokens\n function getAllRewardTokens() external view returns (address[] memory) {\n return rewardTokens;\n }\n\n // All the reward rates\n function getAllRewardRates() external view returns (uint256[] memory) {\n return rewardRates;\n }\n\n // Multiplier amount, given the length of the lock\n function lockMultiplier(uint256 secs) public view returns (uint256) {\n uint256 lock_multiplier = uint256(MULTIPLIER_PRECISION).add(\n secs.mul(lock_max_multiplier.sub(MULTIPLIER_PRECISION)).div(lock_time_for_max_multiplier)\n );\n if (lock_multiplier > lock_max_multiplier) lock_multiplier = lock_max_multiplier;\n return lock_multiplier;\n }\n\n // Last time the reward was applicable\n function lastTimeRewardApplicable() internal view returns (uint256) {\n return min(block.timestamp, periodFinish);\n }\n\n // Amount of reward tokens per LP token\n function rewardsPerToken() public view returns (uint256[] memory newRewardsPerTokenStored) {\n if (_total_liquidity_locked == 0 || _total_combined_weight == 0) {\n return rewardsPerTokenStored;\n } else {\n newRewardsPerTokenStored = new uint256[](rewardTokens.length);\n for (uint256 i = 0; i < rewardsPerTokenStored.length; i++) {\n newRewardsPerTokenStored[i] = rewardsPerTokenStored[i].add(\n lastTimeRewardApplicable().sub(lastUpdateTime).mul(rewardRates[i]).mul(1e18).div(_total_combined_weight)\n );\n }\n return newRewardsPerTokenStored;\n }\n }\n\n // Amount of reward tokens an account has earned / accrued\n // Note: In the edge-case of one of the account's stake expiring since the last claim, this will\n // return a slightly inflated number\n function earned(address account) public view returns (uint256[] memory new_earned) {\n uint256[] memory reward_arr = rewardsPerToken();\n new_earned = new uint256[](rewardTokens.length);\n\n if (_combined_weights[account] == 0) {\n for (uint256 i = 0; i < rewardTokens.length; i++) {\n new_earned[i] = 0;\n }\n } else {\n for (uint256 i = 0; i < rewardTokens.length; i++) {\n new_earned[i] = (_combined_weights[account])\n .mul(reward_arr[i].sub(userRewardsPerTokenPaid[account][i]))\n .div(1e18)\n .add(rewards[account][i]);\n }\n }\n }\n\n // Total reward tokens emitted in the given period\n function getRewardForDuration() external view returns (uint256[] memory rewards_per_duration_arr) {\n rewards_per_duration_arr = new uint256[](rewardRates.length);\n\n for (uint256 i = 0; i < rewardRates.length; i++) {\n rewards_per_duration_arr[i] = rewardRates[i].mul(rewardsDuration);\n }\n }\n\n // See if the caller_addr is a manager for the reward token\n function isTokenManagerFor(address caller_addr, address reward_token_addr) public view returns (bool) {\n if (caller_addr == owner()) return true;\n // Contract owner\n else if (rewardManagers[reward_token_addr] == caller_addr) return true; // Reward manager\n return false;\n }\n\n /* ========== MUTATIVE FUNCTIONS ========== */\n\n function _updateRewardAndBalance(address account, bool sync_too) internal {\n // Need to retro-adjust some things if the period hasn't been renewed, then start a new one\n if (sync_too) {\n sync();\n }\n\n if (account != address(0)) {\n // To keep the math correct, the user's combined weight must be recomputed\n (uint256 old_combined_weight, uint256 new_combined_weight) = calcCurCombinedWeight(account);\n\n // Calculate the earnings first\n _syncEarned(account);\n\n // Update the user's and the global combined weights\n if (new_combined_weight >= old_combined_weight) {\n uint256 weight_diff = new_combined_weight.sub(old_combined_weight);\n _total_combined_weight = _total_combined_weight.add(weight_diff);\n _combined_weights[account] = old_combined_weight.add(weight_diff);\n } else {\n uint256 weight_diff = old_combined_weight.sub(new_combined_weight);\n _total_combined_weight = _total_combined_weight.sub(weight_diff);\n _combined_weights[account] = old_combined_weight.sub(weight_diff);\n }\n }\n }\n\n function _syncEarned(address account) internal {\n if (account != address(0)) {\n // Calculate the earnings\n uint256[] memory earned_arr = earned(account);\n\n // Update the rewards array\n for (uint256 i = 0; i < earned_arr.length; i++) {\n rewards[account][i] = earned_arr[i];\n }\n\n // Update the rewards paid array\n for (uint256 i = 0; i < earned_arr.length; i++) {\n userRewardsPerTokenPaid[account][i] = rewardsPerTokenStored[i];\n }\n }\n }\n\n // Two different stake functions are needed because of delegateCall and msg.sender issues\n function stakeLocked(uint256 liquidity, uint256 secs) public nonReentrant {\n _stakeLocked(msg.sender, msg.sender, liquidity, secs, block.timestamp);\n }\n\n // If this were not internal, and source_address had an infinite approve, this could be exploitable\n // (pull funds from source_address and stake for an arbitrary staker_address)\n function _stakeLocked(\n address staker_address,\n address source_address,\n uint256 liquidity,\n uint256 secs,\n uint256 start_timestamp\n ) internal updateRewardAndBalance(staker_address, true) {\n require(!stakingPaused, 'Staking paused');\n require(liquidity > 0, 'Must stake more than zero');\n require(greylist[staker_address] == false, 'Address has been greylisted');\n require(secs >= lock_time_min, 'Minimum stake time not met');\n require(secs <= lock_time_for_max_multiplier, 'Trying to lock for too long');\n\n uint256 lock_multiplier = lockMultiplier(secs);\n bytes32 kek_id = keccak256(\n abi.encodePacked(staker_address, start_timestamp, liquidity, _locked_liquidity[staker_address])\n );\n lockedStakes[staker_address].push(\n LockedStake(kek_id, start_timestamp, liquidity, start_timestamp.add(secs), lock_multiplier)\n );\n\n // Pull the tokens from the source_address\n TransferHelper.safeTransferFrom(address(stakingToken), source_address, address(this), liquidity);\n\n // Update liquidities\n _total_liquidity_locked = _total_liquidity_locked.add(liquidity);\n _locked_liquidity[staker_address] = _locked_liquidity[staker_address].add(liquidity);\n\n // Need to call to update the combined weights\n _updateRewardAndBalance(staker_address, false);\n\n // Needed for edge case if the staker only claims once, and after the lock expired\n if (lastRewardClaimTime[staker_address] == 0) lastRewardClaimTime[staker_address] = block.timestamp;\n\n emit StakeLocked(staker_address, liquidity, secs, kek_id, source_address);\n }\n\n // Two different withdrawLocked functions are needed because of delegateCall and msg.sender issues\n function withdrawLocked(bytes32 kek_id) public nonReentrant {\n require(withdrawalsPaused == false, 'Withdrawals paused');\n _withdrawLocked(msg.sender, msg.sender, kek_id);\n }\n\n // No withdrawer == msg.sender check needed since this is only internally callable and the checks are done in the wrapper\n // functions like withdraw()\n function _withdrawLocked(address staker_address, address destination_address, bytes32 kek_id) internal {\n // Collect rewards first and then update the balances\n _getReward(staker_address, destination_address);\n\n LockedStake memory thisStake;\n thisStake.liquidity = 0;\n uint256 theArrayIndex;\n for (uint256 i = 0; i < lockedStakes[staker_address].length; i++) {\n if (kek_id == lockedStakes[staker_address][i].kek_id) {\n thisStake = lockedStakes[staker_address][i];\n theArrayIndex = i;\n break;\n }\n }\n require(thisStake.kek_id == kek_id, 'Stake not found');\n require(block.timestamp >= thisStake.ending_timestamp || stakesUnlocked == true, 'Stake is still locked!');\n\n uint256 liquidity = thisStake.liquidity;\n\n if (liquidity > 0) {\n // Update liquidities\n _total_liquidity_locked = _total_liquidity_locked.sub(liquidity);\n _locked_liquidity[staker_address] = _locked_liquidity[staker_address].sub(liquidity);\n\n // Remove the stake from the array\n delete lockedStakes[staker_address][theArrayIndex];\n\n // Need to call to update the combined weights\n _updateRewardAndBalance(staker_address, false);\n\n // Give the tokens to the destination_address\n // Should throw if insufficient balance\n stakingToken.transfer(destination_address, liquidity);\n\n emit WithdrawLocked(staker_address, liquidity, kek_id, destination_address);\n }\n }\n\n // Two different getReward functions are needed because of delegateCall and msg.sender issues\n function getReward() external nonReentrant returns (uint256[] memory) {\n require(rewardsCollectionPaused == false, 'Rewards collection paused');\n return _getReward(msg.sender, msg.sender);\n }\n\n // No withdrawer == msg.sender check needed since this is only internally callable\n function _getReward(\n address rewardee,\n address destination_address\n ) internal updateRewardAndBalance(rewardee, true) returns (uint256[] memory rewards_before) {\n // Update the rewards array and distribute rewards\n rewards_before = new uint256[](rewardTokens.length);\n\n for (uint256 i = 0; i < rewardTokens.length; i++) {\n rewards_before[i] = rewards[rewardee][i];\n rewards[rewardee][i] = 0;\n IERC20(rewardTokens[i]).transfer(destination_address, rewards_before[i]);\n emit RewardPaid(rewardee, rewards_before[i], rewardTokens[i], destination_address);\n }\n\n lastRewardClaimTime[rewardee] = block.timestamp;\n }\n\n // If the period expired, renew it\n function retroCatchUp() internal {\n // Failsafe check\n require(block.timestamp > periodFinish, 'Period has not expired yet!');\n\n // Ensure the provided reward amount is not more than the balance in the contract.\n // This keeps the reward rate in the right range, preventing overflows due to\n // very high values of rewardRate in the earned and rewardsPerToken functions;\n // Reward + leftover must be less than 2^256 / 10^18 to avoid overflow.\n uint256 num_periods_elapsed = uint256(block.timestamp.sub(periodFinish)) / rewardsDuration; // Floor division to the nearest period\n\n // Make sure there are enough tokens to renew the reward period\n for (uint256 i = 0; i < rewardTokens.length; i++) {\n require(\n rewardRates[i].mul(rewardsDuration).mul(num_periods_elapsed + 1) <=\n IERC20(rewardTokens[i]).balanceOf(address(this)),\n string(abi.encodePacked('Not enough reward tokens available: ', rewardTokens[i]))\n );\n }\n\n // uint256 old_lastUpdateTime = lastUpdateTime;\n // uint256 new_lastUpdateTime = block.timestamp;\n\n // lastUpdateTime = periodFinish;\n periodFinish = periodFinish.add((num_periods_elapsed.add(1)).mul(rewardsDuration));\n\n _updateStoredRewardsAndTime();\n\n emit RewardsPeriodRenewed(address(stakingToken));\n }\n\n function _updateStoredRewardsAndTime() internal {\n // Get the rewards\n uint256[] memory rewards_per_token = rewardsPerToken();\n\n // Update the rewardsPerTokenStored\n for (uint256 i = 0; i < rewardsPerTokenStored.length; i++) {\n rewardsPerTokenStored[i] = rewards_per_token[i];\n }\n\n // Update the last stored time\n lastUpdateTime = lastTimeRewardApplicable();\n }\n\n function sync() public {\n if (block.timestamp > periodFinish) {\n retroCatchUp();\n } else {\n _updateStoredRewardsAndTime();\n }\n }\n\n /* ========== RESTRICTED FUNCTIONS ========== */\n\n // Added to support recovering LP Rewards and other mistaken tokens from other systems to be distributed to holders\n function recoverERC20(address tokenAddress, uint256 tokenAmount) external onlyTknMgrs(tokenAddress) {\n // Cannot rug the staking / LP tokens\n require(tokenAddress != address(stakingToken), 'Cannot rug staking / LP tokens');\n\n // Check if the desired token is a reward token\n bool isRewardToken = false;\n for (uint256 i = 0; i < rewardTokens.length; i++) {\n if (rewardTokens[i] == tokenAddress) {\n isRewardToken = true;\n break;\n }\n }\n\n // Only the reward managers can take back their reward tokens\n if (isRewardToken && rewardManagers[tokenAddress] == msg.sender) {\n IERC20(tokenAddress).transfer(msg.sender, tokenAmount);\n emit Recovered(msg.sender, tokenAddress, tokenAmount);\n return;\n }\n // Other tokens, like airdrops or accidental deposits, can be withdrawn by the owner\n else if (!isRewardToken && (msg.sender == owner())) {\n IERC20(tokenAddress).transfer(msg.sender, tokenAmount);\n emit Recovered(msg.sender, tokenAddress, tokenAmount);\n return;\n }\n // If none of the above conditions are true\n else {\n revert('No valid tokens to recover');\n }\n }\n\n function setRewardsDuration(uint256 _rewardsDuration) external onlyOwner {\n require(_rewardsDuration >= 86400, 'Rewards duration too short');\n require(periodFinish == 0 || block.timestamp > periodFinish, 'Reward period incomplete');\n rewardsDuration = _rewardsDuration;\n emit RewardsDurationUpdated(rewardsDuration);\n }\n\n function setMultipliers(uint256 _lock_max_multiplier) external onlyOwner {\n require(_lock_max_multiplier >= uint256(1e18), 'Multiplier must be greater than or equal to 1e18');\n lock_max_multiplier = _lock_max_multiplier;\n emit LockedStakeMaxMultiplierUpdated(lock_max_multiplier);\n }\n\n function setLockedStakeTimeForMinAndMaxMultiplier(\n uint256 _lock_time_for_max_multiplier,\n uint256 _lock_time_min\n ) external onlyOwner {\n require(_lock_time_for_max_multiplier >= 1, 'Mul max time must be >= 1');\n require(_lock_time_min >= 1, 'Mul min time must be >= 1');\n\n lock_time_for_max_multiplier = _lock_time_for_max_multiplier;\n lock_time_min = _lock_time_min;\n\n emit LockedStakeTimeForMaxMultiplier(lock_time_for_max_multiplier);\n emit LockedStakeMinTime(_lock_time_min);\n }\n\n function greylistAddress(address _address) external onlyOwner {\n greylist[_address] = !(greylist[_address]);\n }\n\n function unlockStakes() external onlyOwner {\n stakesUnlocked = !stakesUnlocked;\n }\n\n function toggleStaking() external onlyOwner {\n stakingPaused = !stakingPaused;\n }\n\n function toggleWithdrawals() external onlyOwner {\n withdrawalsPaused = !withdrawalsPaused;\n }\n\n function toggleRewardsCollection() external onlyOwner {\n rewardsCollectionPaused = !rewardsCollectionPaused;\n }\n\n // The owner or the reward token managers can set reward rates\n function setRewardRate(\n address reward_token_address,\n uint256 new_rate,\n bool sync_too\n ) external onlyTknMgrs(reward_token_address) {\n rewardRates[rewardTokenAddrToIdx[reward_token_address]] = new_rate;\n\n if (sync_too) {\n sync();\n }\n }\n\n // The owner or the reward token managers can change managers\n function changeTokenManager(\n address reward_token_address,\n address new_manager_address\n ) external onlyTknMgrs(reward_token_address) {\n rewardManagers[reward_token_address] = new_manager_address;\n }\n\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /* ========== EVENTS ========== */\n\n event StakeLocked(address indexed user, uint256 amount, uint256 secs, bytes32 kek_id, address source_address);\n event WithdrawLocked(address indexed user, uint256 amount, bytes32 kek_id, address destination_address);\n event RewardPaid(address indexed user, uint256 reward, address token_address, address destination_address);\n event RewardsDurationUpdated(uint256 newDuration);\n event Recovered(address destination_address, address token, uint256 amount);\n event RewardsPeriodRenewed(address token);\n event LockedStakeMaxMultiplierUpdated(uint256 multiplier);\n event LockedStakeTimeForMaxMultiplier(uint256 secs);\n event LockedStakeMinTime(uint256 secs);\n}\n" }, "@openzeppelin/contracts/security/ReentrancyGuard.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n" }, "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) 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(\n IERC20 token,\n address spender,\n uint256 value\n ) 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 function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" }, "@openzeppelin/contracts/utils/math/SafeMath.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol)\n\npragma solidity ^0.8.0;\n\n// CAUTION\n// This version of SafeMath should only be used with Solidity 0.8 or later,\n// because it relies on the compiler's built in overflow checks.\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations.\n *\n * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler\n * now has built in overflow checking.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n uint256 c = a + b;\n if (c < a) return (false, 0);\n return (true, c);\n }\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n if (b > a) return (false, 0);\n return (true, a - b);\n }\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) return (true, 0);\n uint256 c = a * b;\n if (c / a != b) return (false, 0);\n return (true, c);\n }\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n return a + b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n return a - b;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n return a * b;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator.\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n return a % b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {trySub}.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n unchecked {\n require(b <= a, errorMessage);\n return a - b;\n }\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n unchecked {\n require(b > 0, errorMessage);\n return a / b;\n }\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting with custom message when dividing by zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryMod}.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n unchecked {\n require(b > 0, errorMessage);\n return a % b;\n }\n }\n}\n" }, "@openzeppelin/contracts/access/Ownable.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" }, "@openzeppelin/contracts/utils/Address.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return 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(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (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/token/ERC20/extensions/draft-IERC20Permit.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" }, "contracts/CToken/CEther.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\nimport './CToken.sol';\nimport './Interfaces/ICErc20.sol';\nimport '@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol';\n\n/**\n * @title Compound's CEther Contract\n * @notice CToken which wraps Ether\n * @author Compound\n */\ncontract CEther is CToken, Initializable {\n using CarefulMath for uint256;\n\n /**\n * @notice Construct a new CEther money market\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ 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 */\n function initialize(\n address comptroller_,\n address interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_,\n uint256 discountRateMantissa_\n ) public initializer {\n super.initialize(\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n true,\n admin_,\n discountRateMantissa_\n );\n\n isCEther = true;\n }\n\n /*** User Interface ***/\n\n /**\n * @notice Sender supplies assets into the market and receives cTokens in exchange\n * @dev Reverts upon any failure\n */\n function mint() external payable {\n (uint256 err, ) = mintInternal(msg.value);\n requireNoError(err, 'mint failed');\n }\n\n /**\n * @notice Sender redeems cTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemTokens The number of cTokens to redeem into underlying\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function redeem(uint256 redeemTokens) external returns (uint256) {\n return redeemInternal(redeemTokens);\n }\n\n /**\n * @notice Sender redeems cTokens in exchange for a specified amount of underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemAmount The amount of underlying to redeem\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function redeemUnderlying(uint256 redeemAmount) external returns (uint256) {\n return redeemUnderlyingInternal(redeemAmount);\n }\n\n /**\n * @notice Sender borrows assets from the protocol to their own address\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function borrow(uint256 borrowAmount) external returns (uint256) {\n return borrowInternal(borrowAmount);\n }\n\n /**\n * @notice Sender repays their own borrow\n * @dev Reverts upon any failure\n */\n function repayBorrow() external payable {\n (uint256 err, ) = repayBorrowInternal(msg.value);\n requireNoError(err, 'repayBorrow failed');\n }\n\n /**\n * @notice Sender repays a borrow belonging to borrower\n * @dev Reverts upon any failure\n * @param borrower the account with the debt being payed off\n */\n function repayBorrowBehalf(address borrower) external payable {\n uint256 received = msg.value;\n uint256 borrows = CEther(payable(this)).borrowBalanceCurrent(borrower);\n if (received > borrows) {\n payable(msg.sender).transfer(received - borrows);\n }\n (uint256 err, ) = repayBorrowBehalfInternal(borrower, borrows);\n requireNoError(err, 'repayBorrowBehalf failed');\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @dev Reverts upon any failure\n * @param borrower The borrower of this cToken to be liquidated\n * @param cTokenCollateral The market in which to seize collateral from the borrower\n */\n function liquidateBorrow(address borrower, address cTokenCollateral) external payable {\n (uint256 err, ) = liquidateBorrowInternal(borrower, msg.value, cTokenCollateral);\n requireNoError(err, 'liquidateBorrow failed');\n }\n\n /**\n * @notice The sender adds to reserves.\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _addReserves() external payable returns (uint256) {\n return _addReservesInternal(msg.value);\n }\n\n /**\n * @notice Send Ether to CEther to mint\n */\n receive() external payable {\n (uint256 err, ) = mintInternal(msg.value);\n requireNoError(err, 'mint failed');\n }\n\n /*** Safe Token ***/\n\n /**\n * @notice Gets balance of this contract in terms of Ether, before this message\n * @dev This excludes the value of the current message, if any\n * @return The quantity of Ether owned by this contract\n */\n function getCashPrior() internal view override returns (uint256) {\n (MathError err, uint256 startingBalance) = address(this).balance.subUInt(msg.value);\n require(err == MathError.NO_ERROR);\n return startingBalance;\n }\n\n /**\n * @notice Perform the actual transfer in, which is a no-op\n * @param from Address sending the Ether\n * @param amount Amount of Ether being sent\n * @return The actual amount of Ether transferred\n */\n function doTransferIn(address from, uint256 amount) internal override returns (uint256) {\n // Sanity checks\n require(msg.sender == from, 'sender mismatch');\n require(msg.value >= amount, 'value mismatch');\n return amount;\n }\n\n function doTransferOut(address payable to, uint256 amount) internal override {\n /* Send the Ether, with minimal gas and revert on failure */\n to.transfer(amount);\n }\n\n function requireNoError(uint256 errCode, string memory message) internal pure {\n if (errCode == uint256(Error.NO_ERROR)) {\n return;\n }\n\n bytes memory fullMessage = new bytes(bytes(message).length + 5);\n uint256 i;\n\n for (i = 0; i < bytes(message).length; i++) {\n fullMessage[i] = bytes(message)[i];\n }\n\n fullMessage[i + 0] = bytes1(uint8(32));\n fullMessage[i + 1] = bytes1(uint8(40));\n fullMessage[i + 2] = bytes1(uint8(48 + (errCode / 10)));\n fullMessage[i + 3] = bytes1(uint8(48 + (errCode % 10)));\n fullMessage[i + 4] = bytes1(uint8(41));\n\n require(errCode == uint256(Error.NO_ERROR), string(fullMessage));\n }\n}\n" }, "contracts/ERC20/ERC20MinterBurnerPauser.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\nimport \"@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol\";\n\n/**\n * @dev {ERC20} token, including:\n *\n * - ability for holders to burn (destroy) their tokens\n * - a minter role that allows for token minting (creation)\n * - a pauser role that allows to stop all token transfers\n *\n * This contract uses {AccessControl} to lock permissioned functions using the\n * different roles - head to its documentation for details.\n *\n * The account that deploys the contract will be granted the minter and pauser\n * roles, as well as the default admin role, which will let it grant both minter\n * and pauser roles to aother accounts\n */\ncontract ERC20MinterBurnerPauser is ERC20PresetMinterPauser {\n uint8 private immutable decimals_;\n\n constructor(\n string memory _name,\n string memory _symbol,\n uint8 _decimals\n ) ERC20PresetMinterPauser(_name, _symbol) {\n decimals_ = _decimals;\n }\n\n function decimals() public view virtual override returns (uint8) {\n return decimals_;\n }\n}\n" }, "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/presets/ERC20PresetMinterPauser.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20.sol\";\nimport \"../extensions/ERC20Burnable.sol\";\nimport \"../extensions/ERC20Pausable.sol\";\nimport \"../../../access/AccessControlEnumerable.sol\";\nimport \"../../../utils/Context.sol\";\n\n/**\n * @dev {ERC20} token, including:\n *\n * - ability for holders to burn (destroy) their tokens\n * - a minter role that allows for token minting (creation)\n * - a pauser role that allows to stop all token transfers\n *\n * This contract uses {AccessControl} to lock permissioned functions using the\n * different roles - head to its documentation for details.\n *\n * The account that deploys the contract will be granted the minter and pauser\n * roles, as well as the default admin role, which will let it grant both minter\n * and pauser roles to other accounts.\n *\n * _Deprecated in favor of https://wizard.openzeppelin.com/[Contracts Wizard]._\n */\ncontract ERC20PresetMinterPauser is Context, AccessControlEnumerable, ERC20Burnable, ERC20Pausable {\n bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n bytes32 public constant PAUSER_ROLE = keccak256(\"PAUSER_ROLE\");\n\n /**\n * @dev Grants `DEFAULT_ADMIN_ROLE`, `MINTER_ROLE` and `PAUSER_ROLE` to the\n * account that deploys the contract.\n *\n * See {ERC20-constructor}.\n */\n constructor(string memory name, string memory symbol) ERC20(name, symbol) {\n _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());\n\n _setupRole(MINTER_ROLE, _msgSender());\n _setupRole(PAUSER_ROLE, _msgSender());\n }\n\n /**\n * @dev Creates `amount` new tokens for `to`.\n *\n * See {ERC20-_mint}.\n *\n * Requirements:\n *\n * - the caller must have the `MINTER_ROLE`.\n */\n function mint(address to, uint256 amount) public virtual {\n require(hasRole(MINTER_ROLE, _msgSender()), \"ERC20PresetMinterPauser: must have minter role to mint\");\n _mint(to, amount);\n }\n\n /**\n * @dev Pauses all token transfers.\n *\n * See {ERC20Pausable} and {Pausable-_pause}.\n *\n * Requirements:\n *\n * - the caller must have the `PAUSER_ROLE`.\n */\n function pause() public virtual {\n require(hasRole(PAUSER_ROLE, _msgSender()), \"ERC20PresetMinterPauser: must have pauser role to pause\");\n _pause();\n }\n\n /**\n * @dev Unpauses all token transfers.\n *\n * See {ERC20Pausable} and {Pausable-_unpause}.\n *\n * Requirements:\n *\n * - the caller must have the `PAUSER_ROLE`.\n */\n function unpause() public virtual {\n require(hasRole(PAUSER_ROLE, _msgSender()), \"ERC20PresetMinterPauser: must have pauser role to unpause\");\n _unpause();\n }\n\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual override(ERC20, ERC20Pausable) {\n super._beforeTokenTransfer(from, to, amount);\n }\n}\n" }, "@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.2) (token/ERC20/extensions/ERC20Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20.sol\";\nimport \"../../../security/Pausable.sol\";\n\n/**\n * @dev ERC20 token with pausable token transfers, minting and burning.\n *\n * Useful for scenarios such as preventing trades until the end of an evaluation\n * period, or having an emergency switch for freezing all token transfers in the\n * event of a large bug.\n *\n * IMPORTANT: This contract does not include public pause and unpause functions. In\n * addition to inheriting this contract, you must define both functions, invoking the\n * {Pausable-_pause} and {Pausable-_unpause} internal functions, with appropriate\n * access control, e.g. using {AccessControl} or {Ownable}. Not doing so will\n * make the contract unpausable.\n */\nabstract contract ERC20Pausable is ERC20, Pausable {\n /**\n * @dev See {ERC20-_beforeTokenTransfer}.\n *\n * Requirements:\n *\n * - the contract must not be paused.\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual override {\n super._beforeTokenTransfer(from, to, amount);\n\n require(!paused(), \"ERC20Pausable: token transfer while paused\");\n }\n}\n" }, "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Burnable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20.sol\";\nimport \"../../../utils/Context.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20Burnable is Context, ERC20 {\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n _spendAllowance(account, _msgSender(), amount);\n _burn(account, amount);\n }\n}\n" }, "contracts/InterestRateModel/suTokenInterestModel.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\nimport './InterestRateModel.sol';\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\n\n/**\n * @title Compound's JumpRateModel Contract\n * @author Compound\n */\ncontract SuTokenRateModel is InterestRateModel {\n using SafeMath for uint256;\n\n address public owner;\n /**\n * @notice The multiplier of utilization rate that gives the slope of the interest rate\n */\n uint256 public borrowRate;\n\n /**\n * @notice The base interest rate which is the y-intercept when utilization rate is 0\n */\n uint256 public supplyRate;\n\n modifier onlyOwner() {\n require(msg.sender == owner, 'ONLY OWNER');\n _;\n }\n\n constructor(uint256 initBorrowRate, uint256 initSupplyRate) {\n borrowRate = initBorrowRate;\n supplyRate = initSupplyRate;\n owner = msg.sender;\n }\n\n function changeOwner(address owner_) public onlyOwner {\n require(owner_ != address(0), 'Address is Zero!');\n owner = owner_;\n }\n\n function setBorrowRate(uint256 rate) public onlyOwner {\n borrowRate = rate;\n }\n\n function setSupplyRate(uint256 rate) public onlyOwner {\n supplyRate = rate;\n }\n\n /**\n * @notice Calculates the current borrow rate per block, with the error code expected by the market\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @return The borrow rate percentage per block as a mantissa (scaled by 1e18)\n */\n function getBorrowRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves\n ) public view override returns (uint256) {\n cash;\n borrows;\n reserves;\n return borrowRate;\n }\n\n /**\n * @notice Calculates the current supply rate per block\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @param reserveFactorMantissa The current reserve factor for the market\n * @return The supply rate percentage per block as a mantissa (scaled by 1e18)\n */\n function getSupplyRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 reserveFactorMantissa\n ) public view override returns (uint256) {\n cash;\n borrows;\n reserves;\n reserveFactorMantissa;\n return supplyRate;\n }\n}\n" }, "contracts/InterestRateModel/InterestRateModel.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\n/**\n * @title Compound's InterestRateModel Interface\n * @author Compound\n */\nabstract contract InterestRateModel {\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\n bool public constant isInterestRateModel = true;\n\n /**\n * @notice Calculates the current borrow interest rate per block\n * @param cash The total amount of cash the market has\n * @param borrows The total amount of borrows the market has outstanding\n * @param reserves The total amount of reserves the market has\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\n */\n function getBorrowRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves\n ) external virtual view returns (uint256);\n\n /**\n * @notice Calculates the current supply interest rate per block\n * @param cash The total amount of cash the market has\n * @param borrows The total amount of borrows the market has outstanding\n * @param reserves The total amount of reserves the market has\n * @param reserveFactorMantissa The current reserve factor the market has\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\n */\n function getSupplyRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 reserveFactorMantissa\n ) external virtual view returns (uint256);\n}\n" }, "contracts/InterestRateModel/JumpRateModel.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.19;\n\nimport './InterestRateModel.sol';\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\n\n/**\n * @title Compound's JumpRateModel Contract\n * @author Compound\n */\ncontract JumpRateModel is InterestRateModel {\n using SafeMath for uint256;\n\n event NewInterestParams(\n uint256 baseRatePerBlock,\n uint256 multiplierPerBlock,\n uint256 jumpMultiplierPerBlock,\n uint256 kink\n );\n\n /**\n * @notice The approximate number of blocks per year that is assumed by the interest rate model\n */\n uint256 public constant blocksPerYear = 2102400;\n\n /**\n * @notice The multiplier of utilization rate that gives the slope of the interest rate\n */\n uint256 public multiplierPerBlock;\n\n /**\n * @notice The base interest rate which is the y-intercept when utilization rate is 0\n */\n uint256 public baseRatePerBlock;\n\n /**\n * @notice The multiplierPerBlock after hitting a specified utilization point\n */\n uint256 public jumpMultiplierPerBlock;\n\n /**\n * @notice The utilization point at which the jump multiplier is applied\n */\n uint256 public kink;\n\n /**\n * @notice Construct an interest rate model\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by 1e18)\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by 1e18)\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\n * @param kink_ The utilization point at which the jump multiplier is applied\n */\n constructor(\n uint256 baseRatePerYear,\n uint256 multiplierPerYear,\n uint256 jumpMultiplierPerYear,\n uint256 kink_\n ) {\n baseRatePerBlock = baseRatePerYear.div(blocksPerYear);\n multiplierPerBlock = multiplierPerYear.div(blocksPerYear);\n jumpMultiplierPerBlock = jumpMultiplierPerYear.div(blocksPerYear);\n kink = kink_;\n\n emit NewInterestParams(baseRatePerBlock, multiplierPerBlock, jumpMultiplierPerBlock, kink);\n }\n\n /**\n * @notice Calculates the utilization rate of the market: `borrows / (cash + borrows - reserves)`\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market (currently unused)\n * @return The utilization rate as a mantissa between [0, 1e18]\n */\n function utilizationRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves\n ) public pure returns (uint256) {\n // Utilization rate is 0 when there are no borrows\n if (borrows == 0) {\n return 0;\n }\n\n return borrows.mul(1e18).div(cash.add(borrows).sub(reserves));\n }\n\n /**\n * @notice Calculates the current borrow rate per block, with the error code expected by the market\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @return The borrow rate percentage per block as a mantissa (scaled by 1e18)\n */\n function getBorrowRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves\n ) public view override returns (uint256) {\n uint256 util = utilizationRate(cash, borrows, reserves);\n\n if (util <= kink) {\n return util.mul(multiplierPerBlock).div(1e18).add(baseRatePerBlock);\n } else {\n uint256 normalRate = kink.mul(multiplierPerBlock).div(1e18).add(baseRatePerBlock);\n uint256 excessUtil = util.sub(kink);\n return excessUtil.mul(jumpMultiplierPerBlock).div(1e18).add(normalRate);\n }\n }\n\n /**\n * @notice Calculates the current supply rate per block\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @param reserveFactorMantissa The current reserve factor for the market\n * @return The supply rate percentage per block as a mantissa (scaled by 1e18)\n */\n function getSupplyRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 reserveFactorMantissa\n ) public view override returns (uint256) {\n uint256 oneMinusReserveFactor = uint256(1e18).sub(reserveFactorMantissa);\n uint256 borrowRate = getBorrowRate(cash, borrows, reserves);\n uint256 rateToPool = borrowRate.mul(oneMinusReserveFactor).div(1e18);\n return utilizationRate(cash, borrows, reserves).mul(rateToPool).div(1e18);\n }\n}\n" } }, "language": "Solidity" }