diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 57fbc27f7..09d5fb1f8 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -29,7 +29,7 @@ jobs: name: Test runs-on: ubuntu-22.04 env: - NODE_OPTIONS: --max-old-space-size=4096 + NODE_OPTIONS: --max-old-space-size=12288 steps: - uses: actions/checkout@v2 diff --git a/Dockerfile b/Dockerfile index 47cd88b23..9efce5794 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,7 @@ RUN wget https://github.com/ethereum/solidity/releases/download/v0.8.25/solc-sta RUN mkdir -p /usr/app WORKDIR /usr/app -ENV NODE_OPTIONS=--max-old-space-size=4096 +ENV NODE_OPTIONS=--max-old-space-size=8192 # First add deps RUN npm install -g yarn diff --git a/contracts/Comptroller.sol b/contracts/Comptroller.sol index 8d25f5ad4..ce979171c 100644 --- a/contracts/Comptroller.sol +++ b/contracts/Comptroller.sol @@ -5,14 +5,16 @@ import { Ownable2StepUpgradeable } from "@openzeppelin/contracts-upgradeable/acc import { ResilientOracleInterface } from "@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol"; import { AccessControlledV8 } from "@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol"; import { IPrime } from "@venusprotocol/venus-protocol/contracts/Tokens/Prime/Interfaces/IPrime.sol"; +import { IProtocolShareReserve } from "./Flashloan/interfaces/IProtocolShareReserve.sol"; -import { ComptrollerInterface, Action } from "./ComptrollerInterface.sol"; +import { ComptrollerInterface, VTokenInterface, Action } from "./ComptrollerInterface.sol"; import { ComptrollerStorage } from "./ComptrollerStorage.sol"; import { ExponentialNoError } from "./ExponentialNoError.sol"; import { VToken } from "./VToken.sol"; import { RewardsDistributor } from "./Rewards/RewardsDistributor.sol"; import { MaxLoopsLimitHelper } from "./MaxLoopsLimitHelper.sol"; import { ensureNonzeroAddress } from "./lib/validators.sol"; +import { IFlashLoanReceiver } from "./Flashloan/interfaces/IFlashloanReceiver.sol"; /** * @title Comptroller @@ -100,9 +102,13 @@ contract Comptroller is /// @notice Emitted when a market is unlisted event MarketUnlisted(address indexed vToken); + /// @notice Emitted when the borrowing or redeeming delegate rights are updated for an account event DelegateUpdated(address indexed approver, address indexed delegate, bool approved); + /// @notice Emitted When the flash loan is successfully executed + event FlashLoanExecuted(address receiver, VTokenInterface[] assets, uint256[] amounts); + /// @notice Thrown when collateral factor exceeds the upper bound error InvalidCollateralFactor(); @@ -163,6 +169,24 @@ contract Comptroller is /// @notice Thrown when collateral factor is not zero error CollateralFactorIsNotZero(); + /// @notice Thrown when the close factor is invalid + error InvalidCloseFactor(); + + /// @notice Thrown when the liquidation incentive is invalid + error InvalidLiquidationIncentive(); + + /// @notice Thrown when the VToken is invalid + error InvalidVToken(); + + /// @notice Thrown when the input is invalid + error InvalidInput(); + + /// @notice Thrown when the rewards distributor already exists + error RewardsDistributorAlreadyExists(); + + /// @notice Thrown when the market does not exist + error MarketNotExist(); + /** * @notice Thrown during the liquidation if user's total collateral amount is lower than * a predefined threshold. In this case only batch liquidations (either liquidateAccount @@ -199,6 +223,18 @@ contract Comptroller is /// @notice Thrown if delegate approval status is already set to the requested value error DelegationStatusUnchanged(); + /// @notice Thrown if invalid flashLoan params passed + error InvalidFlashLoanParams(); + + ///@notice Thrown if the flashLoan is not enabled for a particular market + error FlashLoanNotEnabled(address market); + + ///@notice Thrown if repayment amount is insufficient + error InsufficientReypaymentBalance(address tokenAddress); + + ///@notice Thrown if executeOperation failed + error ExecuteFlashLoanFailed(); + /// @param poolRegistry_ Pool registry address /// @custom:oz-upgrades-unsafe-allow constructor /// @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero @@ -919,6 +955,86 @@ contract Comptroller is } } + /** + * @notice Executes a flashLoan operation with the specified vTokens and underlyingAmounts. + * @dev Transfer the specified vTokens to the receiver contract and ensures that the total repayment (amount + fee) + * is returned by the receiver contract after the operation for each asset. The function performs checks to ensure the validity + * of parameters, that flashLoans are enabled for the given vTokens, and that the total repayment is sufficient. + * Reverts on invalid parameters, disabled flashLoans, or insufficient repayment. + * @param receiver The address of the contract that will receive the flashLoan and execute the operation. + * @param vTokens The addresses of the vTokens to be loaned. + * @param underlyingAmounts The underlyingAmounts of each asset to be loaned. + * @param param The bytes passed in the executeOperation call. + * @custom:requirements + * - `vTokens.length` must be equal to `underlyingAmounts.length`. + * - `vTokens.length` and `underlyingAmounts.length` must not be zero. + * - The `receiver` address must not be the zero address. + * - FlashLoans must be enabled for each asset. + * - The `receiver` contract must repay the loan with the appropriate fee. + * @custom:reverts + * - Reverts with `InvalidFlashLoanParams()` if parameter checks fail. + * - Reverts with `FlashLoanNotEnabled(asset)` if flashLoans are disabled for any of the requested vTokens. + * - Reverts with `ExecuteFlashLoanFailed` if the receiver contract fails to execute the operation. + * - Reverts with `InsufficientReypaymentBalance(asset)` if the repayment (amount + fee) is insufficient after the operation. + */ + function executeFlashLoan( + address receiver, + VTokenInterface[] calldata vTokens, + uint256[] calldata underlyingAmounts, + bytes calldata param + ) external override { + ensureNonzeroAddress(receiver); + // Asset and amount length must be equals and not be zero + if (vTokens.length != underlyingAmounts.length || vTokens.length == 0 || receiver == address(0)) { + revert InvalidFlashLoanParams(); + } + + uint256 len = vTokens.length; + uint256[] memory protocolFees = new uint256[](vTokens.length); + uint256[] memory supplierFees = new uint256[](vTokens.length); + uint256[] memory totalFees = new uint256[](vTokens.length); + uint256[] memory balanceAfterTransfer = new uint256[](len); + + for (uint256 j; j < len; ) { + (protocolFees[j], supplierFees[j]) = (vTokens[j]).calculateFlashLoanFee(underlyingAmounts[j]); + totalFees[j] = protocolFees[j] + supplierFees[j]; // Sum protocol and supplier fees + // Transfer the asset + (balanceAfterTransfer[j]) = (vTokens[j]).transferOutUnderlying(receiver, underlyingAmounts[j]); + + unchecked { + ++j; + } + } + + // Call the execute operation on receiver contract + if (!IFlashLoanReceiver(receiver).executeOperation(vTokens, underlyingAmounts, totalFees, msg.sender, param)) { + revert ExecuteFlashLoanFailed(); + } + + for (uint256 k; k < len; ) { + (vTokens[k]).transferInUnderlyingAndVerify( + receiver, + underlyingAmounts[k], + totalFees[k], + balanceAfterTransfer[k] + ); + (vTokens[k]).transferOutUnderlying(vTokens[k].protocolShareReserve(), protocolFees[k]); + + // Update protocol share reserve state + IProtocolShareReserve(vTokens[k].protocolShareReserve()).updateAssetsState( + address(vTokens[k].comptroller()), + address(vTokens[k].underlying()), + IProtocolShareReserve.IncomeType.FLASHLOAN + ); + + unchecked { + ++k; + } + } + + emit FlashLoanExecuted(receiver, vTokens, underlyingAmounts); + } + /** * @notice Liquidates all borrows of the borrower. Callable only if the collateral is less than * a predefined threshold, and the account collateral can be seized to cover all borrows. If @@ -983,7 +1099,9 @@ contract Comptroller is for (uint256 i; i < marketsCount; ++i) { (, uint256 borrowBalance, ) = _safeGetAccountSnapshot(borrowMarkets[i], borrower); - require(borrowBalance == 0, "Nonzero borrow balance after liquidation"); + if (borrowBalance > 0) { + revert NonzeroBorrowBalance(); + } } } @@ -995,8 +1113,10 @@ contract Comptroller is */ function setCloseFactor(uint256 newCloseFactorMantissa) external { _checkAccessAllowed("setCloseFactor(uint256)"); - require(MAX_CLOSE_FACTOR_MANTISSA >= newCloseFactorMantissa, "Close factor greater than maximum close factor"); - require(MIN_CLOSE_FACTOR_MANTISSA <= newCloseFactorMantissa, "Close factor smaller than minimum close factor"); + + if (MAX_CLOSE_FACTOR_MANTISSA < newCloseFactorMantissa || MIN_CLOSE_FACTOR_MANTISSA > newCloseFactorMantissa) { + revert InvalidCloseFactor(); + } uint256 oldCloseFactorMantissa = closeFactorMantissa; closeFactorMantissa = newCloseFactorMantissa; @@ -1071,7 +1191,9 @@ contract Comptroller is * @custom:access Controlled by AccessControlManager */ function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external { - require(newLiquidationIncentiveMantissa >= MANTISSA_ONE, "liquidation incentive should be greater than 1e18"); + if (newLiquidationIncentiveMantissa < MANTISSA_ONE) { + revert InvalidLiquidationIncentive(); + } _checkAccessAllowed("setLiquidationIncentive(uint256)"); @@ -1099,7 +1221,9 @@ contract Comptroller is revert MarketAlreadyListed(address(vToken)); } - require(vToken.isVToken(), "Comptroller: Invalid vToken"); // Sanity check to make sure its really a VToken + if (!vToken.isVToken()) { + revert InvalidVToken(); + } Market storage newMarket = markets[address(vToken)]; newMarket.isListed = true; @@ -1133,7 +1257,9 @@ contract Comptroller is uint256 numMarkets = vTokens.length; uint256 numBorrowCaps = newBorrowCaps.length; - require(numMarkets != 0 && numMarkets == numBorrowCaps, "invalid input"); + if (numMarkets == 0 || numMarkets != numBorrowCaps) { + revert InvalidInput(); + } _ensureMaxLoops(numMarkets); @@ -1157,8 +1283,9 @@ contract Comptroller is _checkAccessAllowed("setMarketSupplyCaps(address[],uint256[])"); uint256 vTokensCount = vTokens.length; - require(vTokensCount != 0, "invalid number of markets"); - require(vTokensCount == newSupplyCaps.length, "invalid number of markets"); + if (vTokensCount == 0 || vTokensCount != newSupplyCaps.length) { + revert InvalidInput(); + } _ensureMaxLoops(vTokensCount); @@ -1216,7 +1343,9 @@ contract Comptroller is * @custom:event Emits NewRewardsDistributor with distributor address */ function addRewardsDistributor(RewardsDistributor _rewardsDistributor) external onlyOwner { - require(!rewardsDistributorExists[address(_rewardsDistributor)], "already exists"); + if (rewardsDistributorExists[address(_rewardsDistributor)]) { + revert RewardsDistributorAlreadyExists(); + } uint256 rewardsDistributorsLen = rewardsDistributors.length; _ensureMaxLoops(rewardsDistributorsLen + 1); @@ -1554,7 +1683,10 @@ contract Comptroller is * @param paused The new paused state (true=paused, false=unpaused) */ function _setActionPaused(address market, Action action, bool paused) internal { - require(markets[market].isListed, "cannot pause a market that is not listed"); + if (!markets[market].isListed) { + revert MarketNotExist(); + } + _actionPaused[market][action] = paused; emit ActionPausedMarket(VToken(market), action, paused); } diff --git a/contracts/ComptrollerInterface.sol b/contracts/ComptrollerInterface.sol index 662a6aef9..2e6b5037e 100644 --- a/contracts/ComptrollerInterface.sol +++ b/contracts/ComptrollerInterface.sol @@ -5,6 +5,7 @@ import { ResilientOracleInterface } from "@venusprotocol/oracle/contracts/interf import { VToken } from "./VToken.sol"; import { RewardsDistributor } from "./Rewards/RewardsDistributor.sol"; +import { VTokenInterface } from "./VTokenInterfaces.sol"; enum Action { MINT, @@ -90,6 +91,13 @@ interface ComptrollerInterface { function preTransferHook(address vToken, address src, address dst, uint256 transferTokens) external; + function executeFlashLoan( + address receiver, + VTokenInterface[] calldata assets, + uint256[] calldata amounts, + bytes calldata param + ) external; + function isComptroller() external view returns (bool); /*** Liquidity/Liquidation Calculations ***/ diff --git a/contracts/ErrorReporter.sol b/contracts/ErrorReporter.sol index 080c0b73c..64b0e3d30 100644 --- a/contracts/ErrorReporter.sol +++ b/contracts/ErrorReporter.sol @@ -46,4 +46,9 @@ contract TokenErrorReporter { error ReduceReservesCashValidation(); error SetInterestRateModelFreshCheck(); + + error FlashLoanNotEnabled(address); + error ExecuteFlashLoanFailed(); + error InvalidComptroller(address comptroller); + error InsufficientReypaymentBalance(address tokenAddress); } diff --git a/contracts/Flashloan/interfaces/IFlashloanReceiver.sol b/contracts/Flashloan/interfaces/IFlashloanReceiver.sol new file mode 100644 index 000000000..e385f1374 --- /dev/null +++ b/contracts/Flashloan/interfaces/IFlashloanReceiver.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity 0.8.25; + +import { VTokenInterface } from "../../VTokenInterfaces.sol"; + +/// @title IFlashLoanReceiver +/// @notice Interface for flashLoan receiver contract, which execute custom logic with flash-borrowed assets. +/// @dev This interface defines the method that must be implemented by any contract wishing to interact with the flashLoan system. +/// Contracts must ensure they have the means to repay both the flashLoan amount and the associated premium (fee). +interface IFlashLoanReceiver { + /** + * @notice Executes an operation after receiving the flash-borrowed assets. + * @dev Implementation of this function must ensure the borrowed amount plus the premium (fee) is repaid within the same transaction. + * @param assets The addresses of the assets that were flash-borrowed. + * @param amounts The amounts of each of the flash-borrowed assets. + * @param premiums The premiums (fees) associated with each flash-borrowed asset. + * @param initiator The address that initiated the flashLoan operation. + * @param param Additional parameters encoded as bytes. These can be used to pass custom data to the receiver contract. + * @return True if the operation succeeds and the borrowed amount plus the premium is repaid, false otherwise. + */ + function executeOperation( + VTokenInterface[] calldata assets, + uint256[] calldata amounts, + uint256[] calldata premiums, + address initiator, + bytes calldata param + ) external returns (bool); +} diff --git a/contracts/Flashloan/interfaces/IFlashloanSimpleReceiver.sol b/contracts/Flashloan/interfaces/IFlashloanSimpleReceiver.sol new file mode 100644 index 000000000..a7c000dfb --- /dev/null +++ b/contracts/Flashloan/interfaces/IFlashloanSimpleReceiver.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity 0.8.25; + +interface IFlashLoanSimpleReceiver { + /** + * @notice Executes an operation after receiving the flash-borrowed asset + * @dev Ensure that the contract can return the debt + premium, e.g., has + * enough funds to repay and has to transfer the debt + premium to the VToken + * @param asset The address of the flash-borrowed asset + * @param amount The amount of the flash-borrowed asset + * @param premium The premium (fee) associated with flash-borrowed asset. + * @param initiator The address that initiated the flashLoan operation + * @param param The byte-encoded param passed when initiating the flashLoan + * @return True if the execution of the operation succeeds, false otherwise + */ + function executeOperation( + address asset, + uint256 amount, + uint256 premium, + address initiator, + bytes calldata param + ) external returns (bool); +} diff --git a/contracts/Flashloan/interfaces/IProtocolShareReserve.sol b/contracts/Flashloan/interfaces/IProtocolShareReserve.sol new file mode 100644 index 000000000..dfc90196b --- /dev/null +++ b/contracts/Flashloan/interfaces/IProtocolShareReserve.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.25; + +interface IProtocolShareReserve { + /// @notice it represents the type of vToken income + enum IncomeType { + SPREAD, + LIQUIDATION, + FLASHLOAN + } + + function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external; +} diff --git a/contracts/VToken.sol b/contracts/VToken.sol index 0e12b02f7..e8110b7da 100644 --- a/contracts/VToken.sol +++ b/contracts/VToken.sol @@ -5,7 +5,7 @@ import { Ownable2StepUpgradeable } from "@openzeppelin/contracts-upgradeable/acc import { IERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; import { SafeERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; import { AccessControlledV8 } from "@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol"; -import { IProtocolShareReserve } from "@venusprotocol/protocol-reserve/contracts/Interfaces/IProtocolShareReserve.sol"; +import { IProtocolShareReserve } from "./Flashloan/interfaces/IProtocolShareReserve.sol"; import { VTokenInterface } from "./VTokenInterfaces.sol"; import { ComptrollerInterface, ComptrollerViewInterface } from "./ComptrollerInterface.sol"; @@ -14,6 +14,7 @@ import { InterestRateModel } from "./InterestRateModel.sol"; import { ExponentialNoError } from "./ExponentialNoError.sol"; import { TimeManagerV8 } from "@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol"; import { ensureNonzeroAddress } from "./lib/validators.sol"; +import { IFlashLoanSimpleReceiver } from "./Flashloan/interfaces/IFlashloanSimpleReceiver.sol"; /** * @title VToken @@ -106,6 +107,9 @@ contract VToken is * @param accessControlManager_ AccessControlManager contract address * @param riskManagement Addresses of risk & income related contracts * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18) + * @param flashLoanEnabled_ Enable flashLoan or not for this market + * @param flashLoanProtocolFeeMantissa_ FlashLoan protocol fee mantissa, transferred to the protocol reserve + * @param flashLoanSupplierFeeMantissa_ FlashLoan supplier fee mantissa, transferred to suppliers * @custom:error ZeroAddressNotAllowed is thrown when admin address is zero * @custom:error ZeroAddressNotAllowed is thrown when shortfall contract address is zero * @custom:error ZeroAddressNotAllowed is thrown when protocol share reserve address is zero @@ -121,7 +125,10 @@ contract VToken is address admin_, address accessControlManager_, RiskManagementInit memory riskManagement, - uint256 reserveFactorMantissa_ + uint256 reserveFactorMantissa_, + bool flashLoanEnabled_, + uint256 flashLoanProtocolFeeMantissa_, + uint256 flashLoanSupplierFeeMantissa_ ) external initializer { ensureNonzeroAddress(admin_); @@ -137,7 +144,10 @@ contract VToken is admin_, accessControlManager_, riskManagement, - reserveFactorMantissa_ + reserveFactorMantissa_, + flashLoanEnabled_, + flashLoanProtocolFeeMantissa_, + flashLoanSupplierFeeMantissa_ ); } @@ -697,6 +707,168 @@ contract VToken is emit SweepToken(address(token)); } + /** + * @notice Transfers the underlying asset to the specified address. + * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying + * asset by calling the `_doTransferOut` internal function. + * @param to The address to which the underlying asset is to be transferred. + * @param amount The amount of the underlying asset to transfer. + * @custom:requirements + * - The caller must be the Comptroller contract. + * @custom:reverts + * - Reverts with "Only Comptroller" if the caller is not the Comptroller. + * @custom:event Emits TransferOutUnderlying event on successful transfer of amount to receiver + */ + function transferOutUnderlying( + address to, + uint256 amount + ) external override nonReentrant returns (uint256 balanceAfterTransfer) { + if (msg.sender != address(comptroller)) { + revert InvalidComptroller(address(comptroller)); + } + + flashLoanAmount += amount; + _doTransferOut(to, amount); + + balanceAfterTransfer = _getCashPrior(); + emit TransferOutUnderlying(underlying, to, amount); + } + + /** + * @notice Transfers the underlying asset from the specified address. + * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying + * asset by calling the `_doTransferIn` internal function. + * @param from The address from which the underlying asset is to be transferred. + * @param amount The amount of the underlying asset to transfer. + * @param fee Total fee applied on flashloan amount(protocol + supplier). + * @param balanceBefore The cash balance before the transfer. + * @custom:requirements + * - The caller must be the Comptroller contract. + * @custom:reverts + * - Reverts with "Only Comptroller" if the caller is not the Comptroller. + * @custom:event Emits TransferInUnderlyingAndVerify event on successful transfer of amount to receiver + */ + function transferInUnderlyingAndVerify( + address from, + uint256 amount, + uint256 fee, + uint256 balanceBefore + ) external override nonReentrant { + if (msg.sender != address(comptroller)) { + revert InvalidComptroller(address(comptroller)); + } + + uint256 repayment = amount + fee; + _doTransferIn(from, repayment); + flashLoanAmount -= amount; + + uint256 balanceAfter = _getCashPrior(); + + // balanceAfter should be greater than the fee calculated + if ((balanceAfter - balanceBefore) < repayment) { + revert InsufficientReypaymentBalance(underlying); + } + + emit TransferInUnderlyingAndVerify(underlying, from, repayment); + } + + /** + * @notice Executes a flashLoan operation. + * @dev Transfers the amount to the receiver contract and ensures that the total repayment (amount + fee) + * is returned by the receiver contract after the operation. The function performs checks to ensure the validity + * of parameters, that flashLoan is enabled for the given asset, and that the total repayment is sufficient. + * Reverts on invalid parameters, disabled flashLoans, or insufficient repayment. + * @param receiver The address of the contract that will receive the flashLoan and execute the operation. + * @param amount The amount of asset to be loaned. + * @param param The bytes passed in the executeOperation call. + * @custom:requirements + * - The `receiver` address must not be the zero address. + * - FlashLoans must be enabled for the asset. + * - The `receiver` contract must repay the loan with the appropriate fee. + * @custom:reverts + * - Reverts with `FlashLoanNotEnabled(asset)` if flashLoans are disabled for any of the requested assets. + * - Reverts with `ExecuteFlashLoanFailed` if the receiver contract fails to execute the operation. + * - Reverts with `InsufficientReypaymentBalance(asset)` if the repayment (amount + fee) is insufficient after the operation. + * @custom:event Emits FlashLoanExecuted event on success + */ + function executeFlashLoan( + address receiver, + uint256 amount, + bytes calldata param + ) external override nonReentrant returns (uint256) { + ensureNonzeroAddress(receiver); + + IFlashLoanSimpleReceiver receiverContract = IFlashLoanSimpleReceiver(msg.sender); + + flashLoanAmount += amount; + + // Transfer the underlying asset to the receiver. + _doTransferOut(receiver, amount); + + uint256 balanceBefore = _getCashPrior(); + (uint256 protocolFee, uint256 supplierFee) = calculateFlashLoanFee(amount); + + uint256 fee = protocolFee + supplierFee; + uint256 repayAmount = amount + fee; + + // Call the execute operation on receiver contract + if (!receiverContract.executeOperation(underlying, amount, fee, msg.sender, param)) { + revert ExecuteFlashLoanFailed(); + } + + _doTransferIn(receiver, repayAmount); + + flashLoanAmount -= amount; + + if ((_getCashPrior() - balanceBefore) < repayAmount) { + revert InsufficientReypaymentBalance(underlying); + } + + _doTransferOut(protocolShareReserve, protocolFee); + + IProtocolShareReserve(protocolShareReserve).updateAssetsState( + address(comptroller), + underlying, + IProtocolShareReserve.IncomeType.FLASHLOAN + ); + + emit FlashLoanExecuted(receiver, underlying, amount); + + return NO_ERROR; + } + + /** + * @notice Enable or disable flash loan for the market + * @custom:access Only Governance + * @custom:event Emits ToggleFlashLoanEnabled event on success + */ + function toggleFlashLoan() external override { + _checkAccessAllowed("toggleFlashLoan()"); + isFlashLoanEnabled = !isFlashLoanEnabled; + + emit ToggleFlashLoanEnabled(!isFlashLoanEnabled, isFlashLoanEnabled); + } + + /** + * @notice Update flashLoan fee mantissa + * @param protocolFeeMantissa FlashLoan protocol fee mantissa, transferred to protocol share reserve + * @param supplierFeeMantissa FlashLoan supplier fee mantissa, transferred to the supplier of the asset + * @custom:access Only Governance + * @custom:event Emits FlashLoanFeeUpdated event on success + */ + function setFlashLoanFeeMantissa(uint256 protocolFeeMantissa, uint256 supplierFeeMantissa) external override { + _checkAccessAllowed("setFlashLoanFeeMantissa(uint256,uint256)"); + + emit FlashLoanFeeUpdated( + flashLoanProtocolFeeMantissa, + protocolFeeMantissa, + flashLoanSupplierFeeMantissa, + supplierFeeMantissa + ); + flashLoanProtocolFeeMantissa = protocolFeeMantissa; + flashLoanSupplierFeeMantissa = supplierFeeMantissa; + } + /** * @notice A public function to set new threshold of slot(block or second) difference after which funds will be sent to the protocol share reserve * @param _newReduceReservesBlockOrTimestampDelta slot(block or second) difference value @@ -883,6 +1055,25 @@ contract VToken is return NO_ERROR; } + /** + * @notice Calculates the protocol fee and supplier fee for a flash loan. + * @param amount The amount of the flash loan. + * @return protocolFee The portion of the fee allocated to the protocol. + * @return supplierFee The portion of the fee allocated to the supplier. + * @dev This function reverts if flash loans are not enabled. + */ + function calculateFlashLoanFee(uint256 amount) public view override returns (uint256, uint256) { + if (!isFlashLoanEnabled) revert FlashLoanNotEnabled(address(this)); + + // Calculate protocol fee: amount * flashLoanProtocolFeeMantissa / MANTISSA_ONE(1e18) + uint256 protocolFee = (amount * flashLoanProtocolFeeMantissa) / MANTISSA_ONE; + + // Calculate supplier fee: amount * flashLoanSupplierFeeMantissa / MANTISSA_ONE(1e18) + uint256 supplierFee = (amount * flashLoanSupplierFeeMantissa) / MANTISSA_ONE; + + return (protocolFee, supplierFee); + } + /** * @notice User supplies assets into the market and receives vTokens in exchange * @dev Assumes interest has already been accrued up to the current block or timestamp @@ -1536,6 +1727,9 @@ contract VToken is * @param accessControlManager_ AccessControlManager contract address * @param riskManagement Addresses of risk & income related contracts * @param reserveFactorMantissa_ Percentage of borrow interest that goes to reserves (from 0 to 1e18) + * @param flashLoanEnabled_ Enable flashLoan or not for this market + * @param flashLoanProtocolFeeMantissa_ FlashLoan protocol fee mantissa, transferred to the protocol reserve + * @param flashLoanSupplierFeeMantissa_ FlashLoan supplier fee mantissa, transferred to suppliers */ function _initialize( address underlying_, @@ -1548,7 +1742,10 @@ contract VToken is address admin_, address accessControlManager_, RiskManagementInit memory riskManagement, - uint256 reserveFactorMantissa_ + uint256 reserveFactorMantissa_, + bool flashLoanEnabled_, + uint256 flashLoanProtocolFeeMantissa_, + uint256 flashLoanSupplierFeeMantissa_ ) internal onlyInitializing { __Ownable2Step_init(); __AccessControlled_init_unchained(accessControlManager_); @@ -1575,6 +1772,9 @@ contract VToken is _setShortfallContract(riskManagement.shortfall); _setProtocolShareReserve(riskManagement.protocolShareReserve); protocolSeizeShareMantissa = DEFAULT_PROTOCOL_SEIZE_SHARE_MANTISSA; + isFlashLoanEnabled = flashLoanEnabled_; + flashLoanProtocolFeeMantissa = flashLoanProtocolFeeMantissa_; + flashLoanSupplierFeeMantissa = flashLoanSupplierFeeMantissa_; // Set underlying and sanity check it underlying = underlying_; @@ -1657,7 +1857,7 @@ contract VToken is * exchangeRate = (totalCash + totalBorrows + badDebt - totalReserves) / totalSupply */ uint256 totalCash = _getCashPrior(); - uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + badDebt - totalReserves; + uint256 cashPlusBorrowsMinusReserves = totalCash + totalBorrows + flashLoanAmount + badDebt - totalReserves; uint256 exchangeRate = (cashPlusBorrowsMinusReserves * EXP_SCALE) / _totalSupply; return exchangeRate; diff --git a/contracts/VTokenInterfaces.sol b/contracts/VTokenInterfaces.sol index 0f01e1f17..7b121bd19 100644 --- a/contracts/VTokenInterfaces.sol +++ b/contracts/VTokenInterfaces.sol @@ -131,12 +131,32 @@ contract VTokenStorage { */ uint256 public reduceReservesBlockNumber; + /** + * @notice flashLoan is enabled for this market or not + */ + bool public isFlashLoanEnabled; + + /** + * @notice fee percentage collected by protocol on flashLoan + */ + uint256 public flashLoanProtocolFeeMantissa; + + /** + * @notice fee percentage collected by protocol on flashLoan + */ + uint256 public flashLoanSupplierFeeMantissa; + + /** + * @notice variable to store the flashLoan amount + */ + uint256 public flashLoanAmount; + /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ - uint256[48] private __gap; + uint256[44] private __gap; } /** @@ -288,6 +308,36 @@ abstract contract VTokenInterface is VTokenStorage { */ event ProtocolSeize(address indexed from, address indexed to, uint256 amount); + /** + * @notice Event emitted when flashLoanEnabled status is changed + */ + event ToggleFlashLoanEnabled(bool oldEnabled, bool enabled); + + /** + * @notice Event emitted when flashLoan is executed + */ + event FlashLoanExecuted(address receiver, address underlying, uint256 amount); + + /** + * @notice Event emitted when asset is transferred to receiver + */ + event TransferOutUnderlying(address asset, address receiver, uint256 amount); + + /** + * @notice Event emitted when asset is transferred from receiver + */ + event TransferInUnderlyingAndVerify(address asset, address receiver, uint256 amount); + + /** + * @notice Event emitted when flashLoan fee mantissa is updated + */ + event FlashLoanFeeUpdated( + uint256 oldFlashLoanProtocolFeeMantissa, + uint256 flashLoanProtocolFeeMantissa, + uint256 oldFlashLoanSupplierFeeMantissa, + uint256 flashLoanSupplierFeeMantissa + ); + /*** User Interface ***/ function mint(uint256 mintAmount) external virtual returns (uint256); @@ -336,6 +386,21 @@ abstract contract VTokenInterface is VTokenStorage { function sweepToken(IERC20Upgradeable token) external virtual; + function transferOutUnderlying(address receiver, uint256 amount) external virtual returns (uint256 balanceBefore); + + function transferInUnderlyingAndVerify( + address from, + uint256 amount, + uint256 fee, + uint256 balanceBefore + ) external virtual; + + function executeFlashLoan( + address receiver, + uint256 amount, + bytes calldata param + ) external virtual returns (uint256); + /*** Admin Functions ***/ function setReserveFactor(uint256 newReserveFactorMantissa) external virtual; @@ -350,6 +415,10 @@ abstract contract VTokenInterface is VTokenStorage { function addReserves(uint256 addAmount) external virtual; + function toggleFlashLoan() external virtual; + + function setFlashLoanFeeMantissa(uint256 protocolFeeMantissa, uint256 supplierFeeMantissa) external virtual; + function totalBorrowsCurrent() external virtual returns (uint256); function balanceOfUnderlying(address owner) external virtual returns (uint256); @@ -383,4 +452,6 @@ abstract contract VTokenInterface is VTokenStorage { function isVToken() external pure virtual returns (bool) { return true; } + + function calculateFlashLoanFee(uint256 amount) public view virtual returns (uint256 fee, uint256 repaymentAmount); } diff --git a/contracts/test/FlashloanReceiverBase.sol b/contracts/test/FlashloanReceiverBase.sol new file mode 100644 index 000000000..508323af0 --- /dev/null +++ b/contracts/test/FlashloanReceiverBase.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity 0.8.25; + +import { IFlashLoanReceiver } from "../Flashloan/interfaces/IFlashloanReceiver.sol"; +import { ComptrollerInterface } from "../ComptrollerInterface.sol"; + +/// @title FlashLoanReceiverBase +/// @notice A base contract for implementing flashLoan receiver logic. +/// @dev This abstract contract provides the necessary structure for inheriting contracts to implement the `IFlashLoanReceiver` interface. +/// It stores a reference to the Comptroller contract, which manages various aspects of the protocol. +abstract contract FlashLoanReceiverBase is IFlashLoanReceiver { + /// @notice The Comptroller contract that governs the protocol. + /// @dev This immutable variable stores the address of the Comptroller contract, which cannot be changed after deployment. + ComptrollerInterface public immutable COMPTROLLER; + + /** + * @notice Constructor to initialize the base contract with the Comptroller address. + * @param comptroller_ The address of the Comptroller contract that oversees the protocol. + */ + constructor(ComptrollerInterface comptroller_) { + COMPTROLLER = comptroller_; + } +} diff --git a/contracts/test/FlashloanSimpleReceiverBase.sol b/contracts/test/FlashloanSimpleReceiverBase.sol new file mode 100644 index 000000000..ff2dd41ac --- /dev/null +++ b/contracts/test/FlashloanSimpleReceiverBase.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity 0.8.25; + +import { IFlashLoanSimpleReceiver } from "../Flashloan/interfaces/IFlashloanSimpleReceiver.sol"; +import { VTokenInterface } from "../VTokenInterfaces.sol"; + +/** + * @title FlashLoanSimpleReceiverBase + * @author Venus + * @notice Base contract to develop a flashLoan-receiver contract. + * @dev This contract serves as a foundational contract for implementing custom flash loan receiver logic. + * Inheritors of this contract need to implement the `executeOperation` function defined in the `IFlashLoanSimpleReceiver` interface. + */ +abstract contract FlashLoanSimpleReceiverBase is IFlashLoanSimpleReceiver { + /// @notice The VToken contract used to initiate and handle flash loan + /// @dev This is an immutable reference to the VTokenInterface, which enables the flash loan functionality. + VTokenInterface public immutable VTOKEN; + + /// @notice Initializes the base contract by setting the VToken address + /// @param vToken_ The address of the VToken contract that supports flash loan + constructor(VTokenInterface vToken_) { + VTOKEN = vToken_; + } +} diff --git a/contracts/test/Mocks/MockFlashloanReceiver.sol b/contracts/test/Mocks/MockFlashloanReceiver.sol new file mode 100644 index 000000000..1b2d1ef03 --- /dev/null +++ b/contracts/test/Mocks/MockFlashloanReceiver.sol @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; + +import { FlashLoanReceiverBase } from "../FlashloanReceiverBase.sol"; +import { ComptrollerInterface } from "../../ComptrollerInterface.sol"; +import { VTokenInterface } from "../../VTokenInterfaces.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +/// @title MockFlashLoanReceiver +/// @notice A mock implementation of a flashLoan receiver contract that interacts with the Comptroller to request and handle flash loans. +/// @dev This contract extends `FlashLoanReceiverBase` and implements custom logic to request flash loans and repay them. +contract MockFlashLoanReceiver is FlashLoanReceiverBase { + /** + * @notice Constructor to initialize the flashLoan receiver with the Comptroller contract. + * @param comptroller The address of the Comptroller contract used to request flash loans. + */ + constructor(ComptrollerInterface comptroller) FlashLoanReceiverBase(comptroller) {} + + /** + * @notice Requests a flash loan from the Comptroller contract. + * @dev This function calls the `executeFlashLoan` function from the Comptroller to initiate a flash loan. + * @param assets An array of VToken contracts that support flash loans. + * @param amount An array of amounts to borrow in the flash loan for each corresponding asset. + * @param param The bytes passed in the executeOperation call. + */ + function requestFlashLoan( + VTokenInterface[] calldata assets, + uint256[] calldata amount, + bytes calldata param + ) external { + address receiver = address(this); // Receiver address is this contract itself + + // Request the flashLoan from the Comptroller contract + COMPTROLLER.executeFlashLoan(receiver, assets, amount, param); + } + + /** + * @notice Executes custom logic after receiving the flash loan. + * @dev This function is called by the Comptroller contract as part of the flashLoan process. + * It must repay the loan amount plus the premium for each borrowed asset. + * @param assets The addresses of the VToken contracts for the flash-borrowed assets. + * @param amounts The amounts of each asset borrowed. + * @param premiums The fees for each flash-borrowed asset. + * @param initiator The address that initiated the flash loan. + * @param param Additional encoded parameters passed with the flash loan. + * @return True if the operation succeeds and the debt plus premium is repaid, false otherwise. + */ + function executeOperation( + VTokenInterface[] calldata assets, + uint256[] calldata amounts, + uint256[] calldata premiums, + address initiator, + bytes calldata param + ) external returns (bool) { + // 👇 Your custom logic for the flash loan should be implemented here 👇 + /** YOUR CUSTOM LOGIC HERE */ + // 👆 Your custom logic for the flash loan should be implemented above here 👆 + initiator; + param; + // Calculate the total repayment amount (loan amount + premium) for each borrowed asset + uint256 len = assets.length; + for (uint256 k; k < len; ) { + uint256 total = amounts[k] + premiums[k]; + + // Transfer the repayment (amount + premium) back to the VToken contract + IERC20(VTokenInterface(assets[k]).underlying()).approve(address(assets[k]), total); + unchecked { + ++k; + } + } + + // Return true to indicate successful execution of the flash loan operation + return true; + } +} diff --git a/contracts/test/Mocks/MockFlashloanSimpleReceiver.sol b/contracts/test/Mocks/MockFlashloanSimpleReceiver.sol new file mode 100644 index 000000000..b5ecff025 --- /dev/null +++ b/contracts/test/Mocks/MockFlashloanSimpleReceiver.sol @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity ^0.8.10; + +import { FlashLoanSimpleReceiverBase } from "../FlashloanSimpleReceiverBase.sol"; +import { VTokenInterface } from "../../VTokenInterfaces.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +/// @title MockFlashLoanSimpleReceiver +/// @notice This contract serves as a mock implementation for a flash loan receiver, utilizing the +/// FlashLoanSimpleReceiverBase as a foundation. It provides the ability to request a flash loan and +/// defines how the loan is repaid by implementing custom logic in the `executeOperation` function. +contract MockFlashLoanSimpleReceiver is FlashLoanSimpleReceiverBase { + /** + * @notice Constructor that initializes the flashLoan receiver with a reference to the VToken contract. + * @param vToken The address of the VTokenInterface contract that supports flashLoan functionality. + */ + constructor(VTokenInterface vToken) FlashLoanSimpleReceiverBase(vToken) {} + + /** + * @notice Requests a flash loan from the VToken contract. + * @param amount The amount of tokens to borrow through the flash loan. + * @param param Additional encoded parameters passed with the flash loan. + * @dev This function calls the `executeFlashLoan` function of the VToken contract. + */ + function requestFlashLoan(uint256 amount, bytes calldata param) external { + address receiver = address(this); // Receiver address is this contract itself + + // Request the flashLoan from the VToken contract + VTOKEN.executeFlashLoan(receiver, amount, param); + } + + /** + * @notice This function is invoked after receiving the flash loan to handle the loan execution. + * @dev Custom logic for the use of the borrowed amount is implemented in this function. + * It is important that the total borrowed amount plus the premium is repaid. + * @param asset The address of the token being borrowed in the flash loan. + * @param amount The amount of tokens borrowed. + * @param premium The fee for the flash loan, typically a small percentage of the borrowed amount. + * @param initiator The address that initiated the flash loan. + * @param param Additional parameters passed along with the flash loan (can be empty). + * @return Returns true if the operation is successful. + */ + function executeOperation( + address asset, + uint256 amount, + uint256 premium, + address initiator, + bytes calldata param + ) external returns (bool) { + // 👇 Your custom logic for the flash loan should be implemented here 👇 + /** YOUR CUSTOM LOGIC HERE */ + // 👆 Your custom logic for the flash loan should be implemented above here 👆 + + // Calculate the total repayment amount (loan amount + premium) + uint256 total = amount + premium; + + // Transfer the total amount (principal + premium) back to the VToken contract to repay the loan + IERC20(asset).approve(address(VTOKEN), total); + + // Return true to indicate successful execution of the flash loan operation + return true; + } +} diff --git a/contracts/test/UpgradedVToken.sol b/contracts/test/UpgradedVToken.sol index efae5ac4f..fb4ba4a56 100644 --- a/contracts/test/UpgradedVToken.sol +++ b/contracts/test/UpgradedVToken.sol @@ -57,7 +57,10 @@ contract UpgradedVToken is VToken { address payable admin_, address accessControlManager_, RiskManagementInit memory riskManagement, - uint256 reserveFactorMantissa_ + uint256 reserveFactorMantissa_, + bool isFlashLoanEnabled_, + uint256 flashLoanProtocolFeeMantissa_, + uint256 flashLoanSupplierFeeMantissa_ ) public reinitializer(2) { super._initialize( underlying_, @@ -70,7 +73,10 @@ contract UpgradedVToken is VToken { admin_, accessControlManager_, riskManagement, - reserveFactorMantissa_ + reserveFactorMantissa_, + isFlashLoanEnabled_, + flashLoanProtocolFeeMantissa_, + flashLoanSupplierFeeMantissa_ ); } diff --git a/deploy/009-deploy-vtokens.ts b/deploy/009-deploy-vtokens.ts index bf3354e0d..8e019a866 100644 --- a/deploy/009-deploy-vtokens.ts +++ b/deploy/009-deploy-vtokens.ts @@ -66,7 +66,15 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { // Deploy Markets for (const vTokenConfig of pool.vtokens) { - const { name, asset, symbol, reserveFactor } = vTokenConfig; + const { + name, + asset, + symbol, + reserveFactor, + isFlashLoanAllowed, + flashLoanProtocolFeeMantissa, + flashLoanSupplierFeeMantissa, + } = vTokenConfig; const token = getTokenConfig(asset, tokensConfig); let tokenContract; @@ -163,6 +171,9 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { accessControlManagerAddress, [AddressOne, protocolShareReserveAddress], reserveFactor, + isFlashLoanAllowed, + flashLoanProtocolFeeMantissa, + flashLoanSupplierFeeMantissa, ]; await deploy(`VToken_${symbol}`, { from: deployer, diff --git a/hardhat.config.ts b/hardhat.config.ts index 0f186e2dd..8472eec01 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -227,6 +227,7 @@ const config: HardhatUserConfig = { yul: !process.env.CI, }, }, + viaIR: true, evmVersion: "paris", outputSelection: { "*": { diff --git a/helpers/deploymentConfig.ts b/helpers/deploymentConfig.ts index c481b61f1..36ad61c53 100644 --- a/helpers/deploymentConfig.ts +++ b/helpers/deploymentConfig.ts @@ -127,6 +127,9 @@ export type VTokenConfig = { borrowCap: string; vTokenReceiver: string; reduceReservesBlockDelta: string; + isFlashLoanAllowed: boolean; + flashLoanProtocolFeeMantissa: string; + flashLoanSupplierFeeMantissa: string; }; export type AccessControlEntry = { @@ -531,6 +534,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(478980, 18), vTokenReceiver: "account:deployer", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus BTCB", @@ -549,6 +555,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(1000, 18), vTokenReceiver: "account:deployer", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [ @@ -590,6 +599,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(3000000, 18), vTokenReceiver: "account:deployer", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus ankrBNB", @@ -608,6 +620,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(100, 18), vTokenReceiver: "account:deployer", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus MBOX", @@ -626,6 +641,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(3184294, 18), vTokenReceiver: "account:deployer", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus NFT", @@ -644,6 +662,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(24654278679, 18), vTokenReceiver: "account:deployer", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus RACA", @@ -662,6 +683,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(3805812642, 18), vTokenReceiver: "account:deployer", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus stkBNB", @@ -680,6 +704,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(324, 18), vTokenReceiver: "account:deployer", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDD", @@ -698,6 +725,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(1698253, 18), vTokenReceiver: "account:deployer", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [ @@ -1020,6 +1050,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(200_000, 18), vTokenReceiver: preconfiguredAddresses.bsctestnet.VTreasury, reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDT (Stable Coins)", @@ -1038,6 +1071,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(400_000, 6), // USDT has 6 decimals on testnet vTokenReceiver: preconfiguredAddresses.bscmainnet.VTreasury, reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDD (Stable Coins)", @@ -1056,6 +1092,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(400_000, 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus EURA (Stablecoins)", @@ -1074,6 +1113,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(50000, 18), vTokenReceiver: "0xc444949e0054a23c44fc45789738bdf64aed2391", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [ @@ -1121,6 +1163,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("10500000", 18), vTokenReceiver: "0x109E8083a64c7DedE513e8b580c5b08B96f9cE73", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus ALPACA (DeFi)", @@ -1139,6 +1184,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("1750000", 18), vTokenReceiver: "0xAD9CADe20100B8b945da48e1bCbd805C38d8bE77", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDT (DeFi)", @@ -1157,6 +1205,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("14880000", 6), // USDT has 6 decimals on testnet vTokenReceiver: preconfiguredAddresses.bscmainnet.VTreasury, reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDD (DeFi)", @@ -1175,6 +1226,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("1600000", 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus ANKR (DeFi)", @@ -1193,6 +1247,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("6656161", 18), vTokenReceiver: "0xAE1c38847Fb90A13a2a1D7E5552cCD80c62C6508", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus ankrBNB (DeFi)", @@ -1211,6 +1268,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("4000", 18), vTokenReceiver: "0xAE1c38847Fb90A13a2a1D7E5552cCD80c62C6508", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus PLANET (DeFi)", @@ -1229,6 +1289,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("500000000", 18), vTokenReceiver: "0x0554d6079eBc222AD12405E52b264Bdb5B65D1cf", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus TWT (DeFi)", @@ -1247,6 +1310,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("500000", 18), vTokenReceiver: "0x0848dB7cB495E7b9aDA1D4dC972b9A526D014D84", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [ @@ -1294,6 +1360,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("2800000000", 18), vTokenReceiver: "0x6Ee74536B3Ff10Ff639aa781B7220121287F6Fa5", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus FLOKI (GameFi)", @@ -1312,6 +1381,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("28000000000", 18), // FLOKI has 18 decimals on testnet vTokenReceiver: "0x17e98a24f992BB7bcd62d6722d714A3C74814B94", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDT (GameFi)", @@ -1330,6 +1402,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("14880000", 6), // USDT has 6 decimals on testnet vTokenReceiver: preconfiguredAddresses.bscmainnet.VTreasury, reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDD (GameFi)", @@ -1348,6 +1423,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("1600000", 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [ @@ -1389,6 +1467,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("5600", 18), vTokenReceiver: "0xAE1c38847Fb90A13a2a1D7E5552cCD80c62C6508", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus BNBx (Liquid Staked BNB)", @@ -1407,6 +1488,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("1272", 18), vTokenReceiver: "0xF0348E1748FCD45020151C097D234DbbD5730BE7", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus stkBNB (Liquid Staked BNB)", @@ -1425,6 +1509,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("378", 18), vTokenReceiver: "0xccc022502d6c65e1166fd34147040f05880f7972", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus WBNB (Liquid Staked BNB)", @@ -1443,6 +1530,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("56000", 18), vTokenReceiver: preconfiguredAddresses.bscmainnet.VTreasury, reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDT (Liquid Staked BNB)", @@ -1461,6 +1551,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("14880000", 6), // USDT has 6 decimals on testnet vTokenReceiver: preconfiguredAddresses.bscmainnet.VTreasury, reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDD (Liquid Staked BNB)", @@ -1479,6 +1572,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("1600000", 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus slisBNB (Liquid Staked BNB)", @@ -1497,6 +1593,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("100", 18), vTokenReceiver: "0xDC2D855A95Ee70d7282BebD35c96f905CDE31f55", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus PT-clisBNB-24APR2025 (Liquid Staked BNB)", @@ -1592,6 +1691,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("1050000000000", 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus NFT (Tron)", @@ -1610,6 +1712,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("2800000000", 18), // NFT has 18 decimals on testnet vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus WIN (Tron)", @@ -1628,6 +1733,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("2100000000", 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus TRX (Tron)", @@ -1646,6 +1754,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("7700000", 6), // Note 6 decimals vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDT (Tron)", @@ -1664,6 +1775,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("14880000", 6), // USDT has 6 decimals on testnet vTokenReceiver: preconfiguredAddresses.bscmainnet.VTreasury, reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDD (Tron)", @@ -1682,6 +1796,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("1600000", 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [ @@ -1735,6 +1852,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("800000000000000", 9), vTokenReceiver: preconfiguredAddresses.bsctestnet.VTreasury, reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDT (Meme)", @@ -1753,6 +1873,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("900000", 6), vTokenReceiver: preconfiguredAddresses.bsctestnet.VTreasury, reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [ @@ -1788,6 +1911,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("5", 18), reduceReservesBlockDelta: "28800", vTokenReceiver: preconfiguredAddresses.bsctestnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus weETH (Liquid Staked ETH)", @@ -1806,6 +1932,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("200", 18), reduceReservesBlockDelta: "28800", vTokenReceiver: preconfiguredAddresses.bsctestnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus ETH (Liquid Staked ETH)", @@ -1824,6 +1953,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("400", 18), reduceReservesBlockDelta: "28800", vTokenReceiver: preconfiguredAddresses.bsctestnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [], @@ -1852,6 +1984,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("140", 18), reduceReservesBlockDelta: "28800", vTokenReceiver: preconfiguredAddresses.bsctestnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus PT-SolvBTC.BBN-27MAR2025 (BTC)", @@ -1870,6 +2005,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("0", 18), reduceReservesBlockDelta: "28800", vTokenReceiver: preconfiguredAddresses.bsctestnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [], @@ -2135,6 +2273,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(200_000, 18), vTokenReceiver: "0x09702Ea135d9D707DD51f530864f2B9220aAD87B", reduceReservesBlockDelta: "28800", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDT (Stablecoins)", @@ -2153,6 +2294,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(400_000, 18), vTokenReceiver: preconfiguredAddresses.bscmainnet.VTreasury, reduceReservesBlockDelta: "28800", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDD (Stablecoins)", @@ -2171,6 +2315,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(400_000, 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", reduceReservesBlockDelta: "28800", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus EURA (Stablecoins)", @@ -2189,6 +2336,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(50000, 18), vTokenReceiver: "0xc444949e0054a23c44fc45789738bdf64aed2391", // community wallet reduceReservesBlockDelta: "28800", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [ @@ -2236,6 +2386,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("10500000", 18), vTokenReceiver: "0x109E8083a64c7DedE513e8b580c5b08B96f9cE73", // biswap team treasury reduceReservesBlockDelta: "28800", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus ALPACA (DeFi)", @@ -2254,6 +2407,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("1750000", 18), vTokenReceiver: "0xAD9CADe20100B8b945da48e1bCbd805C38d8bE77", // alpaca team treasury reduceReservesBlockDelta: "28800", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDT (DeFi)", @@ -2272,6 +2428,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("14880000", 18), vTokenReceiver: preconfiguredAddresses.bscmainnet.VTreasury, reduceReservesBlockDelta: "28800", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDD (DeFi)", @@ -2290,6 +2449,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("1600000", 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", // tron ecosystem treasury reduceReservesBlockDelta: "28800", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus ANKR (DeFi)", @@ -2308,6 +2470,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("6656161", 18), vTokenReceiver: "0xAE1c38847Fb90A13a2a1D7E5552cCD80c62C6508", // ankr team treasury reduceReservesBlockDelta: "28800", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { @@ -2327,6 +2492,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("4000", 18), vTokenReceiver: "0xAE1c38847Fb90A13a2a1D7E5552cCD80c62C6508", // ankr team treasury reduceReservesBlockDelta: "28800", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus PLANET (DeFi)", @@ -2345,6 +2513,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("500000000", 18), vTokenReceiver: "0x0554d6079eBc222AD12405E52b264Bdb5B65D1cf", reduceReservesBlockDelta: "28800", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus TWT (DeFi)", @@ -2363,6 +2534,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("500000", 18), vTokenReceiver: "0x0848dB7cB495E7b9aDA1D4dC972b9A526D014D84", reduceReservesBlockDelta: "28800", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [ @@ -2411,6 +2585,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("2800000000", 18), vTokenReceiver: "0x6Ee74536B3Ff10Ff639aa781B7220121287F6Fa5", reduceReservesBlockDelta: "28800", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus FLOKI (GameFi)", @@ -2429,6 +2606,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("28000000000", 9), // Note 9 decimals vTokenReceiver: "0x17e98a24f992BB7bcd62d6722d714A3C74814B94", reduceReservesBlockDelta: "28800", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDT (GameFi)", @@ -2447,6 +2627,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("14880000", 18), vTokenReceiver: preconfiguredAddresses.bscmainnet.VTreasury, reduceReservesBlockDelta: "28800", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDD (GameFi)", @@ -2465,6 +2648,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("1600000", 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", reduceReservesBlockDelta: "28800", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [ @@ -2506,6 +2692,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("5600", 18), vTokenReceiver: "0xAE1c38847Fb90A13a2a1D7E5552cCD80c62C6508", reduceReservesBlockDelta: "28800", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus BNBx (Liquid Staked BNB)", @@ -2524,6 +2713,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("1272", 18), vTokenReceiver: "0xF0348E1748FCD45020151C097D234DbbD5730BE7", reduceReservesBlockDelta: "28800", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus stkBNB (Liquid Staked BNB)", @@ -2542,6 +2734,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("378", 18), vTokenReceiver: "0xccc022502d6c65e1166fd34147040f05880f7972", reduceReservesBlockDelta: "28800", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus WBNB (Liquid Staked BNB)", @@ -2560,6 +2755,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("56000", 18), vTokenReceiver: preconfiguredAddresses.bscmainnet.VTreasury, reduceReservesBlockDelta: "28800", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDT (Liquid Staked BNB)", @@ -2578,6 +2776,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("14880000", 18), vTokenReceiver: preconfiguredAddresses.bscmainnet.VTreasury, reduceReservesBlockDelta: "28800", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDD (Liquid Staked BNB)", @@ -2596,6 +2797,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("1600000", 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", reduceReservesBlockDelta: "28800", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus slisBNB (Liquid Staked BNB)", @@ -2614,6 +2818,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("100", 18), vTokenReceiver: "0xDC2D855A95Ee70d7282BebD35c96f905CDE31f55", reduceReservesBlockDelta: "28800", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus PT-clisBNB-24APR2025 (Liquid Staked BNB)", @@ -2709,6 +2916,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("1050000000000", 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", reduceReservesBlockDelta: "28800", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus NFT (Tron)", @@ -2727,6 +2937,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("2800000000", 6), // Note 6 decimals vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", reduceReservesBlockDelta: "28800", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus WIN (Tron)", @@ -2745,6 +2958,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("2100000000", 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", reduceReservesBlockDelta: "28800", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus TRX (Tron)", @@ -2763,6 +2979,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("7700000", 6), // Note 6 decimals vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", reduceReservesBlockDelta: "28800", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDT (Tron)", @@ -2781,6 +3000,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("14880000", 18), vTokenReceiver: preconfiguredAddresses.bscmainnet.VTreasury, reduceReservesBlockDelta: "28800", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDD (Tron)", @@ -2799,6 +3021,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("1600000", 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", reduceReservesBlockDelta: "28800", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [ @@ -2852,6 +3077,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("800000000000000", 9), vTokenReceiver: preconfiguredAddresses.bscmainnet.VTreasury, reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDT (Meme)", @@ -2870,6 +3098,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("900000", 18), vTokenReceiver: preconfiguredAddresses.bscmainnet.VTreasury, reduceReservesBlockDelta: "100", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [ @@ -2905,6 +3136,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("5", 18), reduceReservesBlockDelta: "28800", vTokenReceiver: preconfiguredAddresses.bscmainnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus weETH (Liquid Staked ETH)", @@ -2923,6 +3157,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("200", 18), reduceReservesBlockDelta: "28800", vTokenReceiver: preconfiguredAddresses.bscmainnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus ETH (Liquid Staked ETH)", @@ -2941,6 +3178,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("400", 18), reduceReservesBlockDelta: "28800", vTokenReceiver: preconfiguredAddresses.bscmainnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [], @@ -2969,6 +3209,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("140", 18), reduceReservesBlockDelta: "28800", vTokenReceiver: preconfiguredAddresses.bsctestnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus PT-SolvBTC.BBN-27MAR2025 (BTC)", @@ -2987,6 +3230,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("0", 18), reduceReservesBlockDelta: "28800", vTokenReceiver: "0x63f6D9E7d3953106bCaf98832BD9C88A54AfCc9D", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [], @@ -3285,6 +3531,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(250, 8), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus WETH (Core)", @@ -3303,6 +3552,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(4600, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDC (Core)", @@ -3324,6 +3576,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(9_000_000, 6), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDT (Core)", @@ -3345,6 +3600,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(9_000_000, 6), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus crvUSD (Core)", @@ -3363,6 +3621,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(9_000_000, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus CRV (Core)", @@ -3381,6 +3642,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(2_500_000, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus DAI (Core)", @@ -3399,6 +3663,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(45_000_000, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus TUSD (Core)", @@ -3417,6 +3684,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(1_800_000, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, // TBD + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus Frax (Core)", @@ -3435,6 +3705,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(8_000_000, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, // TBD + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus Staked FRAX (Core)", @@ -3453,6 +3726,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(1_000_000, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, // TBD + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus eBTC (Core)", @@ -3471,6 +3747,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("12.5", 8), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus EIGEN (Core)", @@ -3489,6 +3768,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(1_500_000, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus LBTC (Core)", @@ -3507,6 +3789,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("45", 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDS (Core)", @@ -3525,6 +3810,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("7_680_000", 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus sUSDS (Core)", @@ -3543,6 +3831,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("0", 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus yvUSDC-1 (Core)", @@ -3561,6 +3852,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("0", 6), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus yvUSDT-1 (Core)", @@ -3579,6 +3873,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("0", 6), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus yvUSDS-1 (Core)", @@ -3597,6 +3894,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("0", 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus yvWETH-1 (Core)", @@ -3615,6 +3915,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("0", 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus BAL (Core)", @@ -3633,6 +3936,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(700_000, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus weETHs (Core)", @@ -3651,6 +3957,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(0, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus sUSDe (Core)", @@ -3777,6 +4086,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(4_500_000, 6), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDT (Stablecoins)", @@ -3795,6 +4107,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(4_500_000, 6), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus crvUSD (Stablecoins)", @@ -3813,6 +4128,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(4_500_000, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [], @@ -3841,6 +4159,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(2_000_000, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus CRV (Curve)", @@ -3859,6 +4180,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(2_500_000, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [ @@ -3905,6 +4229,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(2_000, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus WETH (Liquid Staked ETH)", @@ -3923,6 +4250,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(18_000, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus weETH (Liquid Staked ETH)", @@ -3941,6 +4271,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(750, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus PT-wETH-26DEC2024 (Liquid Staked ETH)", @@ -3959,6 +4292,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(375, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus rsETH (Liquid Staked ETH)", @@ -3977,6 +4313,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(3_600, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus sfrxETH (Liquid Staked ETH)", @@ -3995,6 +4334,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(1_000, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus ezETH (Liquid Staked ETH)", @@ -4013,6 +4355,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(1_400, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus weETHs (Liquid Staked ETH)", @@ -4031,6 +4376,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(0, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus pufETH (Liquid Staked ETH)", @@ -4049,6 +4397,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("300", 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [ @@ -4103,6 +4454,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("0", 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus PT-sUSDE-27MAR2025 (Ethena)", @@ -4121,6 +4475,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("0", 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus sUSDe (Ethena)", @@ -4139,6 +4496,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("0", 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDC (Ethena)", @@ -4157,6 +4517,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(46_000_000, 6), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [], @@ -4448,6 +4811,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(850, 8), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.ethereum.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus WETH (Core)", @@ -4466,6 +4832,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(18_000, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.ethereum.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDC (Core)", @@ -4487,6 +4856,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(45_000_000, 6), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.ethereum.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDT (Core)", @@ -4508,6 +4880,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(45_000_000, 6), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.ethereum.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus crvUSD (Core)", @@ -4526,6 +4901,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(45_000_000, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: "0x7a16fF8270133F063aAb6C9977183D9e72835428", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus DAI (Core)", @@ -4544,6 +4922,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(45_000_000, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.ethereum.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus TUSD (Core)", @@ -4562,6 +4943,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(1_800_000, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.ethereum.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus Frax (Core)", @@ -4580,6 +4964,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(8_000_000, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: "0x6e74053a3798e0fC9a9775F7995316b27f21c4D2", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus Staked FRAX (Core)", @@ -4598,6 +4985,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(1_000_000, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: "0x6e74053a3798e0fC9a9775F7995316b27f21c4D2", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus eBTC (Core)", @@ -4616,6 +5006,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("12.5", 8), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.ethereum.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus EIGEN (Core)", @@ -4634,6 +5027,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(1_500_000, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.ethereum.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus LBTC (Core)", @@ -4652,6 +5048,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("45", 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: "0xCb09Ab3F6254437d225Ed3CABEBe0949782E2372", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDS (Core)", @@ -4670,6 +5069,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("7_680_000", 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: "0x9c489E4efba90A67299C1097a8628e233C33BB7B", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus sUSDS (Core)", @@ -4688,6 +5090,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("0", 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: "0x9c489E4efba90A67299C1097a8628e233C33BB7B", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus yvUSDC-1 (Core)", @@ -4706,6 +5111,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("0", 6), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.ethereum.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus yvUSDT-1 (Core)", @@ -4724,6 +5132,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("0", 6), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.ethereum.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus yvUSDS-1 (Core)", @@ -4742,6 +5153,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("0", 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.ethereum.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus yvWETH-1 (Core)", @@ -4760,6 +5174,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("0", 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.ethereum.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus BAL (Core)", @@ -4778,6 +5195,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(700_000, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: "0x36cc7B13029B5DEe4034745FB4F24034f3F2ffc6", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus weETHs (Core)", @@ -4796,6 +5216,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(0, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: "0x3e8734ec146c981e3ed1f6b582d447dde701d90c", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus sUSDe (Core)", @@ -4940,6 +5363,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(2_000_000, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: "0x7a16fF8270133F063aAb6C9977183D9e72835428", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus CRV (Curve)", @@ -4958,6 +5384,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(3_000_000, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: "0x7a16fF8270133F063aAb6C9977183D9e72835428", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [ @@ -5010,6 +5439,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(2_000, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus WETH (Liquid Staked ETH)", @@ -5028,6 +5460,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(18_000, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus weETH (Liquid Staked ETH)", @@ -5046,6 +5481,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(750, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: `0xF6C612c745Ba4546075DB62902c1Eb3255CdAe28`, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus PT-wETH-26DEC2024 (Liquid Staked ETH)", @@ -5064,6 +5502,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(0, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.ethereum.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus rsETH (Liquid Staked ETH)", @@ -5082,6 +5523,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(3_600, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: "0x7AAd74b7f0d60D5867B59dbD377a71783425af47", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus sfrxETH (Liquid Staked ETH)", @@ -5100,6 +5544,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(1_000, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ETHEREUM, vTokenReceiver: "0x6e74053a3798e0fC9a9775F7995316b27f21c4D2", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus ezETH (Liquid Staked ETH)", @@ -5118,6 +5565,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(1_400, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ETHEREUM, vTokenReceiver: "0x1E3233E8d972cfFc7D0f83aFAE4354a0Db74e34E", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus weETHs (Liquid Staked ETH)", @@ -5136,6 +5586,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(0, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ETHEREUM, vTokenReceiver: "0x86fBaEB3D6b5247F420590D303a6ffC9cd523790", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus pufETH (Liquid Staked ETH)", @@ -5154,6 +5607,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("300", 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.ethereum.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [ @@ -5214,6 +5670,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("0", 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: "0x3e8734ec146c981e3ed1f6b582d447dde701d90c", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus PT-sUSDE-27MAR2025 (Ethena)", @@ -5232,6 +5691,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("0", 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: "0x3e8734ec146c981e3ed1f6b582d447dde701d90c", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus sUSDe (Ethena)", @@ -5250,6 +5712,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("0", 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: "0x3e8734ec146c981e3ed1f6b582d447dde701d90c", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDC (Ethena)", @@ -5268,6 +5733,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(46_000_000, 6), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: "0x3e8734ec146c981e3ed1f6b582d447dde701d90c", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [], @@ -5335,6 +5803,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(250, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_OPBNBTESTNET, vTokenReceiver: preconfiguredAddresses.opbnbtestnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus ETH (Core)", @@ -5353,6 +5824,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(4600, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_OPBNBTESTNET, vTokenReceiver: preconfiguredAddresses.opbnbtestnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDT (Core)", @@ -5371,6 +5845,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(9_000_000, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_OPBNBTESTNET, vTokenReceiver: preconfiguredAddresses.opbnbtestnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus WBNB (Core)", @@ -5389,6 +5866,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(56_000, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_OPBNBTESTNET, vTokenReceiver: preconfiguredAddresses.opbnbtestnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [], @@ -5470,6 +5950,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("0.55", 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_OPBNBMAINNET, vTokenReceiver: preconfiguredAddresses.opbnbmainnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus ETH (Core)", @@ -5488,6 +5971,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(16, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_OPBNBMAINNET, vTokenReceiver: preconfiguredAddresses.opbnbmainnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDT (Core)", @@ -5506,6 +5992,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(130_000, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_OPBNBMAINNET, vTokenReceiver: preconfiguredAddresses.opbnbmainnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus WBNB (Core)", @@ -5524,6 +6013,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(75, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_OPBNBMAINNET, vTokenReceiver: preconfiguredAddresses.opbnbmainnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus FDUSD (Core)", @@ -5542,6 +6034,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(130_000, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_OPBNBMAINNET, vTokenReceiver: preconfiguredAddresses.opbnbmainnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [], @@ -5651,6 +6146,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("0.55", 8), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ARBITRUM_SEPOLIA, vTokenReceiver: preconfiguredAddresses.arbitrumsepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus WETH (Core)", @@ -5669,6 +6167,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(16, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ARBITRUM_SEPOLIA, vTokenReceiver: preconfiguredAddresses.arbitrumsepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDC (Core)", @@ -5690,6 +6191,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(130_000, 6), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ARBITRUM_SEPOLIA, vTokenReceiver: preconfiguredAddresses.arbitrumsepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDT (Core)", @@ -5711,6 +6215,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(130_000, 6), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ARBITRUM_SEPOLIA, vTokenReceiver: preconfiguredAddresses.arbitrumsepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus ARB (Core)", @@ -5729,6 +6236,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(16, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ARBITRUM_SEPOLIA, vTokenReceiver: preconfiguredAddresses.arbitrumsepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus gmWETH-USDC (Core)", @@ -5747,6 +6257,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(0, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ARBITRUM_SEPOLIA, vTokenReceiver: preconfiguredAddresses.arbitrumsepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus gmBTC-USDC (Core)", @@ -5765,6 +6278,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(0, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ARBITRUM_SEPOLIA, vTokenReceiver: preconfiguredAddresses.arbitrumsepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [ @@ -5800,6 +6316,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(800, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ARBITRUM_SEPOLIA, vTokenReceiver: preconfiguredAddresses.arbitrumsepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus weETH (Liquid Staked ETH)", @@ -5818,6 +6337,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(2_300, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ARBITRUM_SEPOLIA, vTokenReceiver: preconfiguredAddresses.arbitrumsepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus WETH (Liquid Staked ETH)", @@ -5836,6 +6358,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(12_500, 18), reduceReservesBlockDelta: DEFAULT_REDUCE_RESERVES_BLOCK_DELTA, vTokenReceiver: preconfiguredAddresses.sepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [], @@ -5945,6 +6470,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("500", 8), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ARBITRUM_ONE, vTokenReceiver: preconfiguredAddresses.arbitrumone.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus WETH (Core)", @@ -5963,6 +6491,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("23500", 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ARBITRUM_ONE, vTokenReceiver: preconfiguredAddresses.arbitrumone.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDC (Core)", @@ -5984,6 +6515,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("49000000", 6), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ARBITRUM_ONE, vTokenReceiver: preconfiguredAddresses.arbitrumone.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDT (Core)", @@ -6005,6 +6539,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("18000000", 6), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ARBITRUM_ONE, vTokenReceiver: preconfiguredAddresses.arbitrumone.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus ARB (Core)", @@ -6023,6 +6560,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("9000000", 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ARBITRUM_ONE, vTokenReceiver: preconfiguredAddresses.arbitrumone.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus gmWETH-USDC (Core)", @@ -6041,6 +6581,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(0, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ARBITRUM_ONE, vTokenReceiver: "0xe1f7c5209938780625E354dc546E28397F6Ce174", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus gmBTC-USDC (Core)", @@ -6059,6 +6602,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(0, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ARBITRUM_ONE, vTokenReceiver: "0xe1f7c5209938780625E354dc546E28397F6Ce174", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [ @@ -6105,6 +6651,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(800, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ARBITRUM_ONE, vTokenReceiver: "0x5A9d695c518e95CD6Ea101f2f25fC2AE18486A61", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus weETH (Liquid Staked ETH)", @@ -6123,6 +6672,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(2_300, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ARBITRUM_ONE, vTokenReceiver: "0x46cba1e9b1e5db32da28428f2fb85587bcb785e7", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus WETH (Liquid Staked ETH)", @@ -6141,6 +6693,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(12_500, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ARBITRUM_ONE, vTokenReceiver: preconfiguredAddresses.arbitrumone.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [ @@ -6273,6 +6828,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(23_500, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ZKSYNC_SEPOLIA, vTokenReceiver: preconfiguredAddresses.zksyncsepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus WBTC (Core)", @@ -6291,6 +6849,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(500, 8), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ZKSYNC_SEPOLIA, vTokenReceiver: preconfiguredAddresses.zksyncsepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDT (Core)", @@ -6312,6 +6873,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(18_000_000, 6), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ZKSYNC_SEPOLIA, vTokenReceiver: preconfiguredAddresses.zksyncsepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDC.e (Core)", @@ -6333,6 +6897,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(49_000_000, 6), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ZKSYNC_SEPOLIA, vTokenReceiver: preconfiguredAddresses.zksyncsepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus ZK (Core)", @@ -6351,6 +6918,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(2_350_000, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ZKSYNC_SEPOLIA, vTokenReceiver: preconfiguredAddresses.zksyncsepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDC (Core)", @@ -6372,6 +6942,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(1_000_000, 6), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ZKSYNC_SEPOLIA, vTokenReceiver: preconfiguredAddresses.zksyncsepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus wUSDM (Core)", @@ -6390,6 +6963,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("4000000", 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ZKSYNC_SEPOLIA, vTokenReceiver: preconfiguredAddresses.zksyncsepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus wstETH (Core)", @@ -6408,6 +6984,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(35, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ZKSYNC_SEPOLIA, vTokenReceiver: preconfiguredAddresses.zksyncsepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus zkETH (Core)", @@ -6426,6 +7005,9 @@ export const globalConfig: NetworkConfig = { borrowCap: "0", reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ZKSYNC_SEPOLIA, vTokenReceiver: preconfiguredAddresses.zksyncsepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [ @@ -6560,6 +7142,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(1_700, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ZKSYNC_MAINNET, vTokenReceiver: preconfiguredAddresses.zksyncmainnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus WBTC (Core)", @@ -6578,6 +7163,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(20, 8), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ZKSYNC_MAINNET, vTokenReceiver: preconfiguredAddresses.zksyncmainnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDT (Core)", @@ -6599,6 +7187,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(3_300_000, 6), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ZKSYNC_MAINNET, vTokenReceiver: preconfiguredAddresses.zksyncmainnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDC.e (Core)", @@ -6620,6 +7211,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(4_200_000, 6), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ZKSYNC_MAINNET, vTokenReceiver: preconfiguredAddresses.zksyncmainnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { @@ -6639,6 +7233,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(12_500_000, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ZKSYNC_MAINNET, vTokenReceiver: preconfiguredAddresses.zksyncmainnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDC (Core)", @@ -6660,6 +7257,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(1_000_000, 6), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ZKSYNC_MAINNET, vTokenReceiver: preconfiguredAddresses.zksyncmainnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus wUSDM (Core)", @@ -6678,6 +7278,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("4000000", 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ZKSYNC_MAINNET, vTokenReceiver: "0xFfCf33Ed3fc6B7eC7d4F6166cC1B86d4F42Af192", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus wstETH (Core)", @@ -6696,6 +7299,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(35, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ZKSYNC_MAINNET, vTokenReceiver: "0x65B05f4fCa066316383b0FE196C76C873a4dFD02", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus zkETH (Core)", @@ -6714,6 +7320,9 @@ export const globalConfig: NetworkConfig = { borrowCap: "0", reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_ZKSYNC_MAINNET, vTokenReceiver: "0x3d97E13A1D2bb4C9cE9EA9d424D83d3638F052ad", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [ @@ -6827,6 +7436,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("0.55", 8), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_OP_SEPOLIA, vTokenReceiver: preconfiguredAddresses.opsepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus WETH (Core)", @@ -6845,6 +7457,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(16, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_OP_SEPOLIA, vTokenReceiver: preconfiguredAddresses.opsepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDC (Core)", @@ -6863,6 +7478,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(130_000, 6), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_OP_SEPOLIA, vTokenReceiver: preconfiguredAddresses.opsepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDT (Core)", @@ -6881,6 +7499,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(130_000, 6), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_OP_SEPOLIA, vTokenReceiver: preconfiguredAddresses.opsepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus OP (Core)", @@ -6899,6 +7520,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(16, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_OP_SEPOLIA, vTokenReceiver: preconfiguredAddresses.opsepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [ @@ -6999,6 +7623,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("50", 8), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_OP_MAINNET, vTokenReceiver: preconfiguredAddresses.opmainnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus WETH (Core)", @@ -7017,6 +7644,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("2700", 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_OP_MAINNET, vTokenReceiver: preconfiguredAddresses.opmainnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDT (Core)", @@ -7035,6 +7665,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("3600000", 6), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_OP_MAINNET, vTokenReceiver: preconfiguredAddresses.opmainnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus OP (Core)", @@ -7053,6 +7686,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("1500000", 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_OP_MAINNET, vTokenReceiver: preconfiguredAddresses.opmainnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDC (Core)", @@ -7071,6 +7707,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("9000000", 6), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_OP_MAINNET, vTokenReceiver: preconfiguredAddresses.opmainnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [], @@ -7157,6 +7796,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("130000", 6), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_BASE_SEPOLIA, vTokenReceiver: preconfiguredAddresses.basesepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus WETH (Core)", @@ -7175,6 +7817,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(16, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_BASE_SEPOLIA, vTokenReceiver: preconfiguredAddresses.basesepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus cbBTC (Core)", @@ -7193,6 +7838,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(16, 8), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_BASE_SEPOLIA, vTokenReceiver: preconfiguredAddresses.basesepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus wsuperOETHb (Core)", @@ -7211,6 +7859,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(0, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_BASE_SEPOLIA, vTokenReceiver: preconfiguredAddresses.basesepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus wstETH (Core)", @@ -7229,6 +7880,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(260, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_BASE_SEPOLIA, vTokenReceiver: preconfiguredAddresses.basesepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [ @@ -7332,6 +7986,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("27000000", 6), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_BASE_MAINNET, vTokenReceiver: preconfiguredAddresses.basemainnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus WETH (Core)", @@ -7350,6 +8007,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(9000, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_BASE_MAINNET, vTokenReceiver: preconfiguredAddresses.basemainnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus cbBTC (Core)", @@ -7368,6 +8028,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(200, 8), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_BASE_MAINNET, vTokenReceiver: preconfiguredAddresses.basemainnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus wsuperOETHb (Core)", @@ -7386,6 +8049,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(0, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_BASE_MAINNET, vTokenReceiver: "0x3c112E20141B65041C252a68a611EF145f58B7bc", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus wstETH (Core)", @@ -7404,6 +8070,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(260, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_BASE_SEPOLIA, vTokenReceiver: "0x5A9d695c518e95CD6Ea101f2f25fC2AE18486A61", + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [], @@ -7516,6 +8185,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(18_000_000, 6), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_UNICHAIN_SEPOLIA, vTokenReceiver: preconfiguredAddresses.unichainsepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus USDT (Core)", @@ -7534,6 +8206,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(18_000_000, 6), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_UNICHAIN_SEPOLIA, vTokenReceiver: preconfiguredAddresses.unichainsepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus WETH (Core)", @@ -7552,6 +8227,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(23_500, 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_UNICHAIN_SEPOLIA, vTokenReceiver: preconfiguredAddresses.unichainsepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus cbBTC (Core)", @@ -7570,6 +8248,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(500, 8), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_UNICHAIN_SEPOLIA, vTokenReceiver: preconfiguredAddresses.unichainsepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus UNI (Core)", @@ -7663,6 +8344,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(45_000_000, 6), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_UNICHAIN_SEPOLIA, vTokenReceiver: preconfiguredAddresses.unichainsepolia.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [ @@ -7780,6 +8464,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(850_000, 6), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_UNICHAIN_MAINNET, vTokenReceiver: preconfiguredAddresses.unichainmainnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus WETH (Core)", @@ -7798,6 +8485,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("300", 18), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_UNICHAIN_MAINNET, vTokenReceiver: preconfiguredAddresses.unichainmainnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, { name: "Venus UNI (Core)", @@ -7891,6 +8581,9 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(45_000_000, 6), reduceReservesBlockDelta: REDUCE_RESERVES_BLOCK_DELTA_UNICHAIN_MAINNET, vTokenReceiver: preconfiguredAddresses.unichainmainnet.VTreasury, + isFlashLoanAllowed: false, + flashLoanProtocolFeeMantissa: "0", + flashLoanSupplierFeeMantissa: "0", }, ], rewards: [ diff --git a/tests/hardhat/Comptroller/flashLoanMultiple.ts b/tests/hardhat/Comptroller/flashLoanMultiple.ts new file mode 100644 index 000000000..886c61bc7 --- /dev/null +++ b/tests/hardhat/Comptroller/flashLoanMultiple.ts @@ -0,0 +1,234 @@ +import { FakeContract, MockContract, smock } from "@defi-wonderland/smock"; +import { loadFixture, setBalance } from "@nomicfoundation/hardhat-network-helpers"; +import chai from "chai"; +import { parseEther, parseUnits } from "ethers/lib/utils"; +import { ethers, upgrades } from "hardhat"; +import { SignerWithAddress } from "hardhat-deploy-ethers/signers"; + +import { convertToUnit } from "../../../helpers/utils"; +import { + AccessControlManager, + Comptroller, + ERC20Harness, + IProtocolShareReserve, + InterestRateModel, + MockFlashLoanReceiver, + MockFlashLoanReceiver__factory, + PoolRegistry, + ProtocolShareReserve, + VTokenHarness, + VTokenHarness__factory, +} from "../../../typechain"; +import { makeVToken, mockUnderlying } from "../util/TokenTestHelpers"; + +const { expect } = chai; +chai.use(smock.matchers); + +const MAX_LOOP_LIMIT = 150; + +const flashLoanAmount1 = parseUnits("20", 18); +const flashLoanAmount2 = parseUnits("30", 18); +const protocolFeeMantissaTokenA = parseUnits("0.01", 18); +const protocolFeeMantissaTokenB = parseUnits("0.02", 18); +const supplierFeeMantissaTokenA = parseUnits("0.01", 18); +const supplierFeeMantissaTokenB = parseUnits("0.02", 18); + +// Declare the types here +type FlashLoanContractsFixture = { + accessControlManager: FakeContract; + protocolShareReserve: FakeContract; + interestRateModel: FakeContract; + poolRegistry: FakeContract; + comptroller: Comptroller; + underlyingA: MockContract; + underlyingB: MockContract; + VTokenA: VTokenHarness; + VTokenB: VTokenHarness; +}; + +// Create a fixture will deploy all the required contracts for flashLoan +const flashLoanTestFixture = async (): Promise => { + const [admin] = await ethers.getSigners(); + const accessControlManager = await smock.fake("AccessControlManager"); + accessControlManager.isAllowedToCall.returns(true); + const protocolShareReserve = await smock.fake("ProtocolShareReserve"); + const interestRateModel = await smock.fake("InterestRateModel"); + interestRateModel.isInterestRateModel.returns(true); + + const poolRegistry = await smock.fake("PoolRegistry"); + + const underlyingA = await mockUnderlying("Mock AAVE", "AAVE"); + const underlyingB = await mockUnderlying("Mock UNI", "UNI"); + + const Comptroller = await ethers.getContractFactory("Comptroller"); + const comptrollerBeacon = await upgrades.deployBeacon(Comptroller, { constructorArgs: [poolRegistry.address] }); + + const comptroller = await upgrades.deployBeaconProxy(comptrollerBeacon, Comptroller, [ + MAX_LOOP_LIMIT, + accessControlManager.address, + ]); + + const VTokenA = await makeVToken( + { + underlying: underlyingA, + comptroller, + accessControlManager, + admin, + interestRateModel, + protocolShareReserve, + isFlashLoanAllowed: true, + flashLoanProtocolFeeMantissa: protocolFeeMantissaTokenA, + flashLoanSupplierFeeMantissa: supplierFeeMantissaTokenA, + }, + { kind: "VTokenHarness" }, + ); + + const VTokenB = await makeVToken( + { + underlying: underlyingB, + comptroller, + accessControlManager, + admin, + interestRateModel, + protocolShareReserve, + isFlashLoanAllowed: true, + flashLoanProtocolFeeMantissa: protocolFeeMantissaTokenB, + flashLoanSupplierFeeMantissa: supplierFeeMantissaTokenB, + }, + { kind: "VTokenHarness" }, + ); + + await comptroller.setMarketSupplyCaps( + [VTokenA.address, VTokenB.address], + [convertToUnit(1, 50), convertToUnit(1, 50)], + ); + + await setBalance(poolRegistry.address, parseEther("1")); + await comptroller.connect(poolRegistry.wallet).supportMarket(VTokenA.address); + await comptroller.connect(poolRegistry.wallet).supportMarket(VTokenB.address); + + return { + accessControlManager, + protocolShareReserve, + interestRateModel, + poolRegistry, + comptroller, + underlyingA, + underlyingB, + VTokenA, + VTokenB, + }; +}; + +describe("FlashLoan", async () => { + let alice: SignerWithAddress; + let acmUser: SignerWithAddress; + let contracts: FlashLoanContractsFixture; + let VTokenA: VTokenHarness; + let VTokenB: VTokenHarness; + let underlyingA: MockContract; + let underlyingB: MockContract; + let comptroller: Comptroller; + let mockReceiverContract: MockFlashLoanReceiver; + let protocolShareReserveMock: FakeContract; + + beforeEach(async () => { + [alice, acmUser] = await ethers.getSigners(); + contracts = await loadFixture(flashLoanTestFixture); + ({ comptroller, VTokenA, VTokenB, underlyingA, underlyingB } = contracts); + }); + + describe("FlashLoan Multi-Assets", async () => { + beforeEach(async () => { + const MockFlashLoanReceiver = await ethers.getContractFactory( + "MockFlashLoanReceiver", + ); + mockReceiverContract = await MockFlashLoanReceiver.deploy(comptroller.address); + await mockReceiverContract.deployed(); + + protocolShareReserveMock = await smock.fake( + "contracts/InterfacesV8.sol:IProtocolShareReserve", + ); + protocolShareReserveMock.updateAssetsState.returns(true); + await VTokenA.setProtocolShareReserve(protocolShareReserveMock.address); + await VTokenB.setProtocolShareReserve(protocolShareReserveMock.address); + }); + + it("Should revert if flashLoan is not enabled", async () => { + await VTokenA.connect(acmUser).toggleFlashLoan(); + expect(await VTokenA.isFlashLoanEnabled()).to.be.false; + + await expect( + mockReceiverContract.requestFlashLoan( + [VTokenA.address.toString(), VTokenB.address.toString()], + [flashLoanAmount1, flashLoanAmount2], + "0x", + ), + ).to.be.revertedWithCustomError(comptroller, "FlashLoanNotEnabled"); + }); + + it("FlashLoan for multiple underlying", async () => { + // Admin Enable flashLoan for multiple vToken + expect(await VTokenA.isFlashLoanEnabled()).to.be.true; + expect(await VTokenB.isFlashLoanEnabled()).to.be.true; + + // Set the balance of mockReceiver in order to pay for flashLoan fee + await underlyingA.harnessSetBalance(mockReceiverContract.address, parseUnits("10", 18)); + await underlyingB.harnessSetBalance(mockReceiverContract.address, parseUnits("20", 18)); + + await underlyingA.harnessSetBalance(VTokenA.address, parseUnits("50", 18)); + await underlyingB.harnessSetBalance(VTokenB.address, parseUnits("50", 18)); + + // Get the balance before the flashLoan + const beforeBalanceVTokenA = await underlyingA.balanceOf(VTokenA.address); + const beforeBalanceVTokenB = await underlyingB.balanceOf(VTokenB.address); + const psrABalanceBefore = await underlyingA.balanceOf(protocolShareReserveMock.address); + const psrBBalanceBefore = await underlyingB.balanceOf(protocolShareReserveMock.address); + + // Execute the flashLoan from the mockReceiverContract + const flashLoan = await mockReceiverContract + .connect(alice) + .requestFlashLoan([VTokenA.address, VTokenB.address], [flashLoanAmount1, flashLoanAmount2], "0x"); + + // Get the balance after the flashLoan + const afterBalanceVTokenA = await underlyingA.balanceOf(VTokenA.address); + const afterBalanceVTokenB = await underlyingB.balanceOf(VTokenB.address); + + const protocolFeeA = flashLoanAmount1.mul(protocolFeeMantissaTokenA).div(parseUnits("1", 18)); + const supplierFeeA = flashLoanAmount1.mul(supplierFeeMantissaTokenA).div(parseUnits("1", 18)); + + const protocolFeeB = flashLoanAmount2.mul(protocolFeeMantissaTokenB).div(parseUnits("1", 18)); + const supplierFeeB = flashLoanAmount2.mul(supplierFeeMantissaTokenB).div(parseUnits("1", 18)); + + expect(afterBalanceVTokenA).to.be.equal(beforeBalanceVTokenA.add(supplierFeeA)); + expect(afterBalanceVTokenB).to.be.equal(beforeBalanceVTokenB.add(supplierFeeB)); + + expect(await underlyingA.balanceOf(protocolShareReserveMock.address)).to.equal( + psrABalanceBefore.add(protocolFeeA), + ); + expect(await underlyingB.balanceOf(protocolShareReserveMock.address)).to.equal( + psrBBalanceBefore.add(protocolFeeB), + ); + + await expect(flashLoan) + .to.emit(comptroller, "FlashLoanExecuted") + .withArgs( + mockReceiverContract.address, + [VTokenA.address, VTokenB.address], + [flashLoanAmount1, flashLoanAmount2], + ); + + expect(protocolShareReserveMock.updateAssetsState).to.have.been.calledWith( + comptroller.address, + underlyingA.address, + 2, + ); + + expect(protocolShareReserveMock.updateAssetsState).to.have.been.calledWith( + comptroller.address, + underlyingB.address, + 2, + ); + }); + }); +}); diff --git a/tests/hardhat/Comptroller/liquidateAccountTest.ts b/tests/hardhat/Comptroller/liquidateAccountTest.ts index 75fbd4f06..6bac7ea07 100644 --- a/tests/hardhat/Comptroller/liquidateAccountTest.ts +++ b/tests/hardhat/Comptroller/liquidateAccountTest.ts @@ -338,8 +338,9 @@ describe("liquidateAccount", () => { beforeLiquidation: { supply: 0, borrows: parseUnits("1", 18) }, afterLiquidation: { supply: 0, borrows: 0 }, }); - await expect(comptroller.connect(liquidator).liquidateAccount(user.address, [])).to.be.revertedWith( - "Nonzero borrow balance after liquidation", + await expect(comptroller.connect(liquidator).liquidateAccount(user.address, [])).to.be.revertedWithCustomError( + comptroller, + "NonzeroBorrowBalance", ); }); }); diff --git a/tests/hardhat/Comptroller/pauseTest.ts b/tests/hardhat/Comptroller/pauseTest.ts index f15875109..79879ad31 100644 --- a/tests/hardhat/Comptroller/pauseTest.ts +++ b/tests/hardhat/Comptroller/pauseTest.ts @@ -101,8 +101,9 @@ describe("Comptroller", () => { }); it("reverts if the market is not listed", async () => { - await expect(comptroller.setActionsPaused([SKT.address], [1], true)).to.be.revertedWith( - "cannot pause a market that is not listed", + await expect(comptroller.setActionsPaused([SKT.address], [1], true)).to.be.revertedWithCustomError( + comptroller, + "MarketNotExist", ); }); diff --git a/tests/hardhat/Comptroller/setters.ts b/tests/hardhat/Comptroller/setters.ts index e50da4007..af440a37e 100644 --- a/tests/hardhat/Comptroller/setters.ts +++ b/tests/hardhat/Comptroller/setters.ts @@ -105,8 +105,9 @@ describe("setters", async () => { it("reverts if re-adding same rewardDistributor", async () => { await comptroller.addRewardsDistributor(newRewardsDistributor.address); - await expect(comptroller.addRewardsDistributor(newRewardsDistributor.address)).to.be.revertedWith( - "already exists", + await expect(comptroller.addRewardsDistributor(newRewardsDistributor.address)).to.be.revertedWithCustomError( + comptroller, + "RewardsDistributorAlreadyExists", ); }); }); @@ -147,17 +148,24 @@ describe("setters", async () => { describe("SupplyAndBorrowCaps", async () => { it("reverts if token data is invalid", async () => { - await expect(comptroller.setMarketSupplyCaps([], [1, 2])).to.be.revertedWith("invalid number of markets"); + await expect(comptroller.setMarketSupplyCaps([], [1, 2])).to.be.revertedWithCustomError( + comptroller, + "InvalidInput", + ); }); it("reverts if supply and token data is invalid", async () => { - await expect(comptroller.setMarketSupplyCaps([OMG.address], [1, 2])).to.be.revertedWith( - "invalid number of markets", + await expect(comptroller.setMarketSupplyCaps([OMG.address], [1, 2])).to.be.revertedWithCustomError( + comptroller, + "InvalidInput", ); }); it("reverts if borrow and token data is invalid", async () => { - await expect(comptroller.setMarketBorrowCaps([OMG.address], [1, 2])).to.be.revertedWith("invalid input"); + await expect(comptroller.setMarketBorrowCaps([OMG.address], [1, 2])).to.be.revertedWithCustomError( + comptroller, + "InvalidInput", + ); }); }); diff --git a/tests/hardhat/Fork/constants.ts b/tests/hardhat/Fork/constants.ts index fd670589a..60e0a3304 100644 --- a/tests/hardhat/Fork/constants.ts +++ b/tests/hardhat/Fork/constants.ts @@ -181,7 +181,7 @@ export const contractAddresses = { ACC1: "0xc7f050b6F465b876c764A866d6337EabBab08Cd4", ACC2: "0xce0180B3B992649CBc3C8e1cF95b4A52Be9bA3AF", ACC3: "0x13E0a421c17Ff1e7FFccFa05714957cF530b3aa4", - BLOCK_NUMBER: 58181663, + BLOCK_NUMBER: 111100817, }, arbitrumone: { ADMIN: "0x14e0E151b33f9802b3e75b621c1457afc44DcAA0", diff --git a/tests/hardhat/Fork/flashloan.ts b/tests/hardhat/Fork/flashloan.ts new file mode 100644 index 000000000..25b6e2644 --- /dev/null +++ b/tests/hardhat/Fork/flashloan.ts @@ -0,0 +1,213 @@ +import { mine } from "@nomicfoundation/hardhat-network-helpers"; +import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; +import { expect } from "chai"; +import { parseUnits } from "ethers/lib/utils"; +import { ethers, network } from "hardhat"; + +import { getMaxBorrowRateMantissa } from "../../../helpers/deploymentConfig"; +import { getBlockOrTimestampBasedDeploymentInfo } from "../../../helpers/deploymentUtils"; +import { + AccessControlManager, + AccessControlManager__factory, + Comptroller, + Comptroller__factory, + ERC20, + ERC20__factory, + MockFlashLoanReceiver, + MockFlashLoanReceiver__factory, + UpgradeableBeacon__factory, + VToken, + VToken__factory, +} from "../../../typechain"; +import { getContractAddresses, initMainnetUser, setForkBlock } from "./utils"; + +const FORK = process.env.FORK === "true"; +const FORKED_NETWORK = process.env.FORKED_NETWORK || "bscmainnet"; +const { ACC2, TOKEN1, TOKEN2, VTOKEN2, ACM, VTOKEN1, POOL_REGISTRY, COMPTROLLER, TOKEN1_HOLDER, BLOCK_NUMBER, ADMIN } = + getContractAddresses(FORKED_NETWORK as string); + +const blocksToMine: number = 30000; + +const AddressZero = "0x0000000000000000000000000000000000000000"; +const WETH_HOLDER = "0xd7512902999b34af2B2940Eb8827CC8345DC77C6"; +const COMPTROLLER_BEACON = "0x12Dcb8D9F1eE7Ad7410F5B36B07bcC7891ab4cEf"; +const VTOKEN_BEACON = "0x74ae9919F5866cE148c81331a5FCdE71b81c4056"; +const { isTimeBased, blocksPerYear } = getBlockOrTimestampBasedDeploymentInfo(network.name); +const MAX_BORROW_RATE_MANTISSA = getMaxBorrowRateMantissa(network.name); + +const ARBFlashLoanProtocolFeeMantissa = parseUnits("0.01", 18); +const WETHFlashLoanProtocolFeeMantissa = parseUnits("0.03", 18); +const ARBFlashLoanSupplierFeeMantissa = parseUnits("0.01", 18); +const WETHFlashLoanSupplierFeeMantissa = parseUnits("0.03", 18); +const ARBFlashLoanAmount = parseUnits("50", 18); +const WETHFlashLoanAmount = parseUnits("20", 18); + +// Giving permission to Timelock to call chainlink setDirectPrice and setTokenConfig +async function grantPermissions() { + accessControlManager = AccessControlManager__factory.connect(ACM, impersonatedTimelock); + let tx = await accessControlManager + .connect(impersonatedTimelock) + .giveCallPermission(vARB.address, "toggleFlashLoan()", ADMIN); + await tx.wait(); + + tx = await accessControlManager + .connect(impersonatedTimelock) + .giveCallPermission(vARB.address, "setFlashLoanFeeMantissa(uint256, uint256)", ADMIN); + await tx.wait(); + + tx = await accessControlManager + .connect(impersonatedTimelock) + .giveCallPermission(vWETH.address, "toggleFlashLoan()", ADMIN); + await tx.wait(); + + tx = await accessControlManager + .connect(impersonatedTimelock) + .giveCallPermission(vWETH.address, "setFlashLoanFeeMantissa(uint256, uint256)", ADMIN); + await tx.wait(); +} + +let impersonatedTimelock: SignerWithAddress; +let john: SignerWithAddress; +let comptroller: Comptroller; +let arbHolder: SignerWithAddress; +let wETHHolder: SignerWithAddress; +let accessControlManager: AccessControlManager; +let ARB: ERC20; +let WETH: ERC20; +let vARB: VToken; +let vWETH: VToken; +let mockFlashLoanReceiver: MockFlashLoanReceiver; + +async function setup() { + await setForkBlock(BLOCK_NUMBER); + + impersonatedTimelock = await initMainnetUser(ADMIN, parseUnits("2")); + john = await initMainnetUser(ACC2, parseUnits("2")); + arbHolder = await initMainnetUser(TOKEN1_HOLDER, parseUnits("2")); + wETHHolder = await initMainnetUser(WETH_HOLDER, parseUnits("2")); + ARB = ERC20__factory.connect(TOKEN2, impersonatedTimelock); + WETH = ERC20__factory.connect(TOKEN1, impersonatedTimelock); + vARB = VToken__factory.connect(VTOKEN2, impersonatedTimelock); + vWETH = VToken__factory.connect(VTOKEN1, impersonatedTimelock); + comptroller = Comptroller__factory.connect(COMPTROLLER, impersonatedTimelock); + + // Deploy the comptroller and VToken + const Comptroller = await ethers.getContractFactory("Comptroller", impersonatedTimelock); + const upgradeComptrollerImpl = await Comptroller.deploy(POOL_REGISTRY); + await upgradeComptrollerImpl.deployed(); + + const VToken = await ethers.getContractFactory("VToken", impersonatedTimelock); + const upgradeVTokenImpl = await VToken.deploy(isTimeBased, blocksPerYear, MAX_BORROW_RATE_MANTISSA); + await upgradeVTokenImpl.deployed(); + + // Upgrade the comptroller implementation + const comptrollerBeacon = UpgradeableBeacon__factory.connect(COMPTROLLER_BEACON, impersonatedTimelock); + const vTokenBeacon = UpgradeableBeacon__factory.connect(VTOKEN_BEACON, impersonatedTimelock); + + await comptrollerBeacon.connect(impersonatedTimelock).upgradeTo(upgradeComptrollerImpl.address); + await vTokenBeacon.connect(impersonatedTimelock).upgradeTo(upgradeVTokenImpl.address); + + expect(await comptrollerBeacon.implementation()).to.be.equal(upgradeComptrollerImpl.address); + expect(await vTokenBeacon.implementation()).to.be.equal(upgradeVTokenImpl.address); + + await grantPermissions(); +} + +if (FORK) { + describe("FlashLoan Fork Test", async () => { + beforeEach(async () => { + // Run the setup function before each test to initialize the environment + await setup(); + + // Deploy a mock flashLoan receiver contract to simulate flashLoan interactions in tests + const MockFlashLoanReceiver = await ethers.getContractFactory( + "MockFlashLoanReceiver", + ); + mockFlashLoanReceiver = await MockFlashLoanReceiver.deploy(comptroller.address); + }); + + it("Should revert if flashLoan not enabled", async () => { + // Attempt to execute a flashLoan when the flashLoan feature is disabled, which should revert + await expect( + comptroller + .connect(john) + .executeFlashLoan( + mockFlashLoanReceiver.address, + [vARB.address, vWETH.address], + [ARBFlashLoanAmount, WETHFlashLoanAmount], + ), + ).to.be.revertedWithCustomError(vARB, "FlashLoanNotEnabled"); + }); + + it("Should revert if asset and amount arrays are mismatched", async () => { + // Attempt to execute a flashLoan with mismatched arrays for assets and amounts, which should revert + await expect( + comptroller.connect(john).executeFlashLoan( + mockFlashLoanReceiver.address, + [vARB.address], // Only one asset provided + [ARBFlashLoanAmount, WETHFlashLoanAmount], // Two loan amounts provided + ), + ).to.be.revertedWithCustomError(comptroller, "InvalidFlashLoanParams"); + }); + + it("Should revert if receiver is zero address", async () => { + // Attempt to execute a flashLoan with a zero address as the receiver, which should revert + await expect( + comptroller.connect(john).executeFlashLoan( + mockFlashLoanReceiver.address, + [AddressZero], // Zero address as an asset, which is invalid + [ARBFlashLoanAmount, WETHFlashLoanAmount], + ), + ).to.be.revertedWithCustomError(comptroller, "InvalidFlashLoanParams"); + }); + + it("Should be able to do flashLoan for ARB & WETH", async () => { + // Transfer ARB and WETH tokens to Alice to set up initial balances + await ARB.connect(arbHolder).transfer(vARB.address, parseUnits("100", 18)); + await ARB.connect(arbHolder).transfer(mockFlashLoanReceiver.address, parseUnits("10", 18)); + await WETH.connect(wETHHolder).transfer(vWETH.address, parseUnits("50", 18)); + await WETH.connect(wETHHolder).transfer(mockFlashLoanReceiver.address, parseUnits("5", 18)); + + // Mine blocks as required by the test setup + await mine(blocksToMine); + + const balanceBeforeARB = await ARB.balanceOf(vARB.address); + const balanceBeforeWETH = await WETH.balanceOf(vWETH.address); + + // Enable the flashLoan and set fee mantissa on vARB and vWETH contracts + await vARB.connect(impersonatedTimelock).toggleFlashLoan(); + await vWETH.connect(impersonatedTimelock).toggleFlashLoan(); + + await vARB + .connect(impersonatedTimelock) + .setFlashLoanFeeMantissa(ARBFlashLoanProtocolFeeMantissa, ARBFlashLoanSupplierFeeMantissa); + await vWETH + .connect(impersonatedTimelock) + .setFlashLoanFeeMantissa(WETHFlashLoanProtocolFeeMantissa, WETHFlashLoanSupplierFeeMantissa); + + // John initiates a flashLoan of ARB and WETH through the comptroller contract + await comptroller + .connect(john) + .executeFlashLoan( + mockFlashLoanReceiver.address, + [vARB.address, vWETH.address], + [ARBFlashLoanAmount, WETHFlashLoanAmount], + ); + + // Record ARB and WETH balances in vARB and vWETH contracts after flashLoan + const balanceAfterARB = await ARB.balanceOf(vARB.address); + const balanceAfterWETH = await WETH.balanceOf(vWETH.address); + + const ARBFlashLoanFee = ARBFlashLoanAmount.mul( + ARBFlashLoanProtocolFeeMantissa.add(ARBFlashLoanSupplierFeeMantissa), + ).div(parseUnits("1", 18)); + const WETHFlashLoanFee = WETHFlashLoanAmount.mul( + WETHFlashLoanProtocolFeeMantissa.add(WETHFlashLoanSupplierFeeMantissa), + ).div(parseUnits("1", 18)); + + // Validate that ARB and WETH balances in the contracts increased, confirming repayment plus fees + expect(balanceAfterARB).to.be.equal(balanceBeforeARB.add(ARBFlashLoanFee)); + expect(balanceAfterWETH).to.be.equal(balanceBeforeWETH.add(WETHFlashLoanFee)); + }); + }); +} diff --git a/tests/hardhat/Fork/flashloanSimple.ts b/tests/hardhat/Fork/flashloanSimple.ts new file mode 100644 index 000000000..1868b25a5 --- /dev/null +++ b/tests/hardhat/Fork/flashloanSimple.ts @@ -0,0 +1,158 @@ +import { smock } from "@defi-wonderland/smock"; +import { mine } from "@nomicfoundation/hardhat-network-helpers"; +import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; +import chai from "chai"; +import { parseUnits } from "ethers/lib/utils"; +import { ethers, network } from "hardhat"; + +import { getMaxBorrowRateMantissa } from "../../../helpers/deploymentConfig"; +import { getBlockOrTimestampBasedDeploymentInfo } from "../../../helpers/deploymentUtils"; +import { + AccessControlManager, + AccessControlManager__factory, + IERC20, + IERC20__factory, + MockFlashLoanSimpleReceiver, + MockFlashLoanSimpleReceiver__factory, + UpgradeableBeacon__factory, + VToken, + VToken__factory, +} from "../../../typechain"; +import { getContractAddresses, initMainnetUser, setForkBlock } from "./utils"; + +const { expect } = chai; +chai.use(smock.matchers); + +const blocksToMine: number = 30000; + +const FORK = process.env.FORK === "true"; +const FORKED_NETWORK = process.env.FORKED_NETWORK || "bscmainnet"; + +let john: SignerWithAddress; +let impersonatedTimelock: SignerWithAddress; +let ARB: IERC20; +let vARB: VToken; +let accessControlManager: AccessControlManager; +let arbHolder: SignerWithAddress; +let mockReceiverSimpleFlashLoan: MockFlashLoanSimpleReceiver; + +const AddressZero = "0x0000000000000000000000000000000000000000"; +const VTOKEN_BEACON_ARB = "0x74ae9919F5866cE148c81331a5FCdE71b81c4056"; +const { isTimeBased, blocksPerYear } = getBlockOrTimestampBasedDeploymentInfo(network.name); +const MAX_BORROW_RATE_MANTISSA = getMaxBorrowRateMantissa(network.name); + +const { VTOKEN2, ACM, ACC1, TOKEN2, ADMIN, BLOCK_NUMBER, TOKEN1_HOLDER } = getContractAddresses( + FORKED_NETWORK as string, +); + +const flashLoanProtocolFeeMantissa = parseUnits("0.01", 18); +const flashLoanSupplierFeeMantissa = parseUnits("0.01", 18); +const flashLoanAmount = parseUnits("100", 18); + +async function configureTimelock() { + impersonatedTimelock = await initMainnetUser(ADMIN, ethers.utils.parseUnits("2")); +} + +// Giving permission to Timelock to interact with the contracts +async function grantPermissions() { + accessControlManager = AccessControlManager__factory.connect(ACM, impersonatedTimelock); + let tx = await accessControlManager + .connect(impersonatedTimelock) + .giveCallPermission(vARB.address, "toggleFlashLoan()", ADMIN); + await tx.wait(); + + tx = await accessControlManager + .connect(impersonatedTimelock) + .giveCallPermission(vARB.address, "setFlashLoanFeeMantissa(uint256, uint256)", ADMIN); + await tx.wait(); +} + +if (FORK) { + describe("FlashLoan Fork Test", async () => { + async function setup() { + // Set the forked blockchain to a specific block number to create a consistent testing environment + await setForkBlock(BLOCK_NUMBER); + + // Configure the timelock address, typically the admin account, by funding it with tokens + await configureTimelock(); + + john = await initMainnetUser(ACC1, parseUnits("2", 18)); + arbHolder = await initMainnetUser(TOKEN1_HOLDER, parseUnits("2", 18)); + + ARB = IERC20__factory.connect(TOKEN2, impersonatedTimelock); + vARB = VToken__factory.connect(VTOKEN2, impersonatedTimelock); + + // Deploy a new VToken implementation to upgrade the current VToken contract + const VTOKEN_IMPL = await ethers.getContractFactory("VToken", impersonatedTimelock); + const upgradeImpl = await VTOKEN_IMPL.deploy(isTimeBased, blocksPerYear, MAX_BORROW_RATE_MANTISSA); + await upgradeImpl.deployed(); + + // Connect to the upgradeable beacon managing VToken implementations for ARB and upgrade it + const beaconVToken = UpgradeableBeacon__factory.connect(VTOKEN_BEACON_ARB, impersonatedTimelock); + await beaconVToken.connect(impersonatedTimelock).upgradeTo(upgradeImpl.address); + + expect(await beaconVToken.callStatic.implementation()).to.be.equal(upgradeImpl.address); + + // Grant necessary permissions to users or contracts + await grantPermissions(); + } + + beforeEach(async () => { + // Run setup before each test to reset the environment + await setup(); + + // Deploy a mock flashLoan receiver to test flashLoan functionality + const MockFlashLoanSimpleReceiver = await ethers.getContractFactory( + "MockFlashLoanSimpleReceiver", + ); + mockReceiverSimpleFlashLoan = await MockFlashLoanSimpleReceiver.deploy(vARB.address); + }); + + it("Should revert if flashLoan not enabled", async () => { + // Attempt to take a flashLoan when the flashLoan feature is disabled should fail + await expect( + vARB.connect(john).executeFlashLoan(mockReceiverSimpleFlashLoan.address, flashLoanAmount), + ).to.be.revertedWithCustomError(vARB, "FlashLoanNotEnabled"); + }); + + it("Should revert if receiver is zero address", async () => { + // Enable flashLoan feature for testing + await vARB.connect(impersonatedTimelock).toggleFlashLoan(); + + // Attempt to take a flashLoan with zero address as receiver should fail + await expect(vARB.connect(john).executeFlashLoan(AddressZero, flashLoanAmount)).to.be.revertedWithCustomError( + vARB, + "ZeroAddressNotAllowed", + ); + }); + + it("Should flashLoan ARB", async () => { + // Transfer ARB tokens to test users for setting up the flashLoan test + await ARB.connect(arbHolder).transfer(vARB.address, parseUnits("1000", 18)); + await ARB.connect(arbHolder).transfer(mockReceiverSimpleFlashLoan.address, parseUnits("50", 18)); + + // Record vARB contract's ARB balance before flashLoan + const balanceBefore = await ARB.balanceOf(vARB.address); + + // Mine blocks if necessary for time-based operations + await mine(blocksToMine); + + // Enable flashLoan feature by the admin + await vARB.connect(impersonatedTimelock).toggleFlashLoan(); + await vARB + .connect(impersonatedTimelock) + .setFlashLoanFeeMantissa(flashLoanProtocolFeeMantissa, flashLoanSupplierFeeMantissa); + + // John initiates a flashLoan of 2000 ARB through the mock receiver + await vARB.connect(john).executeFlashLoan(mockReceiverSimpleFlashLoan.address, parseUnits("100", 18)); + + // Check if the ARB balance in vARB increased, validating flashLoan repayment with fees + const balanceAfter = await ARB.balanceOf(vARB.address); + const totalFlashLoanFee = flashLoanAmount + .mul(flashLoanProtocolFeeMantissa.add(flashLoanSupplierFeeMantissa)) + .div(parseUnits("1", 18)); + + expect(balanceAfter).to.be.equal(balanceBefore.add(totalFlashLoanFee)); + }); + }); +} diff --git a/tests/hardhat/Tokens/flashLoanSimple.ts b/tests/hardhat/Tokens/flashLoanSimple.ts new file mode 100644 index 000000000..23d60b33b --- /dev/null +++ b/tests/hardhat/Tokens/flashLoanSimple.ts @@ -0,0 +1,191 @@ +import { FakeContract, MockContract, smock } from "@defi-wonderland/smock"; +import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; +import chai from "chai"; +import { BigNumber } from "ethers"; +import { parseUnits } from "ethers/lib/utils"; +import { ethers } from "hardhat"; +import { SignerWithAddress } from "hardhat-deploy-ethers/signers"; + +import { + AccessControlManager, + Comptroller, + ERC20Harness, + IProtocolShareReserve, + MockFlashLoanSimpleReceiver, + MockFlashLoanSimpleReceiver__factory, + VTokenHarness, +} from "../../../typechain"; +import { initMainnetUser } from "../Fork/utils"; +import { VTokenTestFixture, vTokenTestFixture } from "../util/TokenTestHelpers"; + +const { expect } = chai; +chai.use(smock.matchers); + +const flashLoanAmount = parseUnits("2", 18).toBigInt(); +const protocolFeeMantissa = parseUnits("0.01", 18); +const supplierFeeMantissa = parseUnits("0.01", 18); + +describe("FlashLoan Simple", () => { + let minter: SignerWithAddress; + let alice: SignerWithAddress; + let receiver: SignerWithAddress; + let acmUser: SignerWithAddress; + let contracts: VTokenTestFixture; + let underlying: MockContract; + let vToken: VTokenHarness; + let mockReceiverSimple: MockFlashLoanSimpleReceiver; + let accessControlManager: FakeContract; + let comptroller: FakeContract; + let comptrollerSigner: SignerWithAddress; + let protocolShareReserveMock: FakeContract; + + beforeEach(async () => { + [minter, alice, acmUser, receiver] = await ethers.getSigners(); + contracts = await loadFixture(vTokenTestFixture); + ({ vToken, underlying, accessControlManager, comptroller } = contracts); + comptrollerSigner = await initMainnetUser(comptroller.address, ethers.utils.parseUnits("2")); + + protocolShareReserveMock = await smock.fake( + "contracts/InterfacesV8.sol:IProtocolShareReserve", + ); + protocolShareReserveMock.updateAssetsState.returns(true); + + await vToken.setProtocolShareReserve(protocolShareReserveMock.address); + }); + + describe("Enable/disable flash loan feature", () => { + it("Should have access to toggle flash loan feature", async () => { + accessControlManager.isAllowedToCall.returns(false); + + expect(await vToken.isFlashLoanEnabled()).to.be.false; + await expect(vToken.connect(acmUser).toggleFlashLoan()).to.be.revertedWithCustomError(vToken, "Unauthorized"); + expect(await vToken.isFlashLoanEnabled()).to.be.false; + }); + + it("Enable flashLoan feature", async () => { + accessControlManager.isAllowedToCall.returns(true); + + expect(await vToken.isFlashLoanEnabled()).to.be.false; + await vToken.connect(acmUser).toggleFlashLoan(); + expect(await vToken.isFlashLoanEnabled()).to.be.true; + }); + + it("Disable flashLoan feature", async () => { + expect(await vToken.isFlashLoanEnabled()).to.be.false; + await vToken.connect(acmUser).toggleFlashLoan(); + expect(await vToken.isFlashLoanEnabled()).to.be.true; + + await vToken.connect(acmUser).toggleFlashLoan(); + expect(await vToken.isFlashLoanEnabled()).to.be.false; + }); + + it("Emit ToggleFlashLoanEnabled event on toggle flashLoan feature", async () => { + let result = await vToken.connect(acmUser).toggleFlashLoan(); + await expect(result).to.emit(vToken, "ToggleFlashLoanEnabled").withArgs(false, true); + + result = await vToken.connect(acmUser).toggleFlashLoan(); + await expect(result).to.emit(vToken, "ToggleFlashLoanEnabled").withArgs(true, false); + }); + }); + + describe("Set fee on flashLoan", () => { + it("Should have access to set fee on flashLoan", async () => { + accessControlManager.isAllowedToCall.returns(false); + + await expect( + vToken.connect(acmUser).setFlashLoanFeeMantissa(protocolFeeMantissa, supplierFeeMantissa), + ).to.be.revertedWithCustomError(vToken, "Unauthorized"); + }); + + it("Set fee on flashLoan", async () => { + accessControlManager.isAllowedToCall.returns(true); + + await vToken.connect(acmUser).setFlashLoanFeeMantissa(protocolFeeMantissa, supplierFeeMantissa); + expect(await vToken.flashLoanProtocolFeeMantissa()).to.be.equal(protocolFeeMantissa); + expect(await vToken.flashLoanSupplierFeeMantissa()).to.be.equal(supplierFeeMantissa); + }); + + it("Emit FlashLoanFeeUpdated event on set fee on flashLoan", async () => { + const result = await vToken.connect(acmUser).setFlashLoanFeeMantissa(protocolFeeMantissa, supplierFeeMantissa); + await expect(result) + .to.emit(vToken, "FlashLoanFeeUpdated") + .withArgs(0, protocolFeeMantissa, 0, supplierFeeMantissa); + }); + }); + + describe("Transfer underlying assets to receiver contract", () => { + beforeEach(async () => { + await underlying.harnessSetBalance(vToken.address, parseUnits("1", 18)); + }); + + it("Revert if not comptroller", async () => { + await expect( + vToken.connect(acmUser).transferOutUnderlying(minter.address, parseUnits("1", 18)), + ).to.be.revertedWithCustomError(vToken, "InvalidComptroller"); + }); + + it("Only comptroller can transfer underlying assets to receiver contract", async () => { + await vToken.connect(comptrollerSigner).transferOutUnderlying(minter.address, parseUnits("1", 18)); + expect(await underlying.balanceOf(minter.address)).to.be.equal(parseUnits("1", 18)); + }); + + it("Emit TransferUnderlying event on transfer underlying assets to receiver contract", async () => { + const result = await vToken + .connect(comptrollerSigner) + .transferOutUnderlying(receiver.address, parseUnits("1", 18)); + await expect(result) + .to.emit(vToken, "TransferOutUnderlying") + .withArgs(underlying.address, receiver.address, parseUnits("1", 18)); + }); + }); + + describe("FlashLoan Single Asset", () => { + beforeEach(async () => { + const MockFlashLoanSimpleReceiver = await ethers.getContractFactory( + "MockFlashLoanSimpleReceiver", + ); + mockReceiverSimple = await MockFlashLoanSimpleReceiver.deploy(vToken.address); + await mockReceiverSimple.deployed(); + + await vToken.connect(acmUser).setFlashLoanFeeMantissa(protocolFeeMantissa, supplierFeeMantissa); + await underlying.harnessSetBalance(mockReceiverSimple.address, parseUnits("1", 18)); + await underlying.harnessSetBalance(vToken.address, parseUnits("10", 18)); + }); + + it("Should revert if the flashLoan is not enabled", async () => { + await expect(mockReceiverSimple.requestFlashLoan(flashLoanAmount, "0x")).to.be.revertedWithCustomError( + vToken, + "FlashLoanNotEnabled", + ); + }); + + it("FlashLoan for single underlying", async () => { + await vToken.connect(acmUser).toggleFlashLoan(); + + const vTokenBalanceBefore = await underlying.balanceOf(vToken.address); + const psrBalanceBefore = await underlying.balanceOf(protocolShareReserveMock.address); + + const flashLoan = await mockReceiverSimple.connect(alice).requestFlashLoan(flashLoanAmount, "0x"); + + const vTokenBalanceAfter = await underlying.balanceOf(vToken.address); + const psrBalanceAfter = await underlying.balanceOf(protocolShareReserveMock.address); + + const protocolFee = BigNumber.from(flashLoanAmount).mul(protocolFeeMantissa).div(parseUnits("1", 18)); + const supplierFee = BigNumber.from(flashLoanAmount).mul(supplierFeeMantissa).div(parseUnits("1", 18)); + + expect(vTokenBalanceAfter).to.be.equal(vTokenBalanceBefore.add(supplierFee)); + + expect(psrBalanceAfter).to.equal(psrBalanceBefore.add(protocolFee)); + + await expect(flashLoan) + .to.emit(vToken, "FlashLoanExecuted") + .withArgs(mockReceiverSimple.address, underlying.address, flashLoanAmount); + + expect(protocolShareReserveMock.updateAssetsState).to.have.been.calledWith( + comptroller.address, + underlying.address, + 2, + ); + }); + }); +}); diff --git a/tests/hardhat/util/TokenTestHelpers.ts b/tests/hardhat/util/TokenTestHelpers.ts index 93923292f..7fbd95513 100644 --- a/tests/hardhat/util/TokenTestHelpers.ts +++ b/tests/hardhat/util/TokenTestHelpers.ts @@ -38,6 +38,9 @@ interface VTokenParameters { isTimeBased: boolean; blocksPerYear: BigNumberish; maxBorrowRateMantissa: BigNumberish; + isFlashLoanAllowed: boolean; + flashLoanProtocolFeeMantissa: BigNumberish; + flashLoanSupplierFeeMantissa: BigNumberish; } const getNameAndSymbol = async (underlying: AddressOrContract): Promise<[string, string]> => { @@ -110,6 +113,9 @@ const deployVTokenDependencies = async ( @@ -146,6 +152,9 @@ export const makeVToken = async ; return vToken; diff --git a/tests/integration/index.ts b/tests/integration/index.ts index aa8e75e0f..52bda3ec0 100644 --- a/tests/integration/index.ts +++ b/tests/integration/index.ts @@ -484,8 +484,9 @@ describe("Straight Cases For Single User Liquidation and healing", function () { dummyPriceOracle.getUnderlyingPrice.whenCalledWith(vBNX.address).returns(convertToUnit("100", 12)); dummyPriceOracle.getUnderlyingPrice.whenCalledWith(vBTCB.address).returns(convertToUnit("100", 12)); await Comptroller.setPriceOracle(dummyPriceOracle.address); - await expect(Comptroller.connect(acc1Signer).liquidateAccount(acc2, [param])).to.be.revertedWith( - "Nonzero borrow balance after liquidation", + await expect(Comptroller.connect(acc1Signer).liquidateAccount(acc2, [param])).to.be.revertedWithCustomError( + Comptroller, + "NonzeroBorrowBalance", ); });